fsharp / fslang-suggestions

The place to make suggestions, discuss and vote on F# language and core library features
344 stars 21 forks source link

Support optional, named and outref parameters on let bindings on modules #151

Open baronfel opened 8 years ago

baronfel commented 8 years ago

Submitted by Gustavo Guerra on 3/21/2014 12:00:00 AM
131 votes on UserVoice prior to migration

Optional and named parameters are supported in static methods, but not in let bindings on modules. This many times forces you to use a static class instead of a module, which has some inconvenients. Ocaml has this, so I'm guessing is doable.

Original UserVoice Submission Archived Uservoice Comments

Overlord-Zurg commented 7 years ago

Is there any difference between module functions and class functions that prevents this? Or was it perhaps done to encourage curried rather than tupled parameters?

dsyme commented 7 years ago

@Overlord-Zurg THe two main issues are

  1. f (x=1) is not reserved - it is a valid program today e.g.
> let x = 1
- let f x = x;;

val x : int = 1
val f : x:'a -> 'a

> f (x=1);;
val it : bool = true
  1. currying is much more common for module-defined functions and so many more people will generally want/expect named arguments to work in conjunction with currying
czhang03 commented 7 years ago

This feature will be really helpful

aeshthetic commented 6 years ago

Can we bring some attention back to this? Using the syntax that ocaml uses might be confusing due to the fact that members already support optional/default args; perhaps there's something we can do about that. Are there any more issues surroudning the implemenation of this feature?

dsyme commented 6 years ago

From Language Design Office Hours:

@dsyme says: optional and named arguments on module-let-defined functions is something I'd like to see done, in my heart of hearts.

Modules are used for API-design, even if as a stepping stone towards type/member-based design. I do think nearly all APIs end up better if they use some object programming features, but it is entirely reasonable for an API to evolve from prototype module/let code towards a completed API design. Along the way, adding optional and named parameters to module-bound functions is reasonable.

I mention above that there are a couple of technical things here. One that is that f (x=y) today is not reserved - if x and y are in scope then it passes a boolean value. The other is that currying is much more common with module/let code, and optional arguments don't necessarily sit so well with currying (that's what motivates OCaml's inference-based flow of optional/named arguments IIRC).

If you have opinions on this please add them to this suggestion

dsyme commented 6 years ago

More comments from Language Design Office Hours:

@dsyme says should mark it approved-in-principle, with a sketch of the design rules. Basically

  1. allow optional and named arguments on let-defined functions in modules and let-defined functions in lass implementations

  2. allow curried argument sets but not partial application (i.e. the function that results from partial application would not accept named or optional arguments).

  3. For regularity, allow curried argument sets with named/optional arguments for members too, using the same rules.

  4. Find a way of not breaking any existing code for "f(x=y)".

7sharp9 commented 6 years ago

With 2.

allow curried argument sets but not partial application (i.e. the function that results from partial application would not accept named or optional arguments).

If all optional arguments were all applied would this still need to be enforced?

e.g. by keeping optional arguments last, and if there was only one optional argument.

cartermp commented 5 years ago

Given the issue with x=y, would it not be too terrible to have OCAML syntax?

dsyme commented 5 years ago

Given the issue with x=y, would it not be too terrible to have OCAML syntax?

We would just put it under a /langversion:5.0 switch.

There's no chance we would use ~ syntax here, given we already support named arguments for member calls.

cartermp commented 5 years ago

Right, my thinking here is that this might be too much of a breaking change given the ubiquity of function calls compared with, say, the implicit yield or byref changes. Maybe it won't be so bad, would need to get people to try it out

cartermp commented 5 years ago

Similar problem here: https://github.com/dotnet/fsharp/issues/7423

lukemcdo commented 3 years ago

Perhaps a dumb idea but what if named parameters were accessible via dot notation? Say, in your example

> let x = 1
- let f x = x;;

val x : int = 1
val f : x:'a -> 'a

> f (f.x = 1);;

or maybe we could use the legendary params reserved word? For say f(params.x = 1)