Re-2: What does a Consumer consume?

Thomas Münz t.muenz at xdev-software.de
Thu Apr 11 06:42:01 PDT 2013


Thanks for the detailed explanation(s), Brian.


I'm tempted to disagree on the equal naming topic for architectural reasons (I very often encountered a "ouh that has to implement multiple functional interfaces, damn" situation - but literally every time minutes later, I saw that independent of the method naming, it's not desirable to have a class to act as all kinds of functional instance with its public methods).
HOWEVER
Stability alone (or the people-will-want-it-anyway "joker") is enough reason to prefer differently named methods, no doubt.
That's also the reason why I will end up getting along with "Predicate#test()".



The other explanation was indedd very helpful, thanks again.

Of course things can't be reopened just because some random guy has doubts. Would be pretty ridiculus to assume that.
The intention was more to give proper arguments and (only) if they suffice it should be possible if not mandatory to reopen the topic.
If they don't, then well okay, I tried.

I still don't see where the logic behind the "consuming" terminology is (following your argument, wouldn't it have to be named "Acceptor" or so to express its larger role, but don't cause any confusion about consuming anything?).
I still don't see why there's a straight forward named Function (instead of "Transformer" for its larger role) but its "brother" shape has such an indirect name all of a sudden. Doesn't seem very consistent.
AND I still see millions of developers getting confused about why they have to set a "consumer" on their collections if all they want is to iterate it.

Nevertheless, I can live with the explanation, although with a serious headache.
At least "Consumer" is way better than "Block" ;P.


Thank you and keep up the nice work =)




Original Message Re: What does a Consumer consume? (11-Apr-2013 15:01)
From:   Brian Goetz
To:Thomas Münz


