-
Notifications
You must be signed in to change notification settings - Fork 21
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
Simplify use of child scopes inside computation expressions #1000
Comments
I really like that fsharp allows to do this: let step(objects:List<MassObject>, newObjects:List<MassObject>, i:int, h:float) =
let awsum, vwsum =
// ... lots of intermediates
newObjects.[i].position <- newObjects.[i].position + h*vwsum
newObjects.[i].velocity <- newObjects.[i].velocity + h*awsum out of let step(objects:List<MassObject>, newObjects:List<MassObject>, i:int, h:float) =
// everything under the same scope
// ... lots of intermediates
let awsum = // ...
let vwsum = // ...
newObjects.[i].position <- newObjects.[i].position + h*vwsum
newObjects.[i].velocity <- newObjects.[i].velocity + h*awsum So translating this into CE land to remove the noise is a great idea.
If that was another suggestion, I would not upvote that separate suggestion, so I'm ambivalent and biased against the anonymous-bang operator just on the face of it looking a bit alien / causing operator soup. |
Please don't nail me on that operator or on the concrete syntax. It could also be a keyword or whatever. The point I tried to make is: We should provide syntactic sugar for
in a way where |
@ronaldschlenker not nailing you, sorry! Just trying to be thorough so that my upvote comes with more context. Looking for other approach than I'll try to better understand the fineprint of the generalization you are conveying with that aspect, but it may take me more time, like unbounded 🙂 |
No need be bo sorry, @smoothdeveloper ! I thought "nailing" was more like a joking term - so absolutely no offense from my side! :)
I don't quite understand what you mean. In case my explanation was not clear, I try to clarify: This let result : Task<int> = (!! Task.FromResult 1) + 2 could be translated to this: let result : Task<int> = Task.map (Task.FromResult 1) (fun x -> + 2) |
It's also very annoying with branches let getData id includeAdditional = async {
let! data = get id
// nope :(
// let additional =
// if includeAdditional then
// let! x = getAdditional id
// x
// else
// []
// instead
let! additional =
if includeAdditional then
getAdditional id
else
async { return [] } // oh no, pointless allocation and overhead
return data, additional
} |
Thanks for the additional variation, I was implying at the stage I am, maybe as it is hard to grok I'm not super versed with CE and still susceptible to trip on dealing with the binding and having the right semantic when I nest them. The main suggestion, I'm confident it will help me, the |
I think a better name for the operator would be let a = id! 1 equivalent to let! a = 1 |
Anonymous bang corresponding to For example it would be nice if instead of the following code (based on an example in Validus documentation) // Construct Person if all validators return Success
validate {
let! first = nameValidator "First name" input.FirstName
and! last = nameValidator "Last name" input.LastName
and! email = emailValidator "Email address" input.Email
and! age = ageValidator "Age" input.Age
and! startDate = dateValidator "Start Date" input.StartDate
let name =
{ First = first
Last = last }
let person =
{ Name = name
Email = email
Age = age
StartDate = startDate }
return person
} you could write // Construct Person if all validators return Success
validate {
let name =
{ First = !!(nameValidator "First name" input.FirstName)
Last = !!(nameValidator "Last name" input.LastName) }
let person =
{ Name = name
Email = !!(emailValidator "Email address" input.Email)
Age = !!(ageValidator "Age" input.Age)
StartDate = !!(dateValidator "Start Date" input.StartDate) }
return person
} Though I don't know if it would be possible to have same operator both for |
I propose to add a mechanism that allows for implicit use of builder methods in child scopes when being inside of a computation expression.
Today, we have to start new CEs when not being at top level scope of a surrounding CE.
In this example, a second
task
workflow has to be started in order to be usable in the child scope of thelet! b ...
body:This would become:
In addition, it could be possible to introduce an anonymous bang, so that this:
becomes this:
(I use !! in the example as a placeholder for the anonymous-bang operator.)
Pros and Cons
.+
,.*
, etc. ambiguous. In C#, this is also possible today, where you can write something like this:(await Task.FromResult(new [] {1,2,3})).Select(x => x + 1);
The disadvantages of making this adjustment to F# are not obvious to me from a users point of view.
Extra information
Estimated cost (XS, S, M, L, XL, XXL): I can't tell because I'm not familiar with the F# compiler code. I guess it might be quite complex (L - XL?)
Related suggestions:
Affidavit (please submit!)
Please tick this by placing a cross in the box:
Please tick all that apply:
For Readers
If you would like to see this issue implemented, please click the 👍 emoji on this issue. These counts are used to generally order the suggestions by engagement.
The text was updated successfully, but these errors were encountered: