fslang-suggestions icon indicating copy to clipboard operation
fslang-suggestions copied to clipboard

Make the `fun` keyword optional

Open baronfel opened this issue 8 years ago • 170 comments

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

baronfel avatar Oct 20 '16 01:10 baronfel

+1 to fat arrows, all in the name of driving adoption for the language.

ncave avatar Oct 31 '16 21:10 ncave

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)

cartermp avatar Oct 31 '16 22:10 cartermp

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

cloudRoutine avatar Oct 31 '16 22:10 cloudRoutine

Good point, => would make cases like that unambiguous.

cartermp avatar Nov 01 '16 01:11 cartermp

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.

gusty avatar Nov 01 '16 09:11 gusty

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.

charlesroddie avatar Jul 20 '17 15:07 charlesroddie

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.

Rickasaurus avatar Jul 21 '17 21:07 Rickasaurus

+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?

sonhanguyen avatar Jul 22 '17 09:07 sonhanguyen

+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

wiwiwa avatar Jul 28 '17 07:07 wiwiwa

+1, if it is possible to make fun optional while still being unambiguous, it would be greatly appreciated.

matthewcrews avatar Aug 07 '17 16:08 matthewcrews

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.

AnthonyLloyd avatar Nov 26 '17 14:11 AnthonyLloyd

I don't like to remove the 'fun' from F#. I would rather discuss about an alternative syntax for very short lambda expressions.

realvictorprm avatar Nov 26 '17 15:11 realvictorprm

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.

MangelMaxime avatar Nov 26 '17 17:11 MangelMaxime

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.

TIHan avatar Nov 26 '17 21:11 TIHan

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

jichang avatar Nov 27 '17 04:11 jichang

@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!

realvictorprm avatar Nov 27 '17 08:11 realvictorprm

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.

pchalamet avatar Nov 27 '17 18:11 pchalamet

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}

vivainio avatar Nov 27 '17 18:11 vivainio

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!

vilinski avatar Nov 27 '17 18:11 vilinski

@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 (*)

AndreuCodina avatar Nov 27 '17 19:11 AndreuCodina

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/bindings let f = fun x y -> x + y where you can also use let 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).

alfonsogarciacaro avatar Nov 28 '17 08:11 alfonsogarciacaro

:-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.

eiriktsarpalis avatar Nov 28 '17 10:11 eiriktsarpalis

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 ;-)

codybartfast avatar Nov 28 '17 14:11 codybartfast

As a C# dev who's interested in F# I've always found the fun keyword unnecessary and offer very little value.

connelhooley avatar Nov 28 '17 22:11 connelhooley

The fun keyword does seem verbose when moving between C#, F#, and Scala, it would be nice if it could be optional somehow

stevewillcock avatar Nov 28 '17 23:11 stevewillcock

(\x -> x + 1)

wannado avatar Nov 29 '17 05:11 wannado

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.

realvictorprm avatar Nov 29 '17 07:11 realvictorprm

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.

matthewcrews avatar Nov 29 '17 17:11 matthewcrews

I must admit that being mostly C# developer but loving F# I keep forgetting to put 'fun' in lambdas.

eugbaranov avatar Nov 29 '17 20:11 eugbaranov

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.

vilinski avatar Dec 01 '17 16:12 vilinski