Discovering the number of return arguments requested.

Discussion in 'Ruby' started by Brad Phelan, Dec 19, 2006.

  1. Brad Phelan

    Brad Phelan Guest

    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://xtargets.com
     
    Brad Phelan, Dec 19, 2006
    #1
    1. Advertising

  2. Brad Phelan

    Eric Hodel Guest

    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 - - http://blog.segment7.net

    I LIT YOUR GEM ON FIRE!
     
    Eric Hodel, Dec 19, 2006
    #2
    1. Advertising

  3. Brad Phelan

    Brad Phelan Guest

    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
     
    Brad Phelan, Dec 19, 2006
    #3
  4. Brad Phelan

    Guest

    On Tue, 19 Dec 2006, 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.


    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
    --
    if you find yourself slandering anybody, first imagine that your mouth is
    filled with excrement. it will break you of the habit quickly enough. - the
    dalai lama
     
    , Dec 19, 2006
    #4
  5. 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
     
    Robert Klemme, Dec 19, 2006
    #5
  6. Brad Phelan

    Brad Phelan Guest

    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
     
    Brad Phelan, Dec 19, 2006
    #6
  7. 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?ca=dnt-54

    Kind regards

    robert
     
    Robert Klemme, Dec 19, 2006
    #7
  8. Brad Phelan

    Tom Pollard Guest

    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
     
    Tom Pollard, Dec 19, 2006
    #8
  9. Brad Phelan

    Brad Phelan Guest


    >
    > 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
     
    Brad Phelan, Dec 20, 2006
    #9
  10. 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
     
    Joel VanderWerf, Dec 21, 2006
    #10
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jeff 'Jones' Putz
    Replies:
    1
    Views:
    344
    John Saunders
    Nov 25, 2003
  2. Holger (David) Wagner
    Replies:
    7
    Views:
    549
    Scott Allen
    Aug 17, 2004
  3. Sanjay Pais

    Discovering fields in a webform

    Sanjay Pais, Jul 8, 2005, in forum: ASP .Net
    Replies:
    4
    Views:
    405
    Sanjay Pais
    Jul 12, 2005
  4. Mac
    Replies:
    1
    Views:
    454
    Roedy Green
    Sep 3, 2003
  5. z-man
    Replies:
    15
    Views:
    612
    Chris Uppal
    Oct 11, 2006
Loading...

Share This Page