Replies: 44 comments
-
Hi, Thanks. This was briefly discussed here: The syntax I'm considering is
One thing I'm worried about is that it's very easy easy to write unreadable code with complex nested maps. I'm not sure what is the best way to prevent this. |
Beta Was this translation helpful? Give feedback.
-
Summarizing my comment from that issue: That lambda syntax is not very general, it doesn't allow multiple lambda arguments. |
Beta Was this translation helpful? Give feedback.
-
I believe that a explicit declaration of the lambda but implicit parameter inference could work together: doubled_ints := ints.map(_ * 2) // What does _ mean? Is it a number? A variable? However, a doubled_ints := ints.map(fn _ * 2) //Oh, _ is part of a function Parameters could be added at will: doubled_ints := ints.map(fn (x) x * 2) However, implicit return would aid in increasing readability |
Beta Was this translation helpful? Give feedback.
-
It's often good to have meaningful names for parameters to help the reader, even for lambdas. What if any single underscore prefixed identifiers odd := container.filter(
fn _elem & 1)
sum := container.reduce(
fn _total + _elem)
container.sort(
fn _a < _b) |
Beta Was this translation helpful? Give feedback.
-
doubled_ints := ints.map({ return it * 2 }) like kotlin |
Beta Was this translation helpful? Give feedback.
-
So, considering all your opinions, I think the syntax for lambda expressions should follow the following rules:
Lambdas in V would support Target Typing. fn map(arr int[], func fn (int) int) int[] {
// Do the mapping
} And later: map([1, 2, 3], fn (x /* int type inferred */) /* return type int inferred */ { return x * 2 }) Rule 1. All lambdas are prefixed with Rule 2. Lambdas follow the syntax regulations for normal functions, with the exception that the alphanumeric identifier after Rule 3. Lambdas that take no parameters may omit the repeat(3, fn {
println("Hello World!")
}) Rule 4. Lambdas that consist of only one doubled_ints := ints.map(fn (x) x * 2) Rule 5: Rule 3 and Rule 4 may be used together: list_of_threes := ints.map(fn 3) Rule 6: Marking a valid name with a doubled_ints := ints.map(fn x! * 2)
total := ints.reduce(fn total! + value!) Translation to V (as of now): fn main(){
products := zipWith(fn x! * y!, [1, 2, 3], [4, 5, 6]) // ==> [4, 10, 18]
} At compile time it would become: fn lambda_1 /*unique name generated by compiler*/ (x int, y int) int {
return x * y;
}
fn main(){
products := zipWith(lambda_1, [1, 2, 3], [4, 5, 6]) // ==> [4, 10, 18]
} Tell me what you think of this "proposal" for V lambda expressions. |
Beta Was this translation helpful? Give feedback.
-
V is a simple language. You just introduced 6 extra rules that have to be learned. Rule 3 means that there are now 2 different ways to write lambdas without parameters. One of V's main philosophies is to have only one way of doing things. So ideally, no new syntax would have to be introduced at all, just like in Go:
map, filter, etc often have one liners, so I propose the
@ntrel It won't be possible to declare a variable named For multiple arguments the traditional syntax will be used with full types specified. I think omitting the type is only readable when there's only one argument, the function is simple, and it's clear what the type is, like in the |
Beta Was this translation helpful? Give feedback.
-
I agree syntax rules should be simple. This cuts out the return keyword and the noise of the braces, but still supports naming parameters and more than one parameter. It is also much closer to anonymous function syntax than just
|
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
@medvednikov makes a convincing argument. There should only be one way of doing things. V should support support lambdas that look just like functions without names. However, I still feel like the |
Beta Was this translation helpful? Give feedback.
-
@medvednikov how would you feel about something like doubled_ints := ints.map(& * 2) It also has a familiarity to it for anyone that's used Ruby or SASS (maybe others too, idk). |
Beta Was this translation helpful? Give feedback.
-
Why do not just use the same syntax that it is used in named fn?. Using any hidden trick like _, & or 'it' adds confusion to the reader, limits parameters to 1 and does not support nested lambdas. You could try to remove {} as @N8python suggested to make it "cleaner" when it is a one liner:
One thing to discuss should be if the return type is mandatory or always infered. |
Beta Was this translation helpful? Give feedback.
-
I agree with @aguspiza that the best syntax for one liners would be |
Beta Was this translation helpful? Give feedback.
-
@aguspiza the point behind the shorter syntax is just that, it's shorter and more concise for simple operations. I know in Ruby I use it all the time for I know some people aren't fans of syntactic sugar like that, but it does make things a bit more concise. Of course we should still have a full lambda syntax, and for that I agree that the |
Beta Was this translation helpful? Give feedback.
-
It's used in many popular languages with functional features like Scala, Swift, Ruby, Kotlin. I wouldn't call it confusing.
So now we have 3 lambda syntaxes :) |
Beta Was this translation helpful? Give feedback.
-
Shouldn't this wait to be closed until the feature is actually added? |
Beta Was this translation helpful? Give feedback.
-
Ok, I’ll reopen it.
… On Jul 16, 2019, at 5:21 PM, Chris Watson ***@***.***> wrote:
Shouldn't this wait to be closed until the feature is actually added?
—
You are receiving this because you modified the open/close state.
Reply to this email directly, view it on GitHub <#1066?email_source=notifications&email_token=AKKMMKEB5V2UNXJ7SKBZ4MTP7Y3VVA5CNFSM4H7I6LTKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD2CGETY#issuecomment-511992399>, or mute the thread <https://github.com/notifications/unsubscribe-auth/AKKMMKAFIN3BBLKCFWD3K5DP7Y3VVANCNFSM4H7I6LTA>.
|
Beta Was this translation helpful? Give feedback.
-
Having closure syntax as anonymous functions is fine and is very inline with the "one-way" philosophy. But there are two different places where they are used, and I would like to have different approach towards argument types declaration: one thing when you declare the function taking function or closure as argument, another one is when you use it: fn (a mut []int) map(func fn (x int) int) { ... } but [1, 2, 3].map(fn (x) x * 2) I would like to have it this way. |
Beta Was this translation helpful? Give feedback.
-
Actually ints.map((x) => { return x * 2 } syntax let you write any lambda in JS. Implementing was NOT very hard so they create additional options to do so (some archaic ones are with 'function' keyword). In my opinion lambda syntax SHOULD be different because it lets you find where lambda function is very quickly. If you will have just fn keyword and nest several functions in one another it will be hard to check what's going on. Here you have two factors: no name and arrow syntax. Look at Pony, Haskell, Coconut etc. |
Beta Was this translation helpful? Give feedback.
-
I understand. However, I dislike the arrow syntax if you already have the ints.map(fn (x) x * 2) would be a good compromise. |
Beta Was this translation helpful? Give feedback.
-
@medvednikov I think this is the best way to go, anonymous (lambda) function definition shall be exactly like a standard definition, but without the need of a name I also encourage that functions in general require at least one "return" statement, there should be no implicit return values allowed, which makes it more readable especially when there is nothing to return like "none". |
Beta Was this translation helpful? Give feedback.
-
You could find them all with a regexp, although probably you'd be looking for a specific usage instead and search for e.g.
This seems fine: strings.filter(
fn (s) s.find(
fn (c) c.is_alpha()) != none) Given that if and match expressions implicitly yield a result, it seems a bit odd not to have that for lambdas, which are meant to be short (otherwise they're just function literals). Even requiring braces without return would be better than requiring return. |
Beta Was this translation helpful? Give feedback.
-
How about the "it" keyword? Like in Kotlin lambdas: Short lambda
Long lambda
Typed short lambda
Typed long lambda
"Brackets" short lambda
"Brackets" long lambda
Lambda with receiver
|
Beta Was this translation helpful? Give feedback.
-
Short optimized filter/map have been implemented:
For everything else the same syntax ( |
Beta Was this translation helpful? Give feedback.
-
That's awesome! I like the balance between implicit and explicit - shorthand syntax for common cases, and more verbose syntax for the uncommon ones. This is a great resolution. |
Beta Was this translation helpful? Give feedback.
-
That was exactly the reasoning :) Glad you like it. |
Beta Was this translation helpful? Give feedback.
-
I think the real issue is type inference, which is very powerful, but not easy to implement. The syntax |
Beta Was this translation helpful? Give feedback.
-
Return type inference is very easy to implement and would not slow down the compiler: fn (x int) {x * 2} I would limit it to a single expression.
map, filter and sort (each only on arrays) does not cover all the common cases. |
Beta Was this translation helpful? Give feedback.
-
Still hoping for a syntax where the callback's typing is infered from the initial definition. Having only a few methods sprinkled throughout with the Hoping this will bepicked back up eventually and improved on :) |
Beta Was this translation helpful? Give feedback.
-
What about recursive lambdas? |
Beta Was this translation helpful? Give feedback.
-
V is a concise and elegant language, and I think a syntax for lambda expressions could go along with the spirit of V. A lambda could be declared just like a function but without a name:
However, lambdas would have some additional convinces compared to regular functions. Target Typing would allow the lambda to drop the types on it's parameters.
Furthermore, if the lambda consists of a single
return
statement, the braces may be emitted and the return will be implicit:If the lambda doesn't take any parameters, the parens after
fn
may be omitted:The implicit return and parameterless
fn
could be combined:Closure could be implemented once V is more mature. For now, the ability to create anonymous functions would be a huge help to V programmers seeking a more functional style.
Beta Was this translation helpful? Give feedback.
All reactions