New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplified syntax for lambda #634

Open
enricosada opened this Issue Jan 8, 2018 · 21 comments

Comments

Projects
None yet
@enricosada

enricosada commented Jan 8, 2018

I propose we add a simplified syntax for lambda. this helps to cover some scenarios, not to completly replace the fun syntax

A scenario: F# allow easy value transformations (map, etc), who lots of time use simple rules, so short lambda

The existing way of approaching this problem in F# is like

xs |> List.map (fun x -> x.Name)
xs |> List.map (fun x -> x + 2)
xs |> List.map (fun x -> x.[1])
xs |> List.map (fun x -> Some 3, Very(Complex(x, (fun y -> x + y)))))

Current:

  • xs |> List.map (fun x -> x.Length + 1) actual

Two proposed solutions:

  1. xs |> List.map (x -> x.Length +1) drop the fun keyword
  2. xs |> List.map (x => x.Length +1) drop the fun keyword, use fat arrow
  3. xs |> List.map ( it.Length + 1 ) use new it in block

Already proposed variant, but who cannot use the value like (fun x -> x + 2) so discarted it for this proposal for a generic lambda (is discussed in #506),

  • xs |> List.map (.Length)
  • xs |> List.map _.Length ( in #506 )

1 Drop fun

This shorten just a bit the sintax

xs |> List.map (x -> x.Name)
xs |> List.map (x -> x * 2)
xs |> List.map (x -> x.[1])
xs |> List.map (x ->Some 3, Very(Complex(it, (y -> x + y)))))

2 Drop fun, use fat arrow

This shorten just a bit the sintax, and is familiar with other lang like c#.

xs |> List.map (x => x.Name)
xs |> List.map (x => x * 2)
xs |> List.map (x => x.[1])
xs |> List.map (x =>Some 3, Very(Complex(it, (y => x + y)))))

3 use a new keyword it like :

xs |> List.map ( it.Name )
xs |> List.map ( it * 2 )
xs |> List.map ( it.[1] )
xs |> List.map ( Some 3, Very(Complex(it, (fun y -> it + y)))))

Rules:

  • is not possibile to restrict the type. equivalent of (fun (x:int) -> x +2) doesnt exists, just use fun. or ( let x : int = it in x + y) as normal expression
  • is not possibile to deconstruct. equivalent of (fun (x,y) -> x +y) doesnt exists, just use fun. or ( let x,y = it in x + y) because is a normal expression
  • for code formatting, suggest to use a whitespace after initial and before final parens (so ( it.Name ) not (it.Name))
  • it can be use only where a function can be used.
  • inside fun, is expected to be a binding in scope, like normal binding
    • xs |> List.map ( Some 3, Very(Complex(it, (fun y -> x + it)))))

Some variations:

  • 1 and 2 about nested usage
  • A and B about parens (optional vs mandatory)

Variation 1

  • nested, not allowed. this is a sintax for simple scenario. use fun if nested
    • xs |> List.map ( Some 3, Very(Complex(it, ( it + it ))))) doesnt compile, and is error prone anyway
    • xs |> List.map ( Some 3, Very(Complex(it, (fun x -> x+ it ))))) ok
  • it cannot used more than once, no need for shadow rules

Variation 2

  • every lambda has it's own it in scope, which shadows any outer lambda(s) it
  • nested usage is allowed

Variation A

  • require parentheses if the expression is non-atomic
xs |> List.map it.Property
xs |> List.map it.Property1.Property2    
xs |> List.map it.Method
xs |> List.map (it.Method arg)
xs |> List.map (it.Method(1,2))
xs |> List.map (it.Method().Property)
xs |> List.map (it.Method(1).Property)
xs |> List.map (it + 1)
xs |> List.map (it > 10)
xs |> List.map it.[1]
xs |> List.map it.[1..10]

Variation B

  • parens are mandatory. List.map it.Name vs List.map ( it.Name ) is not that much as overhead for a consistent sintax (as a note, List.map _.Name from #506 can cover this additional shortcut sintax)

Pros and Cons

The advantages of making this adjustment to F# are to allow simplified lambda block, with a consistent sintax for both shortcuts like

  • methods (fun x -> x.Name.ToUpper()) to ( it.Name.ToUpper() )
  • values (fun x -> x + x) to ( it+ it )

The disadvantages of making this adjustment to F# are:

  • less usage of fun keyword. but it was fun until it lasted (sry, i had to)
  • another way to declare a lamba
  • more complex inference
  • it used in fsi repl. but because it get shadow'ed, is not that much a problem for backward compatibility (old code doesnt use new sintax)

Extra information

Estimated cost (XS, S, M, L, XL, XXL): XL

Related suggestions:

  • #506 (about _.Property shortcut)

More related work:

Affidavit (please submit!)

Please tick this by placing a cross in the box:

  • This is not a question (e.g. like one you might ask on stackoverflow) and I have searched stackoverflow for discussions of this issue
  • I have searched both open and closed suggestions on this site and believe this is not a duplicate
  • This is not something which has obviously "already been decided" in previous versions of F#. If you're questioning a fundamental design decision that has obviously already been taken (e.g. "Make F# untyped") then please don't submit it.

Please tick all that apply:

  • This is not a breaking change to the F# language design
  • I would be willing to help implement and/or test this
@dsyme

This comment has been minimized.

Show comment
Hide comment
@dsyme

dsyme Jan 8, 2018

Collaborator

I don't understand this rule:

every lambda has it's own it in scope, which shadows any outer lambda(s) it

My interpretation of your rules is that (...) introduces a new lambda if and only if there is a use of it within the parentheses (and not nested in other parentheses). But you show:

xs |> List.map ( Some 3, Very(Complex(it, (fun y -> it + y)))))

as one of your examples, where it is two nestings of parentheses above where you want the implied lambda to be. (My understanding is you are not proposing a type-directed rule for the location of the implied lambda)

Like most people I generally am uneasy with rules that are so sensitive to addition/removal of parentheses - F# already uses these in a few places but we've tried not to make it pervasive in the basic expression-oriented part of the language

Collaborator

dsyme commented Jan 8, 2018

I don't understand this rule:

every lambda has it's own it in scope, which shadows any outer lambda(s) it

My interpretation of your rules is that (...) introduces a new lambda if and only if there is a use of it within the parentheses (and not nested in other parentheses). But you show:

xs |> List.map ( Some 3, Very(Complex(it, (fun y -> it + y)))))

as one of your examples, where it is two nestings of parentheses above where you want the implied lambda to be. (My understanding is you are not proposing a type-directed rule for the location of the implied lambda)

Like most people I generally am uneasy with rules that are so sensitive to addition/removal of parentheses - F# already uses these in a few places but we've tried not to make it pervasive in the basic expression-oriented part of the language

@gerardtoconnor

This comment has been minimized.

Show comment
Hide comment
@gerardtoconnor

gerardtoconnor Jan 8, 2018

Thanks @enricosada

  • I like making fun optional, keeping the -> for backward compatibility.
  • Think time of using => is gone, many code bases use this as a separate special operator also.
  • favour _.Prop over using it.Prop, also I think given the amount of extra resolution & work required to create complete nested scoping etc, I favour using _.Prop purely for method/property calls, there isn't that much typing overhead using (x -> x + 2) vs (_ + 2) and TBH, (x -> x + 2) is a lot more clear/explicit, cant compromise readability of code.

Like most people I generally am uneasy with rules that are so sensitive to addition/removal of parentheses - F# already uses these in a few places but we've tried not to make it pervasive in the basic expression-oriented part of the language

Agreed, there will be a lot of related bugs/issues raised when it's this sensitive, will frustrate more than help people.

gerardtoconnor commented Jan 8, 2018

Thanks @enricosada

  • I like making fun optional, keeping the -> for backward compatibility.
  • Think time of using => is gone, many code bases use this as a separate special operator also.
  • favour _.Prop over using it.Prop, also I think given the amount of extra resolution & work required to create complete nested scoping etc, I favour using _.Prop purely for method/property calls, there isn't that much typing overhead using (x -> x + 2) vs (_ + 2) and TBH, (x -> x + 2) is a lot more clear/explicit, cant compromise readability of code.

Like most people I generally am uneasy with rules that are so sensitive to addition/removal of parentheses - F# already uses these in a few places but we've tried not to make it pervasive in the basic expression-oriented part of the language

Agreed, there will be a lot of related bugs/issues raised when it's this sensitive, will frustrate more than help people.

@theprash

This comment has been minimized.

Show comment
Hide comment
@theprash

theprash Jan 8, 2018

Without an explicit lambda boundary even quite simple expressions become ambiguous:

(f2 (f1 it))

What about -> to mark the start of a lambda after an opening paren?

(-> f2 (f1 it))

Or with an underscore instead:

(-> f2 (f1 _))

