Syntactic sugar for method chaining / fluent interfaces Syntactic sugar for method chaining / fluent interfaces Syntactic sugar for method chaining / fluent interfaces

Marek Kozieł develop4lasu at gmail.com
Thu Dec 1 02:21:00 PST 2011


Hi.
I can agree that many ppl would be happy about such solution. But
while it's language change the main question is: "What harm can it
bring to language?"

Problem lay on interfaces/classes that already exists.
'void' have more than one meaning now time:
1st: there is no need to return anything.
2nd: creator wanted to prevent from chaining - to force one line-one
call formating.
3rd: space for future return type was left.
what's more
allowing mixing void with this would bring ppl to use DoNotTouch class
as force to maintain previous void meaning.
because of above reasons I suggested void+this solution.

I really wonder if language can be harmed in order to fix things that
was written in wrong way.

Unfortunately any change into types system can be pretty heavy as well.


2011/11/22 Eirik Lygre <eirik.lygre at gmail.com>:
>
>
> On Mon, Nov 21, 2011 at 3:07 PM, Marek Kozieł <develop4lasu at gmail.com>
> wrote:
>>
>> 2011/11/20 Eirik Lygre <eirik.lygre at gmail.com>:
>> > It seems that the various Java SE 8 projects have lots of care for
>> > simple
>> > and expressive code, for example as demonstrated by the "Language /
>> > Library
>> > / VM co-evolution in Java SE 8" presentation from Devoxx. Hence, I
>> > wonder
>> > if there is any interest for reviving an older suggestion about simple
>> > method chaining / fluent interface.
>> >
>> > I'm not really qualified to suggest the formal syntax, but it probably
>> > boils down to this:
>> >
>> >    A void method call "object.function(...)" evaluates to the object
>> > itself
>> >
>> > This will be syntactic sugar (compiler only, no jvm changes), making it
>> > possible to chain method calls across void methods. For example:
>> >
>> >    Socket so = new SSLSocket()
>> >                .setSendBufferSize(1024)        // void
>> > Socket.setSendBufferSize(int)
>> >                .setReceiveBufferSize(1024)     // void
>> > Socket.setSendBufferSize(int)
>> >                .setNeedClientAuth(true);       // void
>> > SSLSocket.setNeedClientAuth(boolean)
>> >
>> > A couple of points on the rationale for the suggestion:
>> >
>> > * First, it will enable method chaining on a large body of existing
>> > code.
>> > The javabeans spec says that setters should return void, and this
>> > suggestion would automatically allow fluent use of such beans.
>> >
>> > * It will allow a level of fluent interfaces that are otherwise not
>> > possible, in that it will simulate a "self" return type. If you want to
>> >  implement a fluent interface today, you would return your own type. If
>> > somebody then created a subclass, and wanted to maintain fluency, they
>> > would have to override all parent methods, as shown below. Of course,
>> > this
>> > means that fluent methods added to the superclass must also be added to
>> > all
>> > subclasses, which isn't really an ideal situation if you want to evolve
>> > an
>> > api.
>> >
>> >    class Socket {
>> >        Socket setSendBufferSize(...);   // Can be chained
>> >    }
>> >
>> >    class SSLSocket extends Socket {
>> >        SSLSocket setSendBufferSize(...) {                      // Change
>> > return type, to maintain chainability
>> >            return (SSLSocket)super.setSendBufferSize(...);     // Cast
>> > required.
>> >        }
>> >    }
>> >
>> > This is not a new idea. It was suggested for project coin, where there
>> > are
>> > more references:
>> >
>> > * It was suggested for project coin by Ulf Zibis (
>> > http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/001180.html).
>> > * I've not found much discussion, other than a quick email from Joe
>> > Darcy (
>> > http://mail.openjdk.java.net/pipermail/coin-dev/2009-May/001768.html),
>> > where the idea is rejected: "While fluent interfaces are fine, I don't
>> > think using a language change  to retrofit this pattern of API usage on
>> > code not written that way is  the best use of the language change
>> > budget."
>> >
>> > While it was considered (and rejected) for SE 7, it might still be
>> > proper
>> > for SE 8. Method chaning / fluent interfaces are used in pretty much all
>> > lambda examples, as a useful code pattern. I think it's useful, too, and
>> > think it should be made easier accessible across the language.
>> >
>> > I've got two hopes for this email:
>> >
>> > * First, feedback on whether the community considers this to be useful,
>> > or
>> > not
>> > * Second, feedback on how to proceed, if it is in fact considered useful
>> >
>> > Eirik Lygre
>> > eirik.lygre at gmail.com
>> >
>>
>>
>> There are more reasons against.
>> One of the most important problem occurs when void will be changed
>> into other type in future.
>>
>> How hard to track bugs can be when new return type will have same
>> methods as 'this'? 'Return 'this' proposal' was made to fill that gap.
>> Some of discussion can be found under (but there where more about it):
>> http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000523.html
>>
>>
>> and little under:
>> http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000107.html
>>
>> --
>> Regards.
>> Lasu aka Marek Kozieł
>
> Since you give only one example, I'll have to limit my comment to that
> one. On the other hand, you have a suggestion for an alternative syntax
> to the same problem, so I guess we have a common goal :-)
> You say that the problem occurs when "void will be changed into
> other type in the future". That problem, however, applies to any fluent
> interface, whether manually specified, using the mechanism I described,
> or the mechanism you described. For example, using an abstract
> class that writes to somewhere:
>     class Output {
>         public Output append (char c);  // Manual fluent interface
>         public void append (CharSeq csq); // My suggestion
>         public this append (CharSeq csq, int s, int e); // Your suggestion
>     }
> Now, all of these would suffer from hard debugging if the return type
> was changed from one of Output, void or append to, say,
> java.lang.Appendable, as the following would all compile:
>     // All of these will first call Output.append(), then
>     // Appendable.append
>     new Output().append('a').append('b');
>     new Output().append("a").append("b");
>     new Output().append("a",0,1).append("a",0.1);
> My suggestion has the advantage, or disadvantage, of "just
> working" with a lot of existing api's (including all api's that
> comply to the javabeans specification). To me, that is a
> great advantage.
> It is correct that opening for auto-fluency using void methods,
> or whatever this proposal should be called, will "lock down"
> existing void methods. However, that is pretty much the
> case already today, since changing the return type of a
> method will invalidate any subclass which tries to override
> the method ("sub cannot override func() in super;
> attempting to use incompatible return type")
> And, the benefits are there. They are not purely cosmetic,
> but also functional.
> * It will significantly simplify fluent programming
> * It will enable fluent apis that cannot be made today
> * It will enable fluent thinking on existing code
> * No existing programs will fail or change behavior
> --
> Eirik
>
>



-- 
Pozdrowionka. / Regards.
Lasu aka Marek Kozieł

http://na-chlodno.blogspot.com/
http://lasu2string.blogspot.com/


More information about the jdk8-dev mailing list