Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot use try / with blocks inside sequence expressions. How to get around it?

Tags:

.net

f#

Consider that

Pentagonal numbers are generated by the formula, Pn=n(3n−1)/2.

I opted to create a sequence of pentagonal numbers in F#:

let pentagonalSeq = { 1..Int32.MaxValue } |> Seq.map (fun n -> n*(3*n-1)/2)

So far so good. For most purposes I'll only want to calculate a couple of small integer pentagonal numbers. But there may be times I wish, for instance, to get all Int32 pentagonal numbers. I was thinking it would be possible to just go on calculating them until I eventually got an OverflowException (I'm using checked arithmetic). The trouble is that F# isn't particularly happy about my idea, yelling that

'try/with' cannot be used inside sequence expressions

What's the best way to keep this young lady satisfied?

Assume that I want to create a int32_pentagonalSeq that:

  1. makes use of pentagonalSeq
  2. does not incur in any extra calculations trying to predict whether the next item might or not might not originate an overflow.

Thanks

like image 666
devoured elysium Avatar asked Feb 13 '14 23:02

devoured elysium


2 Answers

I think the answer from Gene is probably the way to go! But if you wanted to use sequence expressions to iterate over elements of a sequence that you already have, you could write something like this:

let takeWhileNonException (input:seq<_>) = seq { 
  use ps = input.GetEnumerator()
  while (try ps.MoveNext() with _ -> false) do 
    yield ps.Current }

Sadly, you cannot just wrap for loop or yield! statement with try .. with because (as you said), sequence expressions does not support exception handlers. However, you can use the underlying iterator and wrap the MoveNext call in exception handler (because this is an ordinary expression) and return false when the operation fails for the first time.

So, to get the last number of the sequence, you can now write:

pentagonalSeq
|> takeWhileNonException
|> Seq.last
like image 180
Tomas Petricek Avatar answered Oct 30 '22 11:10

Tomas Petricek


Can you do something like this maybe?

let pentagonal n = 
   try
      Some(n*(3*n-1)/2)
   with
     | ex -> None

let x = { 1.. Int32.MaxValue } |> Seq.map pentagonal
like image 44
devshorts Avatar answered Oct 30 '22 11:10

devshorts