> 2.) All the functional types have a unifiedly named method "apply". A
> function is applied to an entity. A predicate can apply to an entity
> (honestly: who says "the predicate tests the entity" in common
> speaking? I think 90% say "if the predicate applies to the entity,
> then...") As a side node: colliding method names are irrelevant
> because in practice you never come accross a case where a concrete
> implementation has to implement a procedure and a predicate or so.
> Such cases are done by internal separated delegates anyway, not by
> directly implementing multiple interfaces.

You might get to dismiss the issue of multiple interfaces within your 
small system (which you probably control to some degree.) We play in an 
infinitely bigger sandbox. Saying "No Java developer will ever be 
allowed to implement multiple functional interfaces" would have been 
outright hubris. Setting it up so that it worked 90% of the time but 
not all the time would have made a lot of developers unhappy. Therefore 
the "all different" rule was more stable than the "all same" rule.

There were many other aspects to this issue as well, of course. These 
issues were analyzed and discussed to death.
 Original Message processed by David.fx12  
Re: What does a Consumer consume? (11-Apr-2013 15:02)
From:   Brian Goetz
To:Thomas Münz
Cc (2):David Holmes, lambda-dev at openjdk.java.net


I sympathize with your concerns -- naming is hard and subjective, and 
fraught with lots of pre-existing baggage -- but this is not on the 
table to be reopened. We simply cannot reopen every decision every time 
one of the ten million Java developers discovers it for the first time, 
decides they don't like it, and assumes there couldn't possibly have 
been adequate consideration the first n-1 times it was brought up.

For the record, there's two ways to think about the function shaped

value -> void body

One is focusing on the side-effects inherent in the body (which there 
must be, otherwise there'd be no point of having this this function at 
all). The other is focusing on its role in a larger system -- it *takes 
a value* and does something with it. While the boundary between the two 
perspectives is fuzzy and one can't live without the other, the former 
is mostly the view from the writer of the lambda (I'm going to get a 
value and TAKE AN ACTION), and the latter is mostly the view from the 
consumer of the lambda (I'm going to PASS THIS VALUE TO THE OTHER GUY 
and he'll probably do something with it).

For some functional interface types, like Predicate, the "obvious" name 
worked great from both perspectives. There was no real debate about 
Predicate, because there was very little to not like about it from any 
perspective.

For this shape, there was no name that worked great from both 
perspectives; some names highlight one perspective, other names 
highlight the other (and to make it worse, many candidates had various 
kinds of baggage that made them less attractive in some situations.) 
The preference is highly subjective, and therefore there was (and 
apparently will be forever more) endless debate. Remember, though, 
there is a not a right answer; for everyone who hates Block or Consumer 
or ValueReceiver, there is someone who hates Procedure or Action for 
analogous reasons.

In the end, because the place these names are going to appear more than 
anywhere else is in APIs, that gave weight to the latter perspective.



On 4/11/2013 6:22 AM, Thomas Münz wrote:
> Hi
>
> Thanks for the answer. That's a funny find.
> Sadly, I fail to see the relation to the provided arguments.
>
> I'm sorry if there have been too much over-specific suggestions like "Block", "Receiver" or "Consumer" all over the place in the past for such a much more general concept :-(.
> All I see currently see is the name "Consumer", which is way too specific for the general concept of a generic void logic for the reasons provided before.
>
> Regards,
> Thomas
>
>
>
>
> Original Message
> Re: What does a Consumer consume? (11-Apr-2013 11:09)
> From: David Holmes
> To:Thomas Münz
> Cc:lambda-dev at openjdk.java.net
>
>
> On 11/04/2013 6:19 PM, Thomas Münz wrote:
>> Bike shedding alert :)
>>
>> While I think Java 8 is pretty optimal from what I saw so far (I know it can't be perfect considering Java history), there's one particular thing that worries me so much that I feed compelled to bother you with it.
>> Please bear with me.
>>
>> I strongly appeal to rename the type Consumer to a more approriate name, like maybe Procedure.
>
> See the following
>
> "Let's please rename Block to Receiver before it's too late"
>
> http://mail.openjdk.java.net/pipermail/lambda-libs-spec-observers/2013-January/001136.html
>
> "Hopefully the last message on Block"
>
> http://mail.openjdk.java.net/pipermail/lambda-libs-spec-observers/2013-January/001215.html
>
> David
> -----
>
>> Rationale follows:
>>
>> A consumer is an entity that consumes another entity, meaning removes it from its context. Best example is a collection that is used for inter-thread communication: the producer/supplier thread puts a new item in the queue and the consumer thread removes the item from the queue, hence _consumes_ it.
>> Consuming generally implies that the entity it is applied to is _consumed_, made gone, removed. Also see the meaning of consumer in the economy: consumers (we) take and buy stuff, remove things from their shelf and then use/digest/etc. them until they're gone.
>> But this core meaning of the term is absolutely not the case with the functional type that currently carries this name. It's just a procedure, not a consumer.
>> It MAY be used to consume entities from a collection (which depends on the method called, not the passed function instance), but it may and will be used many times more to just iterate them and apply a logic to them in general busines logic.
>>
>> I must say was very happy to see that the old, compiler-specific-oriented name "Block" has been given up (already wanted to post about it, but the problem solved itself, thankfully).
>> But only to be replaced by an apparently concurrency-specific-oriented name like "Consumer".
>> But why not just take the general functional way of thinking to find a name for a general functional element in the first place?
>>
>> Can('t?) you imagine the hundreds of questions from beginners and not so talented developer colleagues like "If I apply the consumer to the collection, is the collection empty afterwards?"? ... and the hundreds of times we will sigh, start explaining "No, you see, this is just a ..." and think "why oh why did they give it that name?" and then start to explain time and time again?
>> This won't be a sign of missing understanding of the asker, but it's a sign for confusing naming in the official API.
>>
>> Also, a very good indicator that Consumer is an unlucky choice can be found in its own JavaDoc:
>> "An operation which accepts a single input argument and returns no result."
>> If you instantly have to switch to another term to even begin to explain it, then why did you chose the unfitting term in the first place? Why not then call it "Operation" right away? Or as "Operation" might be ambiguous, something even more fitting, like said "Procedure".
>> And again: where is the reference to the name, to the process of consuming in the java doc? It's missing for a good reason: because nothing is consumed in the first place.
>>
>>
>> I have function types in my own (sry: next generation start-over) collection framework that I use very successfully for years now, namely:
>>
>> Predicate with boolean apply(E)
>> Function with O apply(I)
>> Procedure with void apply(E)
>> (Plus a couple of others like Aggregator extends Procedure which for me is a much more elegant, flexible and efficient concept than a reducer, but that doesn't matter here much).
>>
>> Those are very thoroughly thought through names, based on the following rationale:
>> 1.) Procedure correlates very good with the other type Function when it comes to building the mental conception of different functional types.
>> They are both very similar, but Function returns something, Procedure does not. Like "brothers". Very intuitive, very straight forward. At first I named it "Operation" (like mentioned above), but because of this point, procedure appeared to be much more fitting.
>> 2.) All the functional types have a unifiedly named method "apply". A function is applied to an entity. A predicate can apply to an entity (honestly: who says "the predicate tests the entity" in common speaking? I think 90% say "if the predicate applies to the entity, then...")
>> As a side node: colliding method names are irrelevant because in practice you never come accross a case where a concrete implementation has to implement a procedure and a predicate or so. Such cases are done by internal separated delegates anyway, not by directly implementing multiple interfaces.
>>
>>
>> Me personally (however much that is worth), I will happily delete my proprietary "Function" and refactor everything to use the standard one the moment Java 8 goes live. I'm all for standard conformity if it's at least "okay" to use it.
>> I'm currently struggling with myself to accept the standard Predicate with it sub-optimal "test()" as well for sake of standard conformity, but I think I'll get there in the end.
>> But I cannot in good conscious replace an intuitive, easy understandable "Procedure" in my private and professional work with a confusion-prone "Consumer" and explain my customers and colleagues endless times that it doesn't really do what it implies but instead is just an ordinary procedure/operation/routine. The reaction of anyone having even a little reservation about functional programming will instantly be "Aha, this doesn't sound very thought-out, I knew it, functional programming is crap, go away".
>> I'd rather stick to my proprietary Procedure type and tell them to better not use the standard mechanism from the JDK because it does more harm than good. Sadly, I do this a lot and I hate to do it every time. Maybe this time, I hope I can prevent it ...
>>
>>
>> Alternatives fitting the concept instead of Procedure might be "Routine" or even more abstract "Logic" or "Action", but really, please consider that in practice, on a daily business logic designing level instead of a language design working bench, "Consumer" is the second worst and confusing choice right behind "Block". Why not pick a term from the upper end of fitting terms instead of the lower end and save everyone several tons of hazzle in the coming years?
>>
>>
>> Thank you for your attention.
>> Regards and thanks very much for the 99% pretty optimal rest :-). Can't wait to see it go live.
>>
>>
>>
>
> To: david.holmes at oracle.com
> Cc: lambda-dev at openjdk.java.net
>
>
>

To: brian.goetz at oracle.com
Cc: lambda-dev at openjdk.java.net


More information about the lambda-dev mailing list