Reputation: 21727
I wish I could do:
let myFun param1 param2 =
.....
if condition 1
....
if condition 2
yield ....
let sequence = seq { for x in xs do
myFun 1 x
myFun 2 x
}
But now I can only do
let myFun param =
.....
.....
if condition 1
....
if condition 2
Some....
else None // has to complete else
else None
let sequence = seq { for x in xs do
match myFun 1 x with
| Some x -> yield x
| None -> ()
match myFun 2 x with
| Some x -> yield x
| None -> ()
}
let sequence2 = // order will be different, and we can not have index passed into function unless we do a futher Seq.map
let a = xs |> Seq.choose (myFun 1)
let b = xs |> Seq.choose (myFun 2)
Seq.append a b
My real code:
The code looks not that good a few None
and I tried Seq.choose
, which is not that helpful since it doesn't support Seq.choosei
.
let exam isForward brickID =
let brick = state.[brickID]
let (nextTR, nextOccupied, nextUnoccupied) = if isForward then brick.Body.nudgeForward () else brick.Body.nudgeBack ()
if (nextOccupied.isInGrid gridSize) && (map.ContainsKey nextOccupied |> not) then
let nextBrick = { brick with Body = nextTR }
let nextState = getNextState state brickID nextBrick
if not (explored.Contains nextState) then
let nextMap = map |> Map.remove nextUnoccupied
|> Map.add nextOccupied nextBrick
Some ((nextState, nextMap), (nextBrick, if isForward then brick.Body.Direction else brick.Body.Direction.Opposite))
else None
else None
seq { for brickID in 0 .. state.Length - 1 do
match exam true brickID with
| Some x -> yield x
| None -> ()
match exam false brickID with
| Some x -> yield x
| None -> ()
}
Upvotes: 0
Views: 132
Reputation: 41290
The answer by @Tomas is the best approach in this example. However, you still have another choice to use convenient functions from Option module:
let sequence = seq { for x in xs do
yield! Option.toList (myFun 1 x)
yield! Option.toList (myFun 2 x)
}
You can see this as a customized version of Seq.choose
.
Upvotes: 2
Reputation: 243041
Your exam
function could return a sequence that is either empty (instead of None
) or contains exactly one element (instead of Some
) and use yield!
which adds all elements of a given sequence to the one that you're generating at the moment.
In your pseudo-code sample, this would look as:
let myFun param1 param2 param3 = seq {
if param1 then
if param2 then
yield param3 }
let sequence = seq {
for x in xs do
yield! myFun true true x
yield! myFun true true (x * 10) }
Assuming xs = [1;2]
the above sample generates [1; 10; 2; 20]
(and if you set some of the true
arguments to false
, it will skip some of the numbers)
Upvotes: 5