So this is just a curiosity question.
If I want to return unit, which is better practice?
|> ignore
or
()
There's probably other ways as well. I just want to know what's best, considering these:
What is most performant
What is best practice for a production environment
What is most readable for long term maintanance
I think you are comparing things that are not quite comparable here. The () value lets you create the unit value, while |> ignore is what you can use to ignore some other result. The two are not exactly the same:
If you are calling a function and you want to ignore the result, you can write just:
doStuff () |> ignore
But doing the same with () would require you to either ignore the warning:
doStuff () // warning: Result is ignored
()
... or you could assign the result to an ignore pattern _ using let binding:
let _ = doStuff ()
()
So, in this case, using ignore is better - it is inlined, so it has no performance implications and it leads to code that is easier to read.
That said, there are cases where you just need to create a unit value and then () is what you need (and there is no obvious way ignore would let you do the same). For example:
match optMessage with
| Some message -> printfn "ANNOUNCEMENT: %s" message
| None -> ()
You could replace () with 42 |> ignore to get the same result, but it would be silly!
ignore is an inlined function so both will produce exactly the same IL.
ignore is more explicit and therefore more readable, and that's why it exists, so you should probably prefer that.
Related
In F# one comes across this sort of thing:
let p = Earth().GetCountry1().GetPopulation()
Sometimes I find myself wanting to separate the argument from the function as is usually done in F#:
let p = ((Earth ()).GetCountry1 ()).GetPopulation ()
which requires many parentheses. Is there a function, or can someone think of one, which can be used in place of the dot operator, which facilitates a more elegant way of maintaining the space between function and argument -- something like this?
let dot method arg obj = obj.method arg
let p = Earth () |> dot GetCountry1 () |> dot GetPopulation ()
(My dot causes a compiler error.)
The original code is perfectly idiomatic F#. There's no need to change it.
However, sometimes you have an F# function pipeline and you need to call a method in the middle of it. The neatest way to do this is with a lambda:
aValue
|> aFunction parameter
|> anotherFunction
|> fun x -> x.Method()
|> oneLastFunction
The function you're trying to write is not possible in a statically typed language. This would need to be added as a language feature, or you can simply use a lambda as shown above.
First off, F# is a multi-paradigm language, so writing code in an OOP style is perfectly valid. If you are consuming C# libraries, this is very common.
I would suggest using the OOP-style (no space before arguments) for the OOP-style code and the functional-style (space after arguments) for the functional-style code.
There is no built-in mechanism for piping members in F#. This could be enabled in the future with the short-hand accessor suggestion or the lenses suggestion.
For now, the quickest solution for the functional-style is to write an anonymous function:
let p =
Earth ()
|> fun x -> x.getCountry1 ()
|> fun x -> x.getPopulation ()
If you do this frequently, it might be best to write a collection of helper functions:
let country1 x =
x.getCountry1 ()
let population x =
x.getPopulation ()
let p =
Earth ()
|> country1
|> population
You could probably implement your dot function using reflection but that would have a run-time overhead, which is probably not worth it.
I want to try something:
try
0/0
and I don't care if it fails, raising an Exception. But leaving a with or finally block empty makes the file unparsable.
This works, but it's not fun to write.
finally
null |> ignore
How to leave the with/finally blocks (as) empty (as possible)?
Every expression must have a result, and try ... with is no exception. The try part is evaluated and a result is obtained. But if the try part fails, the result of the with part is substituted instead.
If your try part is 0/0, then the result type of it is int. Therefore, in order for the types to match, the result of your with part should also be int. Think about what the result of the whole expression should be when the try part fails, and stick it in there:
let foo =
try 0/0
with _ -> 42
Since you're saying that null |> ignore works, I must conclude that your try part is not in fact 0/0. The ignore function returns () (a value of type unit), so if that works for you in the with part, then your try part must be also returning unit. If that is the case, you can use () as the with part instead of null |> ignore.
let foo =
try printfn "Let's pretend that printfn may fail"
with _ -> ()
For reference, this is (roughly) how ignore is defined:
let ignore x = ()
Probably a newbie question, but is there a standard function like
let apply f = f()
in F#?
No, there is not a standard function for this.
In most cases, just calling the function is shorter and more obvious than using apply would be, so I'm not entirely sure how this would be useful:
foo ()
apply foo
Now, you can also write application using |>, but that's not very nice either:
() |> foo
I guess the only place where apply would be useful is:
functions |> List.map apply
functions |> List.map (fun f -> f ())
Here, the version without apply is shorter, but I don't think it is worth having a named function in the library just for this one use case.
You could actually use |> here to avoid fun, which makes for a lovely piece of ASCII art :-), but not for something that I would ever want to see in my codebase:
functions |> List.map ((|>) ())
I'm a bit confused as to how to get two method to call each other (i.e., have A() call B() and B() call A()). It seems that F# only 'sees' the method after it's been encountered in code, so if it hasn't, it just says value or constructor has not been defined.
Am I missing something very basic here?
'let rec... and...' is the syntax you seek.
let rec F() =
G()
and G() =
F()
See also Adventures in F# Co-Recursion.
Since the question is about methods, and Brian's answer is about functions, maybe it's useful to point out that you can use a similar syntax for types:
type A() =
let b = new B()
member x.MethodA() = b.MethodB()
and B() =
member x.MethodB() = ()
Note also that members are 'let rec' by default (in fact I don't think they can be not recursive).
F# 4.1 introduces mutually recursive modules and namespaces.
These are an alternative to the and keyword.
module rec PingPong = // <------ rec keyword here.
let pong() =
printfn "pong"
ping()
let ping () =
printfn "ping"
pong()
The rec keyword defines modules and namespaces that "allow for all contained code to be mutually recursive."
Functions declared via let
let rec a () = b ()
and b () = ()
These are mutually recursive functions.
Methods within the same type
type T () =
member t.A () = t.B()
member t.B () = ()
This is trivial; it just works. Note Abel's comment though.
Methods within different types
type TypeA () =
member t.A (b : TypeB) = b.B()
and TypeB () =
member b.B () = ()
This uses the type ... and syntax for mutually recursive types.
Notes
Normally, and is only used if the calls occur in both directions. Otherwise, it may be better to re-order the declarations so that the called function comes first. It is often helpful for type-inference and readability to avoid circular dependencies, and to not imply them where they aren't used.
I propose to edit the question to either ask for functions in general, or to ask for different types (in which case I would remove the first two cases from this answer). Methods are usually considered to be a subset of functions, which is the general mathematical term. However, all F# functions are technically CLI methods, as that is what they are compiled to. As is, it is not clear what the question is asking for, but I assume from the accepted answer that it does not only ask for methods, as the title would imply.
Which of theese two alternatives do you find yourself using most often, and which is more "idiomatic"?
f arg (obj.DoStuff())
f arg <| obj.DoStuff()
Overall, I don't know that one or the other is more idiomatic.
Personally, the only time I use <| is with "raise":
raise <| new FooException("blah")
Apart from that, I always use parens. Note that since most F# code uses curried functions, this does not typically imply any "extra" parens:
f arg (g x y)
It's when you get into non-curried functions and constructors and whatnot that it starts getting less pretty:
f arg (g(x,y))
We will probably at least consider changing the F# languages rules so that high-precedence applications bind even more tightly; right now
f g()
parses like
f g ()
but a lot of people would like it to parse as
f (g())
(the motivating case in the original question). If you have a strong opinion about this, leave a comment on this response.
Because type inference works from left to right, a bonus of using |> is that it allows F# to infer the type of the argument of the function.
As a contrived example,
[1; 2; 3] |> (fun x -> x.Length*2)
works just fine, but
(fun x -> x.Length*2) [1; 2; 3]
complains of "lookup on object of indeterminate type".
I use () much much more often, but thats just preference, I'm pretty sure that <| is more idomatic, but I use () by habit.
Whenever possible, I much prefer |> because it reads from left to right.