fslang-suggestions
fslang-suggestions copied to clipboard
Make the `fun` keyword optional
Submitted by Jorge Fioranelli on 3/21/2014 12:00:00 AM
271 votes on UserVoice prior to migration
Make the `fun`` optional. Otherwise it is more verbose than C#.
Original UserVoice Submission Archived Uservoice Comments
+1 to fat arrows, all in the name of driving adoption for the language.
Interesting discussion. I wouldn't support something along the lines of Haskell or Elixir-style lambdas, because instead of shortening what's already there, that would replace it with a new symbol.
I'm also unsure if fat arrows would be needed - is it enough to simply make fun
optional? E.g.
Seq.filter (x y -> something x y)
sticking with ->
leads to situations like
let fn x y =
match x with
| 1 -> z -> x + y * z
| _ -> (z -> x - y * z)
// ^ I guess parens would be required here?
let fn': int -> int -> int = x y -> x + y
I'm ambivalent about this approach, =>
seems better than that
I don't mind fun
though
Good point, =>
would make cases like that unambiguous.
Using an available user-defined operator will break existing code, specifically =>
is being used in some projects, for instance Deedle makes heavy use of it.
The ambiguity reported by @cloudRoutine can be solved since we never match against functions, I mean we can expect a pattern between |
and ->
.
Eventually if a further enhancement allows to decompose a function (if it ever makes any sense) the fun
keyword will not be optional in that context.
Maybe even the function
keyword can be made optional. Cases like
let f x = function | (Some x) -> ... | None -> ...
become
let f x = | (Some x) -> ... | None -> ...
but that for sure will confuse any Haskeller.
I don't like =>
since ⇒ means logical implication.
The mathematical standard is ↦. However there doesn't seem to be a good way to write it in ascii.
->
may be the best ascii approximation of ↦.
~>
doesn't seem too bad if we need something different.
I don't hate this, but I don't love it either. Do you really think the small change will bring over people? I've never heard anyone say "I don't use F# because of the fun keyword". The grammar is also a bit more ambiguous and so difficult to parse, so it will likely always have to be in parens, saving one character on average.
We don't currently use \
to mean anything, so why not gift it from haskell if fun is too much?
I do rather like the idea of dropping the "function" keyword though. It's obnoxiously long.
+1 for this, not only fun
makes us type more it also creates inconsistency in keywords? Why do some have to be a full word (match
) while this one gets abbreviated? Because it's fun?
+1
But more like Scala's lambda shorthand form Seq.filter(_>1)
By the way, proposal of lambda using =>
has already been declined in #384
+1, if it is possible to make fun
optional while still being unambiguous, it would be greatly appreciated.
When I look at my code I see a lot of lets on the left hand side that I think must be redundant. We could remove those too...I'm just joking I think.
I don't like to remove the 'fun' from F#. I would rather discuss about an alternative syntax for very short lambda expressions.
I like the fun keyword because it is easy to read. Sometimes having a lot of symbols make the code harder to read/maintain.
When reading fat arrow or lambda from others language like Javascript, elm or haskell I am always confuse and need time to understand the code.
IMHO, we shouldn't add more ways to do the same thing in this regard. You will not gain that much from trying to shorten syntax; only lead to more inconsitent code across large projects. The property accessor from the other issue is kinda ok, but even then even that can lead to more inconsistencies of just doing the same thing.
As @MangelMaxime said, less keywords and more symbols make code hard to read, plus, in editors, the fun keyword with appropriate color can easily tell the structure of code
@TIHan I agree on your point I admit that I'm in general against anything which reduces readability. It's such a strong and important feature of F# which I always use as selling point for beginners! PS: I'm very against this!
I really would like fun
to disappear of course!
Not sure ->
alone would be the best replacement, =>
is easier to read especially considering match
and function prototypes.
The most annoing use for "fun" is calling methods or looking up properties in objects in pipelines (as they can't be curried away).
Kotlin style lambda with implicit "it" binding would be optimal:
{ it.DoStuff() }
{ i -> i + 1}
A completion snippet for fun
and function
in ionide would be enough for me to solve such "problem". No need to make it shorter if it more clear what happens. Haskell's backslash or scala's underscores are nice but they are adding PROBABLY more perl into F#. Thanks anyway!
@realvictorprm Instead of:
(fun x y -> x + y)
Proposal 1:
\(x y -> x + y)
shown with a font ligature:
λ(x y -> x + y)
Proposal 2:
{x y -> x + y}
shown with a font ligature:
λ{x y -> x + y}
Examples
[ 1; 2; 3; 4; 5 ]
|> map λ(x -> x + 2)
|> fold (*)
[ 1; 2; 3; 4; 5 ]
|> map { x -> x + 2 }
|> fold (*)
For me it was unexpected to see so many opinions in favor of keeping fun
, but that's the good thing of open language design: we can get a better understanding of community's opinion :) However, I'd like to see this suggestion implemented so I'll try to lobby a bit for it with some arguments:
- Lambda syntax looks like a counter example in workshops. I mean we usually try to lure C# or JS people into F# with claims like "it's less verbose!" but then they have to write a pipe chain and it looks like much more code than a fluent API (LINQ) in those languages:
myList
|> List.map (fun x -> x + 1)
|> List.filter (fun x -> x < 5)
myArray
.Select(x => x + 1)
.Where(x => x < 5)
- I'm not an expert in grammar parsing but I don't think it'd be an issue. I would like to see more examples where removing
fun
could make the code ambiguous (there's one by @cloudRoutine above). In my experience you already have to surround lambdas with parens most of the time (except in declarations/bindingslet f = fun x y -> x + y
where you can also uselet x y = x + y
), especially when you pass as them as arguments, either curried (see above) or tupled:
let foo (f: 'a->'b, x: int) = x
let y = foo(fun x -> 5, 6) // Doesn't compile
- It's better to have one general solution than many specific ones. This is a common in F# language design (e.g. using CEs instead of adding a specific
async
mechanism to the language). This discussion has been revived because of the suggestion to allow_.Length
for property accessor, but this would fit that and many other cases without introducing syntax for a very specific situation. I paste here the comparison from this comment:
xs |> List.map (fun x->x.Length)
xs |> List.map (x->x.Length)
xs |> List.map (.Length)
xs |> List.map _.Length
@AndreuCodina Ligatures are really nice (I've also seen fun
being replaced by λ
in emacs and looks awesome) but personally I don't think they should be taken into account for language design. Nowadays we read a lot of code in Github & friends so we shouldn't rely everything to our favorite editor (at least in terms of readability).
:-1: If aesthetics is the sole motivator for this, I don't think it justifies the risk of introducing yet-to-be-discovered breaking changes.
I'm only a lightweight F# user, but I find 'fun' a small, verbose niggle.
When I switch between F# and C# I always use the wrong arrow for a little while, so for '.net' consistency I would like '=>'.
Given how much F# has inspired C#, I think it's only polite for F# to return the favour ;-)
As a C# dev who's interested in F# I've always found the fun keyword unnecessary and offer very little value.
The fun keyword does seem verbose when moving between C#, F#, and Scala, it would be nice if it could be optional somehow
(\x -> x + 1)
Well better tooling support could fix the shorthand property access. Also, Fun definitely increases readability so I'm not really convinced that symbols increase readability. Even in the so famous python one uses lambda args: ...
So one can live very well with fun and it's arrow.
Other than the case provided by @cloudRoutine , is there any reason we can't just make fun
optional? I do most of my work in C# still and it is bizarre to me that it is more succinct to write lambdas in C# than in F# when F# is supposed to be the more functional language. I love F# and wish I could do all of my work in it, but I must admit that the requirement of fun
is odd.
I think the argument that fun
makes it more clear is weak because there's rarely confusion in C# when a lambda is being used in a LINQ expression. Granted, I have not surveyed all C# developers out there but I haven't run across anyone that got confused by the syntax because there wasn't enough indication of what was going on.
If fun
can't be dropped for parsing reasons, I vote for the use of =>
as the operator to signify I am writing a lambda. While it may be ideal to have only one way to express something in a language, I think a pragmatic approach to design should be considered.
F# already admits to not being a pure functional language. From the outset it has been a balance of functional first but willing to bend when the situation calls for it. I believe this is a case where it would serve F# well to adopt a good design choice from another language. C# has been borrowing from F# for years. Maybe it's time we admit that the C# implementation is easier on the developer and is just as clear?
Is it so bad to make fun
optional? I don't think anyone is saying make it forbidden or syntactically wrong to write (fun x -> x + 1)
. Why not be able to say (x -> x + 1)
? Is that really much less clear? I am asking for my own sake because I wan't to understand if there is a design implication that I am not aware of. Thank you for any feedback. I honestly just want to understand.
I must admit that being mostly C# developer but loving F# I keep forgetting to put 'fun' in lambdas.
What about Kotlin's it
for one parameter lambdas? Has it any problems regarding type inference?
myList
|> List.map (it + 1)
|> List.filter (it < 5)
instead of
myList
|> List.map (fun x -> x + 1)
|> List.filter (fun x -> x < 5)
May be it is even enough to just cover single parameter lambdas, or at least as a first step.
I'm also not convinced with =>
. Please don't take any "pragmatic" ways and introduce some different operators or syntax for the same things. Imagine you should explain later to every newbie about some "historical reason". Let's keep ->
for functions.