Discussion:
[dart-misc] Why do I need parens around this (method cascade)
Danny Tuppeny
2017-02-12 16:58:26 UTC
Permalink
I've had to put parents in this code ot make it compile but I don't really
understand why:

Serializers serializers =
(
_$serializers
.toBuilder()
..addPlugin(new StandardJsonPlugin())
).build();


As I understood it, the method cascade operator caused what was on its left
to be returned and the return value of the right side to be discarded.
Therefore, given this code:

Serializers serializers =
_$serializers
.toBuilder()
..addPlugin(new StandardJsonPlugin())
.build();


My expectation was that .build() would be called on the SerializersBuilder
that we called addPlugin on. However, It gives the error "The method
'build' isn't defined for class 'void'".

Have I misunderstood? It always worked as I expected before. Example 1 on Gilad's
post
<http://news.dartlang.org/2012/02/method-cascades-in-dart-posted-by-gilad.html>
actually shows the same, though it doesn't explain the parens :(
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
'Brian Wilkerson' via Dart Misc
2017-02-12 17:06:21 UTC
Permalink
Danny,

It's because of the relative precedence of the '.' and '..' constructs.

With the parentheses, you get what you're really trying to express:

Serializers serializers = _$serializers.toBuilder();
serializers.addPlugin(new StandardJsonPlugin());
serializers.build();


But without the parentheses, the code is equivalent to

Serializers serializers = _$serializers.toBuilder();
serializers.addPlugin(new StandardJsonPlugin()).build();


Brian
Post by Danny Tuppeny
I've had to put parents in this code ot make it compile but I don't really
Serializers serializers =
(
_$serializers
.toBuilder()
..addPlugin(new StandardJsonPlugin())
).build();
As I understood it, the method cascade operator caused what was on its
left to be returned and the return value of the right side to be discarded.
Serializers serializers =
_$serializers
.toBuilder()
..addPlugin(new StandardJsonPlugin())
.build();
My expectation was that .build() would be called on the SerializersBuilder
that we called addPlugin on. However, It gives the error "The method
'build' isn't defined for class 'void'".
Have I misunderstood? It always worked as I expected before. Example 1 on Gilad's
post
<http://news.dartlang.org/2012/02/method-cascades-in-dart-posted-by-gilad.html>
actually shows the same, though it doesn't explain the parens :(
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups
"Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
Danny Tuppeny
2017-02-12 17:09:41 UTC
Permalink
On Sun, 12 Feb 2017 at 17:06 'Brian Wilkerson' via Dart Misc <
Post by 'Brian Wilkerson' via Dart Misc
It's because of the relative precedence of the '.' and '..' constructs.
Gotcha! Can we change them around?

J/k; I'm sure it makes more sense this way, I just hadn't noticed it
before. Thanks! :-)
Post by 'Brian Wilkerson' via Dart Misc
Serializers serializers = _$serializers.toBuilder();
serializers.addPlugin(new StandardJsonPlugin());
serializers.build();
But without the parentheses, the code is equivalent to
Serializers serializers = _$serializers.toBuilder();
serializers.addPlugin(new StandardJsonPlugin()).build();
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
'Erik Ernst' via Dart Misc
2017-02-13 10:49:40 UTC
Permalink
Post by Danny Tuppeny
On Sun, 12 Feb 2017 at 17:06 'Brian Wilkerson' via Dart Misc <
Post by 'Brian Wilkerson' via Dart Misc
It's because of the relative precedence of the '.' and '..' constructs.
Gotcha! Can we change them around?
That would probably be too much. The grammar has the following rule:

cascadeSection:
‘..’ (cascadeSelector arguments*) (assignableSelector arguments*)*
(assignmentOperator expressionWithoutCascade)?


The expressionWithoutCascade at the end allows for a large set of
expressions on the right hand side of `=`, including method invocations,
and further assignments. This is quite convenient, especially in all those
"building" expressions which were a major reason for having cascades in the
first place, because you want to have "general expressions" available for
the value which is used to build each property.

The cascadeSection occurs in a couple of locations in the grammar, but the
most relevant one here is

expression:
conditionalExpression cascadeSection* | ...


This puts cascades at the very top of the expression derivation chain
(i.e., it has low precedence), which fits with the general notion that each
cascade section should be able to contain almost all kinds of expressions.

If you want to do anything in the direction of swapping the precedence of
`.` and `..` we'd need to append cascadeSection to some kind of expression
which has higher precedence (i.e., which is lower in the derivation chain)
than selector, but selector is already near the bottom:

postfixExpression: ... | primary selector*


We have '(' expression ')' as one of the alternatives in the rule for
primary, so that's at the very bottom where we can manually request a high
precedence (that of primary) for an expression of arbitrary precedence (
expression).

I think it would be a bad idea to give selector to a lower precedence,
because we want to be able to use method calls in expressions: For
instance, a.foo() + b.bar() shouldn't mean (a.foo() + b).bar().

So we can't really give `..` a high enough precedence and `.` a low enough
precedence to swap them.

Maybe somebody can come up with a really smart solution (that probably
changes major parts of the grammar), but my impression is that you'll have
to live with `(someExpression).build()` when the someExpression part
contains cascades.

J/k; I'm sure it makes more sense this way, I just hadn't noticed it
Post by Danny Tuppeny
before. Thanks! :-)
Post by 'Brian Wilkerson' via Dart Misc
Serializers serializers = _$serializers.toBuilder();
serializers.addPlugin(new StandardJsonPlugin());
serializers.build();
But without the parentheses, the code is equivalent to
Serializers serializers = _$serializers.toBuilder();
serializers.addPlugin(new StandardJsonPlugin()).build();
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups
"Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an
--
Erik Ernst - Google Danmark ApS
Skt Petri Passage 5, 2 sal, 1165 KÞbenhavn K, Denmark
CVR no. 28866984
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
Loading...