ozgur
ozgur

Reputation: 2719

F# infix overload doesn't work

let (->>>) lst exp = for i in lst do exp

let result = [0..5] ->>> ([1..5] ->>> printf "hi")
let result2 = for i in [0..5] do for x in [1..5] do printf "hi"

I was expecting result and result2 to do the same thing. But result prints hi just once. result2, however, prints it 30 times. What is missing here?

Upvotes: 3

Views: 59

Answers (1)

Fyodor Soikin
Fyodor Soikin

Reputation: 80744

In your operator definition, exp is not necessarily a function. The way you defined the operator, exp is any value whatsoever. For example, you could do this:

[0..1] ->>> 42

This would compile and even run, because there is nothing in the definition of your operator that requires the exp parameter to be a function. Or anything else for that matter.

If you want to make exp evaluate over and over within the body of the loop, you need to make it a function and make sure that the body of the loop calls it. Since you don't have any requirements for it, the simplest one would be unit -> 'a. You don't really have to declare its type though, you can have the compiler infer it from its use:

let (->>>) lst exp = for i in lst do exp()

Notice the parentheses after exp - they signify a value of type unit, thus making expression exp() a function application (i.e. function exp applied to value ()).

Of course, with this definition, you won't be able to write [1..5] ->>> printf "hi", because printf "hi" is not a function. So instead you'll have to write:

[1..5] ->>> (fun() -> printf "hi")

Now you'll have five "hi"s printed out.

This is because the for .. do syntax is really a special part of the language, not "just another function" defined in the standard library. You can't really create same effect with clever function or operator definitions.

If you want a way to construct more complicated syntax than functions and operators, check out computation expressions.

Upvotes: 9

Related Questions