ceylon icon indicating copy to clipboard operation
ceylon copied to clipboard

Invocation syntax for functions accepting single argument lambdas

Open lucono opened this issue 8 years ago • 68 comments

A very common scenario in many projects and libraries is one involving functions which accept a single argument, where the single argument is a zero- or single-argument function or lambda. In these cases, it would be useful to have a syntax which allows the body of the lambda directly in the function call's braces without needing to wrap the lambda with additional curly braces, improving readability quite a bit.

The syntax would need to be able to disambiguate this usage from other possible usages of the named argument function invocation syntax.

To invent a fictional implementation as an example, one might be similar to the invoke operator but where the opening curly brace of the named argument invocation syntax is immediately followed by a colon, resulting in a new function invocation operator which opens with {: as an indicator that the invocation braces directly contain the body (i.e. not wrapped in additional curly braces) of the single lambda argument being supplied.

{Integer*} ints = { 1, 2, 3 };

// 1.

ints.each((it) => print(it));      // today
ints.each {: print(it) };          // after - lambda statements directly in {: } invoke operator

// 2.

ints.map((it) {                    // today
    print(it);
    return it * 2;
});

ints.map {:                        // after - single param list ommitted
    print(it);
    return it * 2;
};

// 3.

ints.map((it) => it * 2);          // today
ints.map {: => it * 2 };           // after - with fat arrow for explicit return

Basically:

  • For single-argument lambdas, a special keyword (e.g. it) only available inside the lambda could be supported for accessing its single argument, and the need for an explicit parameter list relaxed. (Nested lambdas that would create nested its or shadowed its could be disallowed).
  • When using the new syntax, relax the requirement for a terminating ; at the end of the last statement or expression within the lambda block, as the ambiguity with other possible usages of the name argument syntax would not exist when using the new invoke operator. This will particularly eliminate the noise of the terminating semi-colon ; for lambdas with a single statement or expression.
  • For single expression lambdas that return a value, the fat arrow is used to satisfy explicit return.
  • Finally, for multi-argument lambdas, which is not a primary use-case of this feature, the argument list could be between the opening curly { and the colon :, surrounded by parentheses.

ints.sort((a, b) {          // today
    print("``a`` +");
    print(b);
    return a <=> b;
});

ints.sort {(a, b):          // after
    print(a);
    print(b);
    return a <=> b;
};

lucono avatar Aug 13 '17 03:08 lucono

There is a withAnimation prop on the Carousel:

<Carousel
        loop={false}
        width={carouselContentWidth}
        pagingEnabled
        snapEnabled
        mode="parallax"
        data={...}
        renderItem={renderItem}
        withAnimation={{
          type: 'timing',
          config: {
            reduceMotion: ReduceMotion.Never,
          },
        }}
      />

matt-livekindred avatar Apr 03 '24 01:04 matt-livekindred