This cannot work:
let a () =
async {
return 0
}
let b x =
async {
return
match x with
| true ->
let! y = a() <- you can't compile this
y
| false ->
0
}
I understand I could do this:
let b x =
async {
match x with
| true ->
return! a()
| false ->
return 0
}
but there are cases where I need a:
let! y = a()
to do more operations with the result.
Is there an elegant way to achieve this?
Can't you combine the two?
let b x =
async {
match x with
| true ->
let! y = a()
return y
| false ->
return 0
}
You can move the async expression inside each case:
let b x =
match x with
| true -> async {
let! y = a ()
...
return y
}
| false -> async { return 0 }
I don't know if you think this is more elegant, but more functions usually makes it look a bit nicer, here's an example:
module Async =
let create v = async { return v }
let bind f a = async.Bind (a, f)
let map f a =
bind (f >> create) a
let a () = Async.create 0
let addOne y =
y + 1
let b x =
match x with
| true -> a () |> Async.map addOne
| false -> Async.create 0
// Additional piping to map or bind if you wish, e.g:
// |> Async.bind ...
You can do the return inside the match.
let a () = async {
return 0
}
let b x = async {
match x with
| true -> return! a()
| false -> return 0
}
Otherwise you can do this:
module Async =
let create x = async { return x }
let a () = async {
return 10
}
let b x = async {
let! x1 =
match x with
| true -> a()
| false -> async { return 0 }
let! x2 =
if x then a() else Async.create 0
// Do whatever with x1 or x2
return x2
}
Create a function for code that occur often:
let whatever b a x =
if x then a() else Async.create x
let! y = whatever b a 0
Related
If I am using reference tuples, this compiles:
let plot(x: int, y: int) = ()
let point = 3, 4
plot(fst point, snd point)
However, if I am using struct tuples...
let plot(x: int, y: int) = ()
let point = struct (3, 4)
plot(fst point, snd point)
... I get the compiler error, One tuple type is a struct tuple, the other is a reference tuple
What should I do?
There's a ToTuple() extension method in System.TupleExtensions for ValueTuple<T1, T2...>.
You could just call:
plot (point.ToTuple())
As for fst, snd, they're bound to System.Tuple<>, so maybe you could define an alternative:
let fstv struct (a,_) = a
let sndv struct (_,b) = b
In F# 4.7, you must add another line to decompose the tuple.
let plot(x: int, y: int) = ()
let point = struct (3, 4)
let struct (x, y) = point
plot(x, y)
You can declare new functions that work on struct tuples:
let fstv (struct (a, _)) = a
let sndv (struct (_, b)) = b
Usage:
let plot(x: int, y: int) = ()
let point = struct (3, 4)
plot(fstv point, sndv point)
If you want to get clever, you can use SRTP to make new fst and snd functions that work with both struct tuples and regular tuples:
type PairDispatcher =
| PairDispatcher with
static member inline ($) (PairDispatcher, (a, b)) = fun f -> f a b
static member inline ($) (PairDispatcher, struct (a, b)) = fun f -> f a b
let inline fst x = (PairDispatcher $ x) (fun a _ -> a)
let inline snd x = (PairDispatcher $ x) (fun _ b -> b)
(Taken from http://www.fssnip.net/7TT/title/Generic-fst-and-snd-functions)
Then usage is:
let plot(x: int, y: int) = ()
let point = struct (3, 4)
plot(fst point, snd point)
I think on balance I would prefer to declare new functions.
I've implemented my own version of a singly linked list in Rust as one of the challenges for me to learn it, and I'm satisfied with everything I have there except for the .pop() method. Using 2 while loops is very ugly and inefficient, but I found no other way to overcome the problem of setting the node at the index len() - 2 to None (popping the list), and using the data from the node at the index len() - 1 for the Some(data) return value (returns the element that was popped).
GitHub Link
pub struct SimpleLinkedList<T> {
head: Option<Box<Node<T>>>,
}
struct Node<T> {
data: T,
next: Option<Box<Node<T>>>,
}
impl<T> Default for SimpleLinkedList<T> {
fn default() -> Self {
SimpleLinkedList { head: None }
}
}
impl<T: Copy> Clone for SimpleLinkedList<T> {
fn clone(&self) -> SimpleLinkedList<T> {
let mut out: SimpleLinkedList<T> = SimpleLinkedList::new();
let mut cur = &self.head;
while let Some(node) = cur {
cur = &node.next;
out.push(node.data)
}
out
}
}
impl<T> SimpleLinkedList<T> {
pub fn new() -> Self {
Default::default()
}
pub fn len(&self) -> usize {
let mut c = 0;
let mut cur = &self.head;
while let Some(node) = cur {
cur = &node.next;
c += 1;
}
c
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn push(&mut self, _element: T) {
let mut cur = &mut self.head;
match cur {
Some(_) => {
while let Some(node) = cur {
cur = &mut node.next;
}
}
None => (),
}
*cur = Some(Box::from(Node {
data: _element,
next: None,
}));
}
pub fn pop(&mut self) -> Option<T>
where
T: Copy,
{
let length = &self.len();
let mut cur = &mut self.head;
let mut out = None;
match cur {
Some(_) if *length > 1usize => {
let mut c = 0usize;
while let Some(node) = cur {
cur = &mut node.next;
if c >= length - 1 {
out = Some(node.data);
break;
}
c += 1;
}
c = 0usize;
cur = &mut self.head;
while let Some(node) = cur {
cur = &mut node.next;
if c == length - 2 {
break;
}
c += 1;
}
}
Some(node) => out = Some(node.data),
None => (),
}
*cur = None;
out
}
pub fn peek(&self) -> Option<&T> {
let cur = &self.head;
match cur {
Some(node) => Some(&node.data),
None => None,
}
}
}
impl<T: Copy> SimpleLinkedList<T> {
pub fn rev(&self) -> SimpleLinkedList<T> {
let mut clone = self.clone();
let mut out: SimpleLinkedList<T> = SimpleLinkedList::new();
while let Some(val) = clone.pop() {
out.push(val)
}
out
}
}
impl<'a, T: Copy> From<&'a [T]> for SimpleLinkedList<T> {
fn from(_item: &[T]) -> Self {
let mut out: SimpleLinkedList<T> = SimpleLinkedList::new();
for &e in _item.iter() {
out.push(e);
}
out
}
}
impl<T> Into<Vec<T>> for SimpleLinkedList<T> {
fn into(self) -> Vec<T> {
let mut out: Vec<T> = Vec::new();
let mut cur = self.head;
while let Some(node) = cur {
cur = node.next;
out.push(node.data)
}
out
}
}
You can avoid re-traversing the list by keeping track of the last element you saw as you go (and then updating that at the end).
If you are naive about how you do that, you will run into trouble; your "previous" pointer retains ownership of the rest of the list and the borrow checker won't allow that. The trick is to break that link as you go - and to do that you can use the mem::replace function. Once you've done that, you have to put it back before you lose track of your previous node again.
Here's what that could look like in full (you'll have to forgive my liberal use of unwrap - I do think it makes things clearer):
pub fn pop(&mut self) -> Option<T>
where T : Copy,
{
use std::mem::replace;
let curr = replace(&mut self.head, None);
if curr.is_none() { // list started off empty; nothing to pop
return None;
}
let mut curr = curr.unwrap(); // safe because of the check above
if let None = curr.next { // popped the last element
return Some(curr.data);
}
let mut prev_next = &mut self.head;
while curr.next.is_some() {
// Take ownership of the next element
let nnext = replace(&mut curr.next, None).unwrap();
// Update the previous element's "next" field
*prev_next = Some(curr);
// Progress to the next element
curr = nnext;
// Progress our pointer to the previous element's "next" field
prev_next = &mut prev_next.as_mut().unwrap().next;
}
return Some(curr.data);
}
As an aside, all this pointer shuffling simplifies a lot if you're willing to change the interface a little so that we return a "new" list each time (taking ownership in the pop function), or use a persistent datastructure, as they do in Learning Rust with entirely too many linked lists (already mentioned in a comment):
pub fn pop_replace(self) -> (Option<T>, Self) {
// freely mutate self and all the nodes
}
Which you would use like:
let elem, list = list.pop();
inspired from here
fn pop(&mut self) -> Option<T> {
let mut current: &mut Option<Box<Node<T>>> = &mut self.head;
loop {
// println!("curr: {:?}", current);
match current {
None => {
return None;
}
Some(node) if node.next.is_none() => {
let val = node.data;
*current = node.next.take();
return Some(val);
}
Some(ref mut node) => {
current = &mut node.next;
}
}
}
}
I want to define the expected data type of the elements of a tuple which will be passed to call a function. When I don't define it and let the type inference work it is ok, but in the moment I want to write small functions that are still not called anywhere I don't get how to define the arguments.
This example. I expect description to be a tuple where every of the five elements is a int and then extract each of the parts to work with then.
let setArray (description: int * int * int * int * int) =
let id = fun (i, _, _, _, _) -> i
let startX = fun (_, x, _, _, _) -> x
let startY = fun (_, _, y, _, _) -> y
let width = fun (_, _, _, w, _) -> w
let height = fun (_, _, _, _, h) -> h
let arrayResult = Array2D.init (width + 1) (height + 1) (fun i j -> if i < width && j < height then id)
arrayResult
.fsx(29,45): error FS0001: The type 'int' does not match the type ''a * 'b * 'c * 'd * 'e -> 'd'
For other functions, like I said, type inference works and I can use the pattern matching without problem
let getMaxCoords =
let x = elements |> Seq.map (fun (_, x, _, _, _) -> x) |> Seq.max
let y = elements |> Seq.map (fun (_, _, y, _, _) -> x) |> Seq.max
x, y
What am I doing wrong?
First, the following code block is defining five functions, not five integer values:
let setArray (description: int * int * int * int * int) =
let id = fun (i, _, _, _, _) -> i
let startX = fun (_, x, _, _, _) -> x
let startY = fun (_, _, y, _, _) -> y
let width = fun (_, _, _, w, _) -> w
let height = fun (_, _, _, _, h) -> h
What you probably meant to do is to pass the description tuple into each of these destructuring functions, like so:
let setArray (description: int * int * int * int * int) =
let id = description |> (fun (i, _, _, _, _) -> i)
let startX = description |> (fun (_, x, _, _, _) -> x)
let startY = description |> (fun (_, _, y, _, _) -> y)
let width = description |> (fun (_, _, _, w, _) -> w)
let height = description |> (fun (_, _, _, _, h) -> h)
But there's a much easier way to do this. F# lets you destructure a tuple in the function signature. So you can replace that whole code block with the following:
let setArray (id, startX, startY, width, height) =
That's it! So now your entire function looks like:
let setArray (id, startX, startY, width, height) =
let arrayResult = Array2D.init (width + 1) (height + 1) (fun i j -> if i < width && j < height then id)
arrayresult
And there's one more simplification you can make. Any time you have let x = (some calculation) followed immediately by x as the function's return value, you can get rid of that let and just have the function return (some calculation). Applying that simplification, your function becomes:
let setArray (id, startX, startY, width, height) =
Array2D.init (width + 1) (height + 1) (fun i j -> if i < width && j < height then id)
And you're done! If you really want to specify that id, startX, etc., are all integers, you can do it like this:
let setArray (id : int, startX : int, startY : int, width : int, height : int) =
Array2D.init (width + 1) (height + 1) (fun i j -> if i < width && j < height then id)
What's the difference between my actual union case value and the expected value?
I have the following test:
[<Test>]
let ``black checker jumps to king``() =
let redChecker = { RedChecker.Position= { X=1 ; Y=6 } }
let target = (redChecker, [redChecker])
{ BlackChecker.Position= { X=0 ; Y=5 } } |> jumpRed target
|> fst
|> should equal (BlackKing { BlackKing.Position= { X=2 ; Y=7 } })
Here's the actual result when executing the test operation in the interactive window:
val redChecker : RedChecker = {Position = {X = 1;
Y = 6;};}
val target : RedChecker * RedChecker list =
({Position = {X = 1;
Y = 6;};}, [{Position = {X = 1;
Y = 6;};}])
val it : Checker = BlackKing {Position = {X = 2;
Y = 7;};}
I see that a BlackKing value is returned with xy being (2,7). Thus, I'm verifying in my test that union case value with that specific xy value.
I'm just not seeing why my test is failing.
Any suggestions?
Appendix:
open NUnit.Framework
open FsUnit
(* Types *)
type North = NorthEast | NorthWest
type South = SouthEast | SouthWest
type Direction =
| NorthEast
| NorthWest
| SouthEast
| SouthWest
type Position = { X:int; Y:int }
type BlackChecker = { Position:Position }
type RedChecker = { Position:Position }
type BlackKing = { Position:Position }
type RedKing = { Position:Position }
type Checker =
| BlackChecker of BlackChecker
| RedChecker of RedChecker
| BlackKing of BlackKing
| RedKing of RedKing
type King =
| BlackKing of BlackKing
| RedKing of RedKing
(* Functions *)
let rec remove item list = list |> List.filter (fun x -> x <> item)
let setRowPosition y1 y2 y3 index =
match index with
| x when x < 4 -> { X=x; Y=y1 }
| x when x < 8 -> { X=x-4; Y=y2 }
| _ -> { X=index-8; Y=y3 }
let initializeBlack () =
let setPosition index =
index |> setRowPosition 7 6 5
let blackCheckers = List.init 12 setPosition |> List.map (fun pos -> { BlackChecker.Position= { X=pos.X; Y=pos.Y } })
blackCheckers
let initializeRed () =
let setPosition index =
index |> setRowPosition 0 1 2
let redCheckers = List.init 12 setPosition |> List.map (fun pos -> { RedChecker.Position= { X=pos.X; Y=pos.Y } })
redCheckers
let set (x, y) positions (position:Position) =
match not (positions |> List.exists (fun pos -> pos = { X=x; Y=y })) with
| true -> { X=x; Y=y }
| false -> position
let moveBlack direction positions (checker:BlackChecker) =
let position = checker.Position
match direction with
| North.NorthEast -> { BlackChecker.Position= (positions, position) ||> set ((position.X + 1), (position.Y + 1 )) }
| North.NorthWest -> { BlackChecker.Position= (positions, position) ||> set ((position.X - 1), (position.Y + 1 )) }
let moveRed direction positions (checker:RedChecker) =
let position = checker.Position
match direction with
| South.SouthEast -> { RedChecker.Position= (positions, position) ||> set ((position.X + 1), (position.Y - 1 )) }
| South.SouthWest -> { RedChecker.Position= (positions, position) ||> set ((position.X - 1), (position.Y - 1 )) }
let moveKing direction positions (king:King) =
let position = match king with
| BlackKing bk -> bk.Position
| RedKing rk -> rk.Position
let result = match direction with
| NorthEast -> (positions, position) ||> set ((position.X + 1), (position.Y + 1 ))
| NorthWest -> (positions, position) ||> set ((position.X - 1), (position.Y + 1 ))
| SouthEast -> (positions, position) ||> set ((position.X + 1), (position.Y - 1 ))
| SouthWest -> (positions, position) ||> set ((position.X - 1), (position.Y - 1 ))
match king with
| BlackKing _ -> BlackKing { BlackKing.Position= result }
| RedKing _ -> RedKing { RedKing.Position= result }
let jump target yDirection source =
let updateX value = { X=target.X + value
Y=target.Y + yDirection }
match source with
| position when position.Y + yDirection = target.Y &&
position.X + 1 = target.X -> updateX 1
| position when position.Y + yDirection = target.Y &&
position.X - 1 = target.X -> updateX -1
| _ -> source
let jumpRed ((redChecker:RedChecker), (redCheckers:RedChecker list)) (blackChecker:BlackChecker) =
let yIncrementValue = 1
let maxY = 7
let position = blackChecker.Position |> jump redChecker.Position yIncrementValue
match position with
| pos when pos = blackChecker.Position -> BlackChecker { blackChecker with Position= position }, redCheckers
| pos when pos.Y = maxY -> Checker.BlackKing { BlackKing.Position=position }, redCheckers |> remove redChecker
| _ -> BlackChecker { blackChecker with Position= position }, redCheckers |> remove redChecker
let jumpBlack ((blackChecker:BlackChecker),(blackCheckers:BlackChecker list)) (redChecker:RedChecker) =
let yIncrementValue = -1
let minY = 0
let position = redChecker.Position |> jump blackChecker.Position yIncrementValue
match position with
| pos when pos = redChecker.Position -> RedChecker { redChecker with Position= position }, blackCheckers
| pos when pos.Y = minY -> Checker.RedKing { RedKing.Position=position }, blackCheckers |> remove blackChecker
| _ -> RedChecker { redChecker with Position= position }, blackCheckers |> remove blackChecker
Well this statement
{ BlackChecker.Position= { X=0 ; Y=5 } } |> jumpRed target
|> fst
gives:
val it : Checker = BlackKing {Position = {X = 2;
Y = 7;};}
It is of type Checker. On the other hand:
(BlackKing { BlackKing.Position= { X=2 ; Y=7 } })
gives:
val it : King = BlackKing {Position = {X = 2;
Y = 7;};}
It is of type King. They aren't the same types...
If you want to compare them you need to unwrap the BlackKing type inside the things you want to compare via pattern matching.
I have been working on a function for reducing fractions in Swift, and came across the Euclidean algorithm for finding the greatest common factor (http://en.wikipedia.org/wiki/Euclidean_algorithm)
I converted the pseudo code into swift, but yet I am confused how this is going to give me the greatest common factor if it is returning a which I thought was supposed to be the numerator of the fraction. Any help on this would be greatly appreciated. Thanks!
Pseudocode:
function gcd(a, b)
while b ≠ 0
t := b
b := a mod b
a := t
return a
Swift:
var a = 2
var b = 4
func gcd(a: Int, b: Int) -> Int {
var t = 0
while b != 0 {
t = b
let b = a % b
let a = t
}
return a
}
println("\(a)/\(b)")
Console output: 2/4
When you do this
let b = a % b
you are creating another readonly variable b, which has nothing to do with the variable b from the outside scope. You need to remove both lets inside the loop, and make parameters modifiable by declaring them with var, like this:
func gcd(var a: Int, var b: Int) -> Int {
var t = 0
while b != 0 {
t = b
b = a % b
a = t
}
return a
}
You can call your function like this:
let a = 111
let b = 259
println("a=\(a), b=\(b), gcd=\(gcd(a,b))")
This prints a=111, b=259, gcd=37
Taking #dasblinkenlight's answer and getting rid of t by using tuples for parallel assignment yields:
Swift 2.1:
func gcd(var a: Int, var _ b: Int) -> Int {
while b != 0 {
(a, b) = (b, a % b)
}
return a
}
gcd(1001, 39) // 13
var parameters are deprecated in Swift 2.2 and will be removed in Swift 3. So now it becomes necessary to declare a and b as var within the function:
func gcd(a: Int, _ b: Int) -> Int {
var (a, b) = (a, b)
while b != 0 {
(a, b) = (b, a % b)
}
return a
}
Swift 3 version of answer given by Christopher Larsen
func gcd(a: Int, b: Int) -> Int {
if b == 0 { return a }
return gcd(a: b, b: a % b)
}
Can use a recursive method that just keeps calling itself until the GCD is found.
func gcd(a: Int, b: Int) -> Int {
if b == 0 {
return a
}
let remainder: Int = a % b
return gcd(b, b: remainder)
}
and use like so
let gcdOfSomeNums = gcd(28851538, b: 1183019)
//gcdOfSomeNums is 17657