Skip to content
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

Allow more concise function literal argument #343

Open
eernstg opened this issue May 8, 2019 · 4 comments
Open

Allow more concise function literal argument #343

eernstg opened this issue May 8, 2019 · 4 comments
Labels
request Requests to resolve a particular developer problem

Comments

@eernstg
Copy link
Member

eernstg commented May 8, 2019

A Dart function invocation requires parentheses, e.g., f(42). Other languages can be more concise.

Functional languages like Haskell and SML use an "empty" operator (a space), e.g., f 42. With curried invocation this extends to several arguments (f 42 true), but curried function invocation would be a radical change for Dart, and simultaneous invocation with multiple arguments in functional languages still require parentheses, because we're passing one value which is a tuple (f (42, true)). This seems to indicate that Dart cannot easily use this approach.

However, some languages exploit special properties of the declaration (like being the last parameter) and the call site (like passing a function literal, rather than an arbitrary argument), and that allows the concise form using just a space.

For example, a Ruby function invocation can have an 'associated block' which is passed using a mere space (example from Ruby core Array doc):

arr = [1, 2, 3, 4, 5, 6]
arr.select {|a| a > 3}

In the callee, it's possible to test whether such a block was given (block_given?) and call it (yield), but here we are just interested in the fact that we a block is passed at the call site using a concise syntax.

Kotlin uses a similar syntax to pass a lambda as the last argument in a function invocation. Here is an example which is at the same time an example of a type-safe builder:

class HTML {
    fun body() { ... }
}

fun html(init: HTML.() -> Unit): HTML {
    val html = HTML()
    html.init()
    return html
}

// Invoke `html`, using a mere space to pass the argument `{...}`.
html {
    body()
}

This issue is a request for a similar kind of conciseness in Dart. It may seem like a tiny thing, but it is probably going to be used in a large number of locations.

@eernstg eernstg added the request Requests to resolve a particular developer problem label May 8, 2019
@sczerniawski
Copy link

[This is also re #344]

I'm surprised that nobody mentioned Haskell's $ operator.

f a b c   = (((f a) b) c)  -- f(a, b, c) in languages without currying like dart
f a $ b c = ((f a) (b c))  -- f(a, b(c))

I'm mentioning this only as an example of a syntactic structure that solves the ambiguity problem. $ is probably not a good token to use in dart.

@munificent
Copy link
Member

munificent commented Jun 7, 2019

but curried function invocation would be a radical change for Dart, and simultaneous invocation with multiple arguments in functional languages still require parentheses, because we're passing one value which is a tuple (f (42, true)). This seems to indicate that Dart cannot easily use this approach.

Yes. Ruby has optional parentheses and it gets really weird. To avoid some ambiguous cases, the language actually makes a space before ( significant in some places and produces an error when it's omitted. Consider:

sqrt (1 + 2).abs + 3;
sqrt(1 + 2).abs + 3;

I think making parentheses optional is profoundly confusing in a C-derived syntax.

@Wdestroier
Copy link

Wdestroier commented Mar 23, 2024

Could

numbers.map(it: it + 2)

be an improvement over

numbers.map((it) => it + 2)

?

EDIT: I talked to Randal Schwartz and he pointed out this syntax is ambiguous with named parameters.

@Abion47
Copy link

Abion47 commented Jun 14, 2024

I forget what language it was, but I remember seeing a lambda shorthand that, when there was only one parameter, it allowed forgoing the parameter list entirely by implicitly defining a val parameter (or something similar):

numbers.map(=> val + 2);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
request Requests to resolve a particular developer problem
Projects
None yet
Development

No branches or pull requests

5 participants