Discovering the number of return arguments requested.

B

Brad Phelan

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.
 
E

Eric Hodel

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.)
 
B

Brad Phelan

Eric said:
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
 
A

ara.t.howard

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.

just build that pattern into your interface:

harp:~ > cat a.rb
def foo opts = {}
dst = opts['dst'] || opts[:dst]
dst << 'bar' unless dst.nil?
end

foo :dst => a='' # nargout == 1
p a
foo # nargout == 0


harp:~ > ruby a.rb
"bar"

of course you could do alot more too.

-a
 
R

Robert Klemme

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.
=> 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:
=> 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
 
B

Brad Phelan

Robert said:
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.

=> nil


This is exactly what happens:

=> 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
 
R

Robert Klemme

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?ca=dnt-54

Kind regards

robert
 
T

Tom Pollard

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
 
B

Brad Phelan

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?ca=dnt-54

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
 
J

Joel VanderWerf

Brad said:
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,434
Messages
2,571,691
Members
48,796
Latest member
Greg L.

Latest Threads

Top