Optional brackets around lambda expression (was: Expected distribution of lambda sizes)
Ali Ebrahimi
ali.ebrahimi1781 at gmail.com
Thu Jun 16 03:19:24 PDT 2011
Hi, how about this one:
process( x -> x + 1 );
process( x -> { return x + 1; } );
process( x -> {
if (x == 0) {
return 0;
}
return x + 1;
});
Ali Ebrahimi
On Thu, Jun 16, 2011 at 1:33 PM, Stephen Colebourne <scolebourne at joda.org>wrote:
> I believe I agree with Steven and Reinier that the strawman syntax
> family would be best with only one paren for expressions:
>
> process( #(x) x + 1 )
> process( #(x) { return x + 1; } );
> process( #(x) {
> if (x == 0) {
> return 0;
> }
> return x + 1;
> });
>
> The one less paren helps me read the code, compared to this:
>
> process( #(x) (x + 1) )
>
> (Of course, users might choose to add the parens themselves, as thats
> legal for any expression)
>
>
> I have mixed feelings on supporting a lone expression within the
> block. Thats because I'm unconvinced that the equivalent for a method
> is as readable as using a "return":
>
> process( #(x) {x + 1} ); // reads well enough to me
> public String getSurname() {surname} // doesn't read quite as well to me
>
>
> For other syntax families, I also suspect that I prefer that the
> expression itself does not require being surrounded by parens.
>
> Stephen
>
>
> On 16 June 2011 07:55, Reinier Zwitserloot <reinier at zwitserloot.com>
> wrote:
> > My gut instinct was: That's a really bad idea. But I decided to play
> around
> > with it anyway and it actually resulted in easier to scan code (to me,
> > anyway). The use cases I've worked on before indeed usually boil down to
> > passing the closure straight into a method as an argument, and in such
> cases
> > it's better. As Pavel said, if you treat the closure preamble (the => or
> the
> > #() or whatever the syntax calls for) as an operator with low precedence,
> it
> > works out.
> >
> > This way the strawman syntax almost seems to have that best of both
> worlds
> > scenario: It looks good both for long and one-liner closures. Passing
> > closures inline as argument to a method, i.e. the map/filter usecase,
> looks
> > a lot cleaner when you lose a closing brace/paren.
> >
> > Precedence-wise, if you want to exit the closure scope, you have to
> resort
> > to this:
> >
> > int ageOfJoe = (#(Person x) x.getAge()).invoke(joe);
> >
> > which is different from what traditional strawman wanted you to do:
> >
> > int ageOfJoe = #(Person x) (x.getAge()).invoke(joe);
> >
> > Personally I found it easier to scan the new form vs. the old one (i.e.
> its
> > easier to see in the top version that the toString applies just as much
> to
> > the #(Person x) part as the x.getAge() part), so this is not necessarily
> a
> > bad thing.
> >
> > I don't think its necessary but this proposal can be extended by allowing
> > braces for single expressions, i.e:
> >
> > int ageOfJoe = #(Person x) {x.getAge()}.invoke(joe);
> >
> > though I'm not sure how easy it is to implement this in an LL(k) parser
> > (you'd have to conflate the first statement/expression as 'its one of
> those
> > two', then scan for either a semicolon or the closing brace, at which
> point
> > you have to go back and doublecheck that the statement or expression you
> > parsed is actually an expression if there wasn't one, or actually a
> > statement if there was. That's different than what javac currently does;
> it
> > always knows if it wants a statement or an expression, it never needs to
> > parse an 'it's one of those'. ecj will have any problem with this as it
> > already junks statements and expressions into the same pile.
> >
> >
> > --Reinier Zwitserloot
> >
> >
> >
> > On Wed, Jun 15, 2011 at 10:42 PM, Pavel Minaev <int19h at gmail.com> wrote:
> >
> >> Note that this applies also to "Redmond syntax" in general; e.g.:
> >>
> >> new User().use(x => x + "a string");
> >>
> >> However, I do not recall it ever being a problem in C# in practice, nor
> did
> >> I ever hear of complaints about that in C#. In general, lambda syntax is
> >> treated as a sort of "lambda operator" =>, with a certain "precedence",
> and
> >> said "precedence" is lower than any other operator - in this case, lower
> >> than "+". In that sense, it's not much different than correctly parsing
> >> expressions such as a || b && c.
> >>
> >> On Wed, Jun 15, 2011 at 1:35 PM, Yuval Shavit <yshavit at akiban.com>
> wrote:
> >>
> >> > What would happen with something like:
> >> >
> >> > public interface Sam {
> >> > String doSomething(String arg);
> >> > }
> >> > public class User {
> >> > public void use(Sam sam) { System.out.println("saw a sam"); }
> >> > public void use(String string) { System.out.println("saw a
> string"); }
> >> > }
> >> >
> >> > new User().use( #(x) x + "a string" );
> >> >
> >> > In that context, which are we passing?
> >> > - lambda that takes a String, concatenates "a string" to it and
> returns
> >> > the result
> >> > - a string consisting of (lambda x -> x).toString() concatenated
> with
> >> "a
> >> > string"
> >> >
> >> > This is just one simple and somewhat contrived example, but the point
> is
> >> > that without braces or something similar, it's not too hard to come up
> >> with
> >> > a situation where it's not clear where the lambda ends and the rest of
> >> the
> >> > expression begins.
> >> >
> >> > On Wed, Jun 15, 2011 at 4:18 PM, Steven Simpson <ss at comp.lancs.ac.uk>
> >> > wrote:
> >> >
> >> > > On 13/06/11 21:10, Pavel Minaev wrote:
> >> > > > Statement lambdas would typically be thus wrapped, yes
> >> (coincidentally,
> >> > > it's
> >> > > > also why I'd prefer to have a separate form for expression lambdas
> >> > which
> >> > > > does not include the {} so as to be visually distinct from
> statement
> >> > > > blocks).
> >> > >
> >> > > Yes, I think I'd appreciate that visual distinction too. Is it
> >> possible
> >> > > to have an unambiguous expression syntax not requiring any form of
> >> > > brackets around either the whole lambda or its body?:
> >> > >
> >> > > #() 3
> >> > > #() 3 + 4
> >> > > #(x) x + 1
> >> > > #(x, y) x + y
> >> > >
> >> > > When used like this, they will likely be in argument lists, so they
> are
> >> > > naturally delimited by commas and the list-terminating bracket, and
> >> need
> >> > > no brackets of their own. IOW, #() would have quite a low
> precedence,
> >> > > and any brackets put around it would be part of existing syntax
> (e.g.
> >> > > for normal expressions and argument lists).
> >> > >
> >> > > If you had one lambda in the body of another, it will likely have to
> be
> >> > > inside an enclosed call, whose brackets will naturally delimit it:
> >> > >
> >> > > #(a) a + process(#(b) b * b) + 10
> >> > >
> >> > > If it wasn't so embedded, you could always put normal expression
> >> > > brackets around it:
> >> > >
> >> > > #(a) a + (#(b) b * b).invoke(a)
> >> > >
> >> > > (And that's a little contrived. And possibly quite difficult to
> >> > > type-infer…?)
> >> > >
> >> > > I don't think you could drop the parameter-list brackets too, as
> that
> >> > > would make parsing much more complex (e.g. #a + a). Looking at that
> >> > > more positively, it would keep lambda syntax and appearance
> obviously
> >> > > distinct from method literals. ("#(" => Bam! I'm a lambda!) The
> >> > > presence of braces would then further distinguish lambda expressions
> >> > > from lambda statements.
> >> > >
> >> > > In summary, we require brackets around neither the lambda expression
> >> nor
> >> > > its body. We are then forced to used some around the parameter
> list,
> >> > > but take advantage of this as the constant discriminant of lambda vs
> >> > > method literal.
> >> > >
> >> > > Applied to some other expressions seen on the list lately:
> >> > >
> >> > > list.filter( #(t) t.length() > 3 )
> >> > > .map( #(t) t.barCount )
> >> > > .max();
> >> > >
> >> > > students.filter(#(s) s!=null && "Smith".equals(s.getName()))
> >> > >
> >> > > List men = personList.filter(#(p) p.isMale());
> >> > >
> >> > > List<Double> adjustedPrices =
> >> > > prices.map(#(price) price + getShipping());
> >> > >
> >> > > Cheers,
> >> > >
> >> > > Steven
> >> > >
> >> > >
> >> > >
> >> >
> >> >
> >>
> >>
> >
> >
>
>
More information about the lambda-dev
mailing list