[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Discovering the number of return arguments requested.

Brad Phelan

12/19/2006 9:16:00 AM

Is it possible ( and I think not ) that you can discover if any return
arguments are requested when a method is called.

Eg:

def foo
if nargout == 1
"bar"
end
end

a = foo # nargout == 1
foo # nargout == 0


This would be useful in certain patterns where you only want to
create a return value and consequently a new object if it is
actually required.

--
Brad Phelan
http://xt...
9 Answers

Eric Hodel

12/19/2006 9:52:00 AM

0

On Dec 19, 2006, at 01:20, Brad Phelan wrote:

> Is it possible ( and I think not ) that you can discover if any
> return arguments are requested when a method is called.

Methods only ever return one Object. (Sometimes that Object will be
splatted, giving the illusion of multiple arguments.)

--
Eric Hodel - drbrain@segment7.net - http://blog.se...

I LIT YOUR GEM ON FIRE!


Brad Phelan

12/19/2006 11:22:00 AM

0

Eric Hodel wrote:
> On Dec 19, 2006, at 01:20, Brad Phelan wrote:
>
>> Is it possible ( and I think not ) that you can discover if any return
>> arguments are requested when a method is called.
>
> Methods only ever return one Object. (Sometimes that Object will be
> splatted, giving the illusion of multiple arguments.)

True. However that doesn't answer the question as
to whether it is possible to discover if that single object is used
or not. I suspect Ruby syntax would make this difficult to figure
out.

If the critical function is called as the last statement in another
function or block then the return object can get passed implicitly
up the stack until something takes hold of it.

Brad

Ara.T.Howard

12/19/2006 2:52:00 PM

0

Robert Klemme

12/19/2006 3:06:00 PM

0

On 19.12.2006 12:21, Brad Phelan wrote:
> Eric Hodel wrote:
>> On Dec 19, 2006, at 01:20, Brad Phelan wrote:
>>
>>> Is it possible ( and I think not ) that you can discover if any
>>> return arguments are requested when a method is called.
>>
>> Methods only ever return one Object. (Sometimes that Object will be
>> splatted, giving the illusion of multiple arguments.)
>
> True. However that doesn't answer the question as
> to whether it is possible to discover if that single object is used
> or not. I suspect Ruby syntax would make this difficult to figure
> out.

Actually, a Ruby method does *always* return an instance (even without
explicit "return"). Conversely there is nothing like a void function /
method - there is always a value returned.

>> def foo() end
=> nil
>> foo
=> nil

> If the critical function is called as the last statement in another
> function or block then the return object can get passed implicitly
> up the stack until something takes hold of it.

This is exactly what happens:

>> def bar() 1 end
=> nil
>> def foo() bar() end
=> nil
>> foo
=> 1
>> bar
=> 1

IMHO you are worrying too much about this: if a method has a meaningful
return value it should be documented and returned no matter what the
caller does. If he chooses to ignore it that's his choice. My 0.02EUR.

Kind regards

robert

Brad Phelan

12/19/2006 3:50:00 PM

0

Robert Klemme wrote:
> On 19.12.2006 12:21, Brad Phelan wrote:
>> Eric Hodel wrote:
>>> On Dec 19, 2006, at 01:20, Brad Phelan wrote:
>>>
>>>> Is it possible ( and I think not ) that you can discover if any
>>>> return arguments are requested when a method is called.
>>>
>>> Methods only ever return one Object. (Sometimes that Object will be
>>> splatted, giving the illusion of multiple arguments.)
>>
>> True. However that doesn't answer the question as
>> to whether it is possible to discover if that single object is used
>> or not. I suspect Ruby syntax would make this difficult to figure
>> out.
>
> Actually, a Ruby method does *always* return an instance (even without
> explicit "return"). Conversely there is nothing like a void function /
> method - there is always a value returned.
>
> >> def foo() end
> => nil
> >> foo
> => nil
>
>> If the critical function is called as the last statement in another
>> function or block then the return object can get passed implicitly
>> up the stack until something takes hold of it.
>
> This is exactly what happens:
>
> >> def bar() 1 end
> => nil
> >> def foo() bar() end
> => nil
> >> foo
> => 1
> >> bar
> => 1
>
> IMHO you are worrying too much about this: if a method has a meaningful
> return value it should be documented and returned no matter what the
> caller does. If he chooses to ignore it that's his choice. My 0.02EUR.

I'm only curious about this due to performance issues not interface
issues. I am sure everybody has seen _Why's Markaby builder. On each
nested element called a fragment object is returned though very rarely
used.

The fragment objects are used for rarely encountered events that
are outside of the standard Markaby pattern and can be used to
rewind the stream and pull out chunks that were already
inserted.

mab = Markaby::Builder.new

mab.html do
div do
div do
p do
"cat" + br + "dog" + br + "cow"
end
end
end
end

generates

<html>
<div>
<div>
<p>
cat <br/> dog <br/> cow
</p>
</div>
</div>
</html>

The html, div, p and br methods all return fragment
objects. However only the fragment objects from the br
calls actually get used. The fragment objects from the
other calls are just thrown away.

In the case of Markaby I suspect there would be some
performance increase ( small maybe ) by changing the
Markaby code to do something different if it knew
beforehand that the fragment object was never required
instead of generating one and giving it straight to
the garbage collector.

Brad

Robert Klemme

12/19/2006 4:42:00 PM

0

On 19.12.2006 16:49, Brad Phelan wrote:
> Robert Klemme wrote:
>> IMHO you are worrying too much about this: if a method has a
>> meaningful return value it should be documented and returned no matter
>> what the caller does. If he chooses to ignore it that's his choice.
>> My 0.02EUR.
>
> I'm only curious about this due to performance issues not interface
> issues. I am sure everybody has seen _Why's Markaby builder. On each
> nested element called a fragment object is returned though very rarely
> used.
>
> The fragment objects are used for rarely encountered events that
> are outside of the standard Markaby pattern and can be used to
> rewind the stream and pull out chunks that were already
> inserted.
>
> mab = Markaby::Builder.new
>
> mab.html do
> div do
> div do
> p do
> "cat" + br + "dog" + br + "cow"
> end
> end
> end
> end
>
> generates
>
> <html>
> <div>
> <div>
> <p>
> cat <br/> dog <br/> cow
> </p>
> </div>
> </div>
> </html>
>
> The html, div, p and br methods all return fragment
> objects. However only the fragment objects from the br
> calls actually get used. The fragment objects from the
> other calls are just thrown away.

I can see your point. You could change the code and test it out or
create some test suite of your own. Then you *know* whether this will
actually yield speed improvements - and how large they are. And if they
are negligible - you do not have to worry any more.

When it comes to rendering HTML IO and fetching the data to display is
usually slower than the HTML rendering (assuming some persistent backend
storage).

> In the case of Markaby I suspect there would be some
> performance increase ( small maybe ) by changing the
> Markaby code to do something different if it knew
> beforehand that the fragment object was never required
> instead of generating one and giving it straight to
> the garbage collector.

Actually it is not immediately GC'ed. And when Ruby runs on a JVM then
short lived objects are definitively nothing to worry about. Read here
for example:
http://www-128.ibm.com/developerworks/library/j-jtp01274.html...

Kind regards

robert

Tom Pollard

12/19/2006 7:23:00 PM

0

On Dec 19, 2006, at 10:50 AM, Brad Phelan wrote:
> I'm only curious about this due to performance issues
> not interface issues.
[...]
> In the case of Markaby I suspect there would be some
> performance increase ( small maybe ) by changing the
> Markaby code to do something different if it knew
> beforehand that the fragment object was never required
> instead of generating one and giving it straight to
> the garbage collector.

If the fragment is simply a pointer into a larger structure, then
there might not be any significant penalty at all in providing it.
If it does need to be constructed, then perhaps it could be provided
in a lazy manner?

One of the things I really like about Ruby is that accessors look
just like attribute lookup. This makes it possible to change your
mind about whether an object attribute is just a value, or is
calculated on demand, without changing your object's interface.

TomP

Brad Phelan

12/20/2006 8:38:00 AM

0


>
> Actually it is not immediately GC'ed. And when Ruby runs on a JVM then
> short lived objects are definitively nothing to worry about. Read here
> for example:
> http://www-128.ibm.com/developerworks/library/j-jtp01274.html...
>

Nice article. I remember reading stuff about Java and memory management
back in my Java programming days. The copying generation collector would
work well with Ruby but does escape analysis work?

The Java example given in the article is

void doSomething() {
Point p = someObject.getPosition();
System.out.println("Object is at (" + p.x, + ", " + p.y + ")");
}

....

Point getPosition() {
return new Point(myX, myY);
}

and the Ruby version would be

def do_something
p = some_object.get_position
puts "Object is at #{p.x}, #{p.y}"
end

The article makes the point that the optimizer can
surmise that p is thrown away because it is used only
to get it's attributes. However in Ruby p.x and p.y
are not public attributes but messages which could
result in absolutely anything happening with the
reference to the object in p.

One day I keep promising myself to peek inside the
Ruby interpreter and figure out how it all works. I
am sure that is where all the fun is at if I only
had the time.

Cheers

B

Joel VanderWerf

12/21/2006 12:54:00 AM

0

Brad Phelan wrote:
> Is it possible ( and I think not ) that you can discover if any return
> arguments are requested when a method is called.
>
> Eg:
>
> def foo
> if nargout == 1
> "bar"
> end
> end
>
> a = foo # nargout == 1
> foo # nargout == 0
>
>
> This would be useful in certain patterns where you only want to
> create a return value and consequently a new object if it is
> actually required.

One option is yield:

def foo
yield "bar" if block_given?
end

a = nil

foo {|x| a=x}
#or:
#foo {|a|} # this doesn't work in 1.9 IIRC

--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407