I prefer the underscore because it stands out more as a language feature but wouldn't want it to clash with #506. Would the following lambda return the property or a function to get the property?

(-> _.Prop)

theprash commented Jan 8, 2018

Without an explicit lambda boundary even quite simple expressions become ambiguous:

(f2 (f1 it))

What about -> to mark the start of a lambda after an opening paren?

(-> f2 (f1 it))

Or with an underscore instead:

(-> f2 (f1 _))

I prefer the underscore because it stands out more as a language feature but wouldn't want it to clash with #506. Would the following lambda return the property or a function to get the property?

(-> _.Prop)
@gerardtoconnor

This comment has been minimized.

Show comment
Hide comment
@gerardtoconnor

gerardtoconnor Jan 8, 2018

@theprash I think you have nicely highlighted that as you try to remove ambiguity ... you end up nearly where you started, and for the sake of 1 less arg char/val is it worth it!?

I think (-> _.Prop) bit is ugly and better off sticking with #506 format of _.Prop : 'T -> 'Prop so it is just creating a function (needs input object to extract property), and no parenthesis needed for prop but needed on method call (with args) (_.Method())

gerardtoconnor commented Jan 8, 2018

@theprash I think you have nicely highlighted that as you try to remove ambiguity ... you end up nearly where you started, and for the sake of 1 less arg char/val is it worth it!?

I think (-> _.Prop) bit is ugly and better off sticking with #506 format of _.Prop : 'T -> 'Prop so it is just creating a function (needs input object to extract property), and no parenthesis needed for prop but needed on method call (with args) (_.Method())

@enricosada

This comment has been minimized.

Show comment
Hide comment
@enricosada

enricosada Jan 8, 2018

every lambda has it's own it in scope, which shadows any outer lambda(s) it

sry @dsyme i'll remove that.
i liked the discussion about this in #506 and tried to summarize it, that rule was part of the discussion.

Later, while writing the nested usage example, i found the it to be ambiguous and bad ihmo.

in xs |> List.map ( Some 3, Very(Complex(it, ( it + it ))))) the it doesnt do what you can think, so is error prone ihmo. Is hard to see that it + it is not the other lambda it, but was an additional lambda equal to (fun y -> y + y) ) so i think was worth add a restriction to usage (no nested it)

Added Variation 1 and Variation 2 about nested

Like most people I generally am uneasy with rules that are so sensitive to addition/removal of parentheses

again, trying to write down the examples, making optional the parens may helps with some scenarios, but some of these can be better done with_.Prop sintax for example (#506 if this doesnt replace it, making that _.Prop a special case of it.Prop when is anonimous).

List.map _.Prop vs List.map it.Prop vs List.map ( it.Prop )

Anyway, allow the optional parens add lot of corner case to discuss like List.map it.[0], List.map it.Prop.ToUpper() who can be easier (and not too much verbose) just using the normal form with parens List.map ( it.[0] ) and List.map ( it.Prop.ToUpper() ).

You added some in the #506 (comment) about require require parentheses if the expression is non-atomic

xs |> List.map it.Property
xs |> List.map it.Property1.Property2    
xs |> List.map it.Method
xs |> List.map (it.Method arg)
xs |> List.map (it.Method(1,2))
xs |> List.map (it.Method().Property)
xs |> List.map (it.Method(1).Property)
xs |> List.map (it + 1)
xs |> List.map (it > 10)
xs |> List.map it.[1]
xs |> List.map it.[1..10]

@dsyme added Variation A and Variation B for parens

enricosada commented Jan 8, 2018

every lambda has it's own it in scope, which shadows any outer lambda(s) it

sry @dsyme i'll remove that.
i liked the discussion about this in #506 and tried to summarize it, that rule was part of the discussion.

Later, while writing the nested usage example, i found the it to be ambiguous and bad ihmo.

in xs |> List.map ( Some 3, Very(Complex(it, ( it + it ))))) the it doesnt do what you can think, so is error prone ihmo. Is hard to see that it + it is not the other lambda it, but was an additional lambda equal to (fun y -> y + y) ) so i think was worth add a restriction to usage (no nested it)

Added Variation 1 and Variation 2 about nested

Like most people I generally am uneasy with rules that are so sensitive to addition/removal of parentheses

again, trying to write down the examples, making optional the parens may helps with some scenarios, but some of these can be better done with_.Prop sintax for example (#506 if this doesnt replace it, making that _.Prop a special case of it.Prop when is anonimous).

List.map _.Prop vs List.map it.Prop vs List.map ( it.Prop )

Anyway, allow the optional parens add lot of corner case to discuss like List.map it.[0], List.map it.Prop.ToUpper() who can be easier (and not too much verbose) just using the normal form with parens List.map ( it.[0] ) and List.map ( it.Prop.ToUpper() ).

You added some in the #506 (comment) about require require parentheses if the expression is non-atomic

xs |> List.map it.Property
xs |> List.map it.Property1.Property2    
xs |> List.map it.Method
xs |> List.map (it.Method arg)
xs |> List.map (it.Method(1,2))
xs |> List.map (it.Method().Property)
xs |> List.map (it.Method(1).Property)
xs |> List.map (it + 1)
xs |> List.map (it > 10)
xs |> List.map it.[1]
xs |> List.map it.[1..10]

@dsyme added Variation A and Variation B for parens

@Rickasaurus

This comment has been minimized.

Show comment
Hide comment
@Rickasaurus

Rickasaurus Jan 9, 2018

I'm really not a fan of it, I know it's just aesthetics but it looks really ugly to me.

Rickasaurus commented Jan 9, 2018

I'm really not a fan of it, I know it's just aesthetics but it looks really ugly to me.

@gerardtoconnor

This comment has been minimized.

Show comment
Hide comment
@gerardtoconnor

gerardtoconnor Jan 9, 2018

Yeah ... can we kick it?

gerardtoconnor commented Jan 9, 2018

Yeah ... can we kick it?

@gerardtoconnor

This comment has been minimized.

Show comment
Hide comment
@gerardtoconnor

gerardtoconnor Jan 9, 2018

... oh ... no Tribe Called Quest fans in the audience ... 😒

gerardtoconnor commented Jan 9, 2018

... oh ... no Tribe Called Quest fans in the audience ... 😒

@voronoipotato

This comment has been minimized.

Show comment
Hide comment
@voronoipotato

voronoipotato Jan 9, 2018

I think it also overlaps with the "_" style syntax being discussed on the other issue, vasily proposed it but he relented later, I don't like it,I'm sure it's great for Kotlin but, I think it's bad for F#. I'm a fan of either dropping fun, or dropping fun and using fat arrow. I think the fat arrow will be more clear to javascript and C# users, but I think someone had discussed that fat arrow was already being used by some F# projects. I've personally always found "fun" to be visually noisy. It doesn't provide any information that can't be gleaned from a few characters ahead.

voronoipotato commented Jan 9, 2018

I think it also overlaps with the "_" style syntax being discussed on the other issue, vasily proposed it but he relented later, I don't like it,I'm sure it's great for Kotlin but, I think it's bad for F#. I'm a fan of either dropping fun, or dropping fun and using fat arrow. I think the fat arrow will be more clear to javascript and C# users, but I think someone had discussed that fat arrow was already being used by some F# projects. I've personally always found "fun" to be visually noisy. It doesn't provide any information that can't be gleaned from a few characters ahead.

@rmunn

This comment has been minimized.

Show comment
Hide comment
@rmunn

rmunn Jan 9, 2018

I would generally be in favor of removing fun, but I do have questions. For example, might there be some ambiguous situations involving other meanings of ->? For example, what happens if I have a match that needs to return a function?

match operation with
| Add n -> (+) n
| Sub n -> x -> x - n
| Collatz -> x -> if x % 2 = 0 then x / 2 else x * 3 + 1

Will the Collatz line parse? What about the Sub n line? And how hard will it be to tweak the parser to make those lines work?

For reference, here's how that match statement would be written with fun:

match operation with
| Add n -> (+) n
| Sub n -> (fun x -> x - n)
| Collatz -> (fun x -> if x % 2 = 0 then x / 2 else x * 3 + 1)

rmunn commented Jan 9, 2018

I would generally be in favor of removing fun, but I do have questions. For example, might there be some ambiguous situations involving other meanings of ->? For example, what happens if I have a match that needs to return a function?

match operation with
| Add n -> (+) n
| Sub n -> x -> x - n
| Collatz -> x -> if x % 2 = 0 then x / 2 else x * 3 + 1

Will the Collatz line parse? What about the Sub n line? And how hard will it be to tweak the parser to make those lines work?

For reference, here's how that match statement would be written with fun:

match operation with
| Add n -> (+) n
| Sub n -> (fun x -> x - n)
| Collatz -> (fun x -> if x % 2 = 0 then x / 2 else x * 3 + 1)
@voronoipotato

This comment has been minimized.

Show comment
Hide comment
@voronoipotato

voronoipotato Jan 9, 2018

-> is right associative, so I think it would parse out correctly but I nobody should rely on my word.

voronoipotato commented Jan 9, 2018

-> is right associative, so I think it would parse out correctly but I nobody should rely on my word.

@isaacabraham

This comment has been minimized.

Show comment
Hide comment
@isaacabraham

isaacabraham Jan 15, 2018

Why wouldn't deconstruct be possible e.g. given

List.map(fun (a,b) -> a + b)

why would this not be doable

List.map((a,b) -> a + b)

isaacabraham commented Jan 15, 2018

Why wouldn't deconstruct be possible e.g. given

List.map(fun (a,b) -> a + b)

why would this not be doable

List.map((a,b) -> a + b)
@xperiandri

This comment has been minimized.

Show comment
Hide comment
@xperiandri

xperiandri Jan 16, 2018

In general it looks like a nice idea however the root issues is code generation absence.

Just add snippets support to Visual Studio for F# and it will be much more pleasant to write.
Meanwhile the only solution to avoid waste typing is to use CodeRush with my templates https://github.com/xperiandri/CodeRushTemplates

You just type fun + Space Bar and have template expanded.

xperiandri commented Jan 16, 2018

In general it looks like a nice idea however the root issues is code generation absence.

Just add snippets support to Visual Studio for F# and it will be much more pleasant to write.
Meanwhile the only solution to avoid waste typing is to use CodeRush with my templates https://github.com/xperiandri/CodeRushTemplates

You just type fun + Space Bar and have template expanded.

@voronoipotato

This comment has been minimized.

Show comment
Hide comment
@voronoipotato

voronoipotato Jan 16, 2018

@xperiandri no, the root issue is not code generation absence. You still have to read fun over and over despite it providing no useful information. It's cool that you wrote snippets that cut out some of the typing but it does not eliminate the reading.

voronoipotato commented Jan 16, 2018

@xperiandri no, the root issue is not code generation absence. You still have to read fun over and over despite it providing no useful information. It's cool that you wrote snippets that cut out some of the typing but it does not eliminate the reading.

@wanton7

This comment has been minimized.

Show comment
Hide comment
@wanton7

wanton7 Jan 17, 2018

I'm F# beginner, i've been writing C# professionally 12 years. "it"suggestion looks ugly as hell to me and i feel it would be a taint to this beatiful language. I've written lot and lot of lambdas in C# , but after using F# for a while and => feels very unnatural for F# because -> is already used with fun keyword. I think it would make language harder to read compared to just making fun keyword optional.

wanton7 commented Jan 17, 2018

I'm F# beginner, i've been writing C# professionally 12 years. "it"suggestion looks ugly as hell to me and i feel it would be a taint to this beatiful language. I've written lot and lot of lambdas in C# , but after using F# for a while and => feels very unnatural for F# because -> is already used with fun keyword. I think it would make language harder to read compared to just making fun keyword optional.

@voronoipotato

This comment has been minimized.

Show comment
Hide comment
@voronoipotato

voronoipotato Jan 18, 2018

@wanton7 yeah I don't really understand the "it" suggestion. I think some libraries already use => for a different meaning. I've not seen any reason why we can't just eliminate fun without consequence.

voronoipotato commented Jan 18, 2018

@wanton7 yeah I don't really understand the "it" suggestion. I think some libraries already use => for a different meaning. I've not seen any reason why we can't just eliminate fun without consequence.

@miegir

This comment has been minimized.

Show comment
Hide comment
@miegir

miegir Jan 20, 2018

I don't like the 'it' version because it is too restrictive, 'it' syntax supports only 'fun it -> ...'. In fact, I think that 'function' can also be used instead of 'fun'. The 'function' can always be used instead of 'fun' and is more powerful. With 'funtion', the 'match' keyword is not needed, because you can rewrite 'match x with ...' as 'x |> function ...'. In other words, I would like if there will be a shorter syntax for 'function' lambda, one with '->' or one with '=>' such as xs |> List.map (0 -> "zero" | x -> string x)

miegir commented Jan 20, 2018

I don't like the 'it' version because it is too restrictive, 'it' syntax supports only 'fun it -> ...'. In fact, I think that 'function' can also be used instead of 'fun'. The 'function' can always be used instead of 'fun' and is more powerful. With 'funtion', the 'match' keyword is not needed, because you can rewrite 'match x with ...' as 'x |> function ...'. In other words, I would like if there will be a shorter syntax for 'function' lambda, one with '->' or one with '=>' such as xs |> List.map (0 -> "zero" | x -> string x)

@voronoipotato

This comment has been minimized.

Show comment
Hide comment
@voronoipotato

voronoipotato Jan 20, 2018

oooh interesting. That does sound even more useful.

voronoipotato commented Jan 20, 2018

oooh interesting. That does sound even more useful.

@miegir

This comment has been minimized.

Show comment
Hide comment
@miegir

miegir Jan 25, 2018

Oh, my mistake was that fun can always be replaced with function. It is not correct when fun of more than one argument is needed. For example, xs |> List.mapi (fun i x -> ...) cannot be rewritten with shorter lambda syntax that expands to function. But in this case, continuing to using fun is just 4 symbols longer than possible syntax without keyword, and perhaps this case is rarer than case with one argument.

miegir commented Jan 25, 2018

Oh, my mistake was that fun can always be replaced with function. It is not correct when fun of more than one argument is needed. For example, xs |> List.mapi (fun i x -> ...) cannot be rewritten with shorter lambda syntax that expands to function. But in this case, continuing to using fun is just 4 symbols longer than possible syntax without keyword, and perhaps this case is rarer than case with one argument.

@rmunn

This comment has been minimized.

Show comment
Hide comment
@rmunn

rmunn Jan 25, 2018

That's an interesting question: would functions of arity 2 or higher* be given a shorthand syntax as well? I.e., would (fun a b -> if a > b then a - b else b - a) be shortened to (a b -> if a > b then a - b else b - a)? And would that cause any ambiguities?

My inclination is to say that this should not be allowed, since it's too ambiguous: a b without a leading fun looks too much like a function call, so (a b -> if a > b then a - b else b - a) looks like you're calling a with a lambda (fun b -> ...) as argument. I'd say that if you're wanting a simplified syntax for a two-argument function, you either have to write fun a b -> ... as before, or else you can use the simplified (and curried) syntax a -> b -> ....

So I'm proposing that fun a b -> ... could be converted to a -> b -> ..., but NOT to a b -> ....

* Of course, all functions in F# are curried so they're really of arity 1. But F# lets you pretend that they're arity 2 or higher via fun a b -> ..., and that's the syntax I'm interested in considering here.

rmunn commented Jan 25, 2018

That's an interesting question: would functions of arity 2 or higher* be given a shorthand syntax as well? I.e., would (fun a b -> if a > b then a - b else b - a) be shortened to (a b -> if a > b then a - b else b - a)? And would that cause any ambiguities?

My inclination is to say that this should not be allowed, since it's too ambiguous: a b without a leading fun looks too much like a function call, so (a b -> if a > b then a - b else b - a) looks like you're calling a with a lambda (fun b -> ...) as argument. I'd say that if you're wanting a simplified syntax for a two-argument function, you either have to write fun a b -> ... as before, or else you can use the simplified (and curried) syntax a -> b -> ....

So I'm proposing that fun a b -> ... could be converted to a -> b -> ..., but NOT to a b -> ....

* Of course, all functions in F# are curried so they're really of arity 1. But F# lets you pretend that they're arity 2 or higher via fun a b -> ..., and that's the syntax I'm interested in considering here.

@erbaman

This comment has been minimized.

Show comment
Hide comment
@erbaman

erbaman Jul 28, 2018

I'm really not a fan of it.

Pros and Cons

The advantages of making this adjustment to F# are to allow simplified lambda block, with a consistent sintax for both shortcuts like

methods (fun x -> x.Name.ToUpper()) to ( it.Name.ToUpper() )

ToUpper should just be a function in my opinion.
Seq.map String.ToUpper

As for the fun keyword. I really don't like having two different syntaxes for lambda.
I personally don't mind fun but if I were to pick a replacement it would be \

erbaman commented Jul 28, 2018

I'm really not a fan of it.

Pros and Cons

The advantages of making this adjustment to F# are to allow simplified lambda block, with a consistent sintax for both shortcuts like

methods (fun x -> x.Name.ToUpper()) to ( it.Name.ToUpper() )

ToUpper should just be a function in my opinion.
Seq.map String.ToUpper

As for the fun keyword. I really don't like having two different syntaxes for lambda.
I personally don't mind fun but if I were to pick a replacement it would be \

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment