Open smoothdeveloper opened 1 year ago
Ha, there was always the expectation that people would want to expand the "underscore lambda" syntax to more than member access. We may not want to go full Scala _ + _
, but this small extension seems reasonable to me.
We could even have:
{ _ with a.b = value }
aka "What if we took F# 8's two biggest new features and smashed them together?" 😄
data
|> { _ with a = 2 }
|> // ...
{ data with a = 2 }
|> // ...
let setB value = { _ with b = value }
let setB value x = { x with b = value }
Do you have any other examples? These aren't particularly convincing.
It just came spontaneously, I had to share. Let see.
One drawback is you can't refer again to the _ in the expressions, I think it would conflict with the shorthand lambda that just shipped.
I think it brings a sense of acceptance that there is let _ =
and other places where we discard, then there is the shorthand lambdas for "dot chains" and records, and maybe more.
One thought is we could make an analyzer that scans codebases in the wild, for getting a statistical sense of "is this syntax sugar suggestion going to apply to many codebases and look good in actual code", here we'd search for lambdas that transform a record.
Keep the reasons coming for "why not", and discussing about the "ethos of shorthand lambda and _ for readability", I'll update the top post to summarize once there has been enough bashing / advocating.
cannot refer to the record itself in the shorthand lambda
Pondering on this con, I think it plays nicely with nested record update, and it is kind of a smell to update one field based on the other one in cases that aren't trivial; the shorthand could be a cue that this is impossible just at a glance, so actually a good thing.
@kerams, your contention also applies to shorthand lambda for property access:
let getB x = x.B
let getB = _.B
I've added changeAValues
in the code sample since your comment.
Am I right assuming the real benefit should arrive pretty much only at LOC with both a fun
and a with
as of now?
i.e. somewhat close to what top of these search results show https://github.com/search?q=%22fun%22+%22%7B%22+%22with%22+language%3AF%23+&type=code ?
i.e. changing this:
DotNetCli.Restore (fun p -> { p with Project = docsTutorialsProject })
DotNetCli.Build (fun p -> { p with Project = docsTutorialsProject; Configuration = configuration })
into this:
DotNetCli.Restore { _ with Project = docsTutorialsProject }
DotNetCli.Build { _ with Project = docsTutorialsProject; Configuration = configuration }
@T-Gro now you seem like making a compelling case even 🙂.
Without going too far, I think the symmetry with "get record property" with "udpate record property" has nice, erm, properties, but I don't want to nudge the language on "point free" nor "abusing of discard", unless there is real appeal and we feel it is conservative enough change.
I like how this proposal reads, even though the use case for "pipeline of updates" is likely a lot smaller than one for "pipeline of gets".
Personally, I would especially like if there was a way of somehow achieving symmetry here for tuples (and "tuples" inside DU cases) as well, but I do know that is too much to ask for at once :-))
Hmm it's always worth considering:
If a feature is seldomly used, I think the longer version is alright.
I've tried looking through our fairly large codebase and I couldn't find any immediate uses for it myself. Maybe I need to see more motivating examples 😄
@drhumlen, what @T-Gro shown is one of the many functions in FAKE modules, that take a record and return an updated version; this is an idiom in FAKE and probably other, where you need a default setting, and give the user the ability to alter it by passing a 'record -> 'record
function.
If a feature is seldomly used, I think the longer version is alright.
I think it is not necessarily the case, given the feature may be approved by principle only, it doesn't mean the vendors are going to work on it, it could overall be added by external contributor (just like lambda short hand, and many other features).
The main cutoff for a small feature like this, I believe:
There are features that were approved despite they may not represent something extensively used, but because they made sense.
Not saying any of this necessarily applies here.
Note that I also come across
(fun options -> options.SetterProperty <- value)
_.SetterPropery <- value
, maybe it could in the future, it is used in lots of C# stuff from BCL AFAICS{ _ with SetterProperty <- value; AnotherOne <- anotherValue }
(or similar concept, but { _ ... }
being key here, but this may be very very far fetched.It remains that those patterns are indeed widespread and idiomatic (due to being open ended and not requiring lots of implementation to expose in an API):
'record -> 'record
Action<SettingsWithSetters>
"Sadly" maybe more than:
|> RecordType.setFoo value
.WithSetter(value)
fluent chaindespite codegeneration (such as myriad or source generators) enable this to be potentially low ceremony too.
So having shorthand and distinctive syntax for those constructs could be meaningful feature.
I suggest to define a shorthand lambda for record update expression
pros:
cons: