What does a Consumer consume?
brian.goetz at oracle.com
Thu Apr 11 06:02:56 PDT 2013
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
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
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:
> 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.
> 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"
> "Hopefully the last message on Block"
>> 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
More information about the lambda-dev