What there doesn't seem to be is a way to limit aggregates based on conditions of the elements of the sequence - at least not so far as I can see. Every time I think I've almost got a way to do it, something seems to keep me from what I want.

Wow, this took longer to figure out than expected! Apparently, there is no "Seq.tl" function. Hrumpf.

Anyway, here's a simple, non-recursive solution:

1
2
3
4
5
let truncateIf p (s:seq<'a>) =
    seq { let e = s.GetEnumerator()
          while e.MoveNext() && not (p e.Current) do
            yield e.Current
        }
By on 6/5/2008 7:05 PM ()

Well, this is obviously what I wanted but I can't seem to type it into to F# interactive in VS 2008 with the latest version of F#. I can type it into an FS file and compile the file with no errors but if I type in:

1
2
3
let truncateIf p (s:seq<'a>) =
    seq { let e = s.GetEnumerator()
          while e.MoveNext() && not (p e.Current) do

to the interactive window, then as soon as I hit return it tells me that the "while" is a syntax error. Sorry to pester after the great answer you gave, but this is very confusing and keeps me from trying this out in the interactive window.

Thanks for any ideas.

Darrell

By on 6/5/2008 11:17 PM ()

[...] then as soon as I hit return it tells me that the "while" is a syntax error.

There are two styles of F#: the "light" style, and the OCaml-compatible style. Mostly everyone uses the light style (by typing "#light" at the top of the source, or via command line switches) in which white-space is significant and several language constructs are optional, but a few people prefer the control of OCaml style. Best choice is to be compatible with both, but I still often have trouble with the latter style.

Here it is again without assuming #light:

1
2
3
4
5
6
7
8
9
> let truncateIf p (s:seq<'a>) =
-     seq { let e = s.GetEnumerator() in
-           while e.MoveNext() && not (p e.Current) do
-               yield e.Current
-           done }
- ;;

val truncateIf : ('a -> bool) -> seq<'a> -> seq<'a>

Now that I think of it (OK, so after seeing the name in someone else's post), "takeWhile" sounds more natural than "truncateIf":

1
2
3
4
5
6
7
8
9
10
> let takeWhile p (s:seq<'a>) =
-     seq { let e = s.GetEnumerator() in
-           while e.MoveNext() && p e.Current do
-               yield e.Current
-           done
-         }
- ;;

val takeWhile : ('a -> bool) -> seq<'a> -> seq<'a>
By on 6/6/2008 6:20 PM ()

Hi,

Don't forget to use light mode!
Type #light in the interactive mode, it should work.

By on 6/6/2008 3:40 PM ()

Oh - of course - the seq is really a .NET enumerable so you're just using the IEnumerable member function. I guess that's what comes of me being a greenhorn. I'll get the hang of this eventually. Thanks again!

Darrell

By on 6/5/2008 10:08 PM ()

Thanks so much! That's perfect! In fact, in an earlier draft I had asked about how to get the IEnumerator from the sequence's IEnumerable which is apparently what GetEnumerator does. It's not listed in the online documentation under the Sequence members so it's no wonder I didn't find it. Anyway, I'm much obliged for the help - exactly what I was looking for!

Darrell

By on 6/5/2008 9:56 PM ()
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper