From: Mark Hubbart Date: 2005-04-15T14:20:40+09:00 Subject: Re: want_object? - possible? On 4/14/05, David A. Black wrote: > Hi -- > > On Fri, 15 Apr 2005, Mark Hubbart wrote: > > > On 3/24/05, David A. Black wrote: > >> Hi -- > >> > >> On Fri, 25 Mar 2005, Daniel Berger wrote: > >> > >>> Keep in mind that some of the contexts mentioned there > >>> do not apply to Ruby, e.g. lvalue subs. In fact, most > >>> may not. But, if there were some way for a method to > >>> detect whether it's part of a chain in advance, that > >>> might be useful. > >> > >> I don't think there is a way, logically, within the basic > >> message-receiver-response model. The idea of an object knowing what > >> is going to happen after it finishes responding to the message seems, > >> to me, to be part of a pretty deeply different design. At that point, > >> also, you're not really chaining method calls; you're using > >> method-chaining syntax to execute something that's really not linear > >> from left to right. At that point, the a.b.c syntax starts to obscure > >> what's really happening, rather than revealing it, I think. > > > > There are occasions where a nice uses_return_value? would help: > > > > module Enumerable > > def zip(*others) > > if block_given? > > if uses_return_value? > > # build a new array using the block, return it > > else > > # yield each set of elements, don't build array. > > end > > [...] > > > > and using it with method chaining: > > > > (1..26).zip('a'..'z'){|n,c| n.to_s + c}.map{|v| #do stuff here} > > > > Looks good to me! > > I still don't like the look-ahead aspect of this. It seems to me to > be a quantum leap from block_given? -- in the sense that the presence > or absence of the block is part of the semantics of this method call, > whereas the whole "what happens *after* we return from this method > call?" is part of the semantics of the next method call (or lack > thereof). I don't see it as a "what happens after" type thing; more of a "what's my position" type thing. It would simply glance into the parse tree, checking if this method call is in the outer ring, so to speak, of a statement. If it is, the function can optimize itself not to bother returning any expensive values, since they would just be GC fodder. > Consider this (purely illustrative) example: > > module Array > def something > if subsequently_flattened? > push(1) > else > push(2) > end > self > end > end > > a = [] > a.something.flatten # a == [1] > a.something # a == [1,2] :) > It is no step at all in kind, and only a small step in degree, from > the question "Is what I return going to be used in a chain?" to the > question "Is what I return going to be chained to the 'flatten' > method?" (or any other specific method). It strikes me as a whole > type of knowledge that is not the business of the method that's > currently executing. The example above, while being very funny, is nothing like what's being suggested: - it's a custom method grabbing absurdly specific external context information - it's using the requested information to do something entirely silly in it own right By using this example, it appears that you are trying to say that it's a slippery slope; from a method telling you whether a return value is in a position to be used, to a specialized method call which tells you whether a specific method of a certain class will be called on the result. Since we haven't been given an example of how just knowing whether the return value is used is harmful, I'll present a simpler example of its possible usefulness. I'll even shorten the method name a bit :) class MarkovChain [...] def parse_text(text) words = text.scan(WORDS) links = link_words(words) add_to_library(links) links.compute_statistics if return_value? end end mc = MarkovChain.new(depth=>4) mc.parse_text( IO.read('illiad.text') ) ody_stats = mc.parse( IO.read('odyssey.text') ) Assuming that computing the statistics on a set of markov chain links is processor and memory intensive, it would be nice to know if the return value is used or not. If it is ignored, we can save a lot of time. And it's better than, say, a boolean flag ("mc.parse_text(text, true)"), or having another method with the same name that does the same thing. The more I think on this, the more it seems like a good feature. Sure it's a little magic, but then, so is callcc :) And if it wasn't a little magic, we would just be implementing it ourselves, in pure Ruby. cheers, Mark