return_on

Discussion in 'Ruby' started by Trans, Jan 10, 2007.

  1. Trans

    Trans Guest

    Sometimes i do this:

    return x if x

    Anyway to code it as:

    return_on x

    t.
     
    Trans, Jan 10, 2007
    #1
    1. Advertising

  2. Trans

    Pit Capitain Guest

    Trans schrieb:
    > Sometimes i do this:
    >
    > return x if x
    >
    > Anyway to code it as:
    >
    > return_on x


    It's not very nice, but you could wrap the whole method body in a block
    and use throw/catch behind the scenes.

    Regards,
    Pit
     
    Pit Capitain, Jan 10, 2007
    #2
    1. Advertising

  3. On 1/10/07, Trans <> wrote:
    > Sometimes i do this:
    >
    > return x if x
    >
    > Anyway to code it as:
    >
    > return_on x
    >


    I cannot recall I ever have used return, in this way,
    but my coding style may be 5% different than yours.
    Maybe I can improve my minimal insight.

    Any good (larger) examples of this thing?


    --
    Simon Strandgaard
    http://opcoders.com/
     
    Simon Strandgaard, Jan 10, 2007
    #3
  4. On 10-Jan-2007, at 20:09, Trans wrote:
    > Sometimes i do this:
    >
    > return x if x
    >
    > Anyway to code it as:
    >
    > return_on x
    >
    > t.


    I do this quite often, as well! We need a macro system ;-)

    JS
     
    Srinivas JONNALAGADDA, Jan 11, 2007
    #4
  5. Trans wrote:
    > Sometimes i do this:
    > return x if x
    > Anyway to code it as:
    > return_on x


    I'm wondering if continuations (or continuations + set_trace_func to
    catch the method end) could be used to achieve that, but am not a whiz
    at callcc, and am up past my bedtime (hence am not going to experiment
    w/ it).

    Is there a Weirich in the house?

    Devin
    (Even if it can be implemented using such hackery, I might consider that
    a smell that it's so different, and doesn't map to Ruby's ways, and be
    hesitant to use such a beast in GP code.)
     
    Devin Mullins, Jan 11, 2007
    #5
  6. Trans

    Trans Guest

    Simon Strandgaard wrote:
    > On 1/10/07, Trans <> wrote:
    > > Sometimes i do this:
    > >
    > > return x if x
    > >
    > > Anyway to code it as:
    > >
    > > return_on x
    > >

    >
    > I cannot recall I ever have used return, in this way,
    > but my coding style may be 5% different than yours.
    > Maybe I can improve my minimal insight.
    >
    > Any good (larger) examples of this thing?


    I don't really have any examples that are repleat with it, but as to
    insight it's especially convenient when caching a return value:

    def x
    return_on @cache[:x]
    # do stuff
    @cache[:x] = result_of_stuff
    end

    this gets rid of an extraneous variable too b/c otherwise, the more
    efficient impl. is:

    def x
    r = @cache[:x]
    return r if r
    # do stuff
    @cache[:x] = result_of_stuff
    end

    funny thing i just came across a similar case for break. how would you
    DRY this up and get rid of 'result'?

    result = nil
    files.each do
    result = require file
    break if result
    end
    if result
    ...

    t.
     
    Trans, Jan 13, 2007
    #6
  7. Trans wrote:
    > funny thing i just came across a similar case for break. how would you
    > DRY this up and get rid of 'result'?
    >
    > result = nil
    > files.each do
    > result = require file
    > break if result
    > end
    > if result
    > ...


    Well, this is much easier:

    if files.any? {|file| require file }
    ...

    C'mon, Trans. :)

    Devin
    (Or am I missing something obvious?)
     
    Devin Mullins, Jan 13, 2007
    #7
  8. Trans

    Pit Capitain Guest

    Trans schrieb:
    > I don't really have any examples that are repleat with it, but as to
    > insight it's especially convenient when caching a return value:
    >
    > def x
    > return_on @cache[:x]
    > # do stuff
    > @cache[:x] = result_of_stuff
    > end
    >
    > this gets rid of an extraneous variable too b/c otherwise, the more
    > efficient impl. is:
    >
    > def x
    > r = @cache[:x]
    > return r if r
    > # do stuff
    > @cache[:x] = result_of_stuff
    > end


    You could also implement this as

    def x
    @cache[:x] ||= (
    # do stuff
    result_of_stuff
    )
    end

    > funny thing i just came across a similar case for break. how would you
    > DRY this up and get rid of 'result'?
    >
    > result = nil
    > files.each do
    > result = require file
    > break if result
    > end
    > if result
    > ...


    If "result" is only a flag whose value you don't need later, you could do

    if files.find { |file| require file }
    ...
    end

    Regards,
    Pit
     
    Pit Capitain, Jan 13, 2007
    #8
  9. Trans

    Trans Guest

    Devin Mullins wrote:
    > Trans wrote:
    > > funny thing i just came across a similar case for break. how would you
    > > DRY this up and get rid of 'result'?
    > >
    > > result = nil
    > > files.each do
    > > result = require file
    > > break if result
    > > end
    > > if result
    > > ...

    >
    > Well, this is much easier:
    >
    > if files.any? {|file| require file }
    > ...


    Cool, I forget that #any? will break after the first true encounter. I
    used #find as pit suggested (which can return any value actually). But,
    that wasn't really my point. Such a solution breaks the analogy to the
    original return case --whihc can't be DRYed-up that way.

    T.
     
    Trans, Jan 13, 2007
    #9
  10. Trans

    Trans Guest

    Pit Capitain wrote:
    > Trans schrieb:
    > > I don't really have any examples that are repleat with it, but as to
    > > insight it's especially convenient when caching a return value:
    > >
    > > def x
    > > return_on @cache[:x]
    > > # do stuff
    > > @cache[:x] = result_of_stuff
    > > end
    > >
    > > this gets rid of an extraneous variable too b/c otherwise, the more
    > > efficient impl. is:
    > >
    > > def x
    > > r = @cache[:x]
    > > return r if r
    > > # do stuff
    > > @cache[:x] = result_of_stuff
    > > end

    >
    > You could also implement this as
    >
    > def x
    > @cache[:x] ||= (
    > # do stuff
    > result_of_stuff
    > )
    > end


    That pretty good. I rarely use ( ) as local encapsulator and probably
    should consider it more often. I'm generally partial to less indention
    when I can get it though.

    Thanks,
    T.
     
    Trans, Jan 13, 2007
    #10
  11. Trans wrote:
    ...
    > funny thing i just came across a similar case for break. how would you
    > DRY this up and get rid of 'result'?
    >
    > result = nil
    > files.each do
    > result = require file
    > break if result
    > end
    > if result
    > ...


    This only helps a little...

    result = files.each do |file|
    r = require file and break r
    end

    --
    vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
     
    Joel VanderWerf, Jan 13, 2007
    #11
  12. I have made the most hackish thing to accomplish this. It is basically
    a regexp-supporting preprocessor. I don't recommend using it.

    #! /usr/bin/ruby -w

    def preprocessor_define(*args, &blk)
    # Determine line of caller
    callerLine = caller.join.match(/[0-9]+/)[0].to_i

    # Get the source of the running file
    source = IO.read(__FILE__)

    # Remove the callerLine line
    source = source.split("\n")
    source.delete_at(callerLine - 1)
    source = source.join("\n")

    # Do the replacement
    source.gsub!(*args, &blk)

    # Avoid function redefinition warnings
    newName = ""
    50.times {newName << (rand(26) + 65).chr }
    source.gsub!("preprocessor_define", newName)

    # Run the replacement
    #puts source
    eval source
    exit
    end

    preprocessor_define(/return_on (.*)/) {|s| "return #{s[1]} unless
    #{s[1]}.nil?"}

    def test
    zulu = 5
    return_on zulu
    puts "Broken."
    end
    test

    Output: None, as 'puts Broken' never gets executed.

    Trans wrote:
    > Sometimes i do this:
    >
    > return x if x
    >
    > Anyway to code it as:
    >
    > return_on x
    >
    > t.
    >
    >
    >
     
    Daniel Finnie, Jan 13, 2007
    #12
  13. Trans

    Trans Guest

    Joel VanderWerf wrote:

    > This only helps a little...
    >
    > result = files.each do |file|
    > r = require file and break r
    > end


    ...and the use of 'and'. these are the crafty of ruby :)

    def x
    r = @cache[:x] and return r
    ...
    end

    pretty good, still a little unDRY, but pretty good.

    t.
     
    Trans, Jan 14, 2007
    #13
  14. Trans

    Trans Guest

    Daniel Finnie wrote:
    > I have made the most hackish thing to accomplish this. It is basically
    > a regexp-supporting preprocessor. I don't recommend using it.
    >
    > #! /usr/bin/ruby -w
    >
    > def preprocessor_define(*args, &blk)
    > # Determine line of caller
    > callerLine = caller.join.match(/[0-9]+/)[0].to_i
    >
    > # Get the source of the running file
    > source = IO.read(__FILE__)
    >
    > # Remove the callerLine line
    > source = source.split("\n")
    > source.delete_at(callerLine - 1)
    > source = source.join("\n")
    >
    > # Do the replacement
    > source.gsub!(*args, &blk)
    >
    > # Avoid function redefinition warnings
    > newName = ""
    > 50.times {newName << (rand(26) + 65).chr }
    > source.gsub!("preprocessor_define", newName)
    >
    > # Run the replacement
    > #puts source
    > eval source
    > exit
    > end
    >
    > preprocessor_define(/return_on (.*)/) {|s| "return #{s[1]} unless
    > #{s[1]}.nil?"}
    >
    > def test
    > zulu = 5
    > return_on zulu
    > puts "Broken."
    > end
    > test
    >
    > Output: None, as 'puts Broken' never gets executed.


    Holy Smokes! The Man goes out of his way!!! return_on brother,
    return_on! :)

    T.
     
    Trans, Jan 14, 2007
    #14
  15. On Jan 14, 1:34 am, "Trans" <> wrote:
    >
    > def x
    > return_on @cache[:x]
    > # do stuff
    > @cache[:x] = result_of_stuff
    > end
    >


    def x
    @cache[:x] ||= begin
    # do stuff
    end
    end

    Gavin
     
    Gavin Sinclair, Jan 14, 2007
    #15
  16. Gavin Sinclair wrote:
    > On Jan 14, 1:34 am, "Trans" <> wrote:
    >> def x
    >> return_on @cache[:x]
    >> # do stuff
    >> @cache[:x] = result_of_stuff
    >> end
    >>

    >
    > def x
    > @cache[:x] ||= begin
    > # do stuff
    > end
    > end


    Or (saving an exception handler setup):

    def reverse x
    @cache[:x] ||= (
    puts "CACHING"
    x.reverse
    )
    end

    @cache = {}

    p reverse("foo")
    p reverse("foo")

    __END__

    Output:

    CACHING
    "oof"
    "oof"

    --
    vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
     
    Joel VanderWerf, Jan 14, 2007
    #16
  17. Joel VanderWerf wrote:
    > Gavin Sinclair wrote:
    > > On Jan 14, 1:34 am, "Trans" <> wrote:
    > >> def x
    > >> return_on @cache[:x]
    > >> # do stuff
    > >> @cache[:x] = result_of_stuff
    > >> end
    > >>

    > >
    > > def x
    > > @cache[:x] ||= begin
    > > # do stuff
    > > end
    > > end

    >
    > Or (saving an exception handler setup):
    >
    > def reverse x
    > @cache[:x] ||= (
    > puts "CACHING"
    > x.reverse
    > )
    > end
    >
    > @cache = {}
    >
    > p reverse("foo")
    > p reverse("foo")
    >
    > __END__
    >
    > Output:
    >
    > CACHING
    > "oof"
    > "oof"


    It doesn't work correctly.

    def reverse x
    @cache[:x] ||= (
    puts "CACHING"
    x.reverse
    )
    end

    @cache = {}

    p reverse("foo")
    p reverse("what?")
    p reverse("And this is cached, you think???")

    --- output -----
    CACHING
    "oof"
    "oof"
    "oof"
     
    William James, Jan 14, 2007
    #17
  18. William James wrote:
    > Joel VanderWerf wrote:
    >> Gavin Sinclair wrote:
    >>> On Jan 14, 1:34 am, "Trans" <> wrote:
    >>>> def x
    >>>> return_on @cache[:x]
    >>>> # do stuff
    >>>> @cache[:x] = result_of_stuff
    >>>> end
    >>>>
    >>> def x
    >>> @cache[:x] ||= begin
    >>> # do stuff
    >>> end
    >>> end

    >> Or (saving an exception handler setup):
    >>
    >> def reverse x
    >> @cache[:x] ||= (
    >> puts "CACHING"
    >> x.reverse
    >> )
    >> end
    >>
    >> @cache = {}
    >>
    >> p reverse("foo")
    >> p reverse("foo")
    >>
    >> __END__
    >>
    >> Output:
    >>
    >> CACHING
    >> "oof"
    >> "oof"

    >
    > It doesn't work correctly.
    >
    > def reverse x
    > @cache[:x] ||= (
    > puts "CACHING"
    > x.reverse
    > )
    > end
    >
    > @cache = {}
    >
    > p reverse("foo")
    > p reverse("what?")
    > p reverse("And this is cached, you think???")
    >
    > --- output -----
    > CACHING
    > "oof"
    > "oof"
    > "oof"
    >


    Oof! Typo.

    def reverse x
    @cache[x] ||= (
    puts "CACHING"
    x.reverse
    )
    end

    @cache = {}

    p reverse("foo")
    p reverse("bar")
    p reverse("foo")
    p reverse("bar")

    __END__

    Output:

    CACHING
    "oof"
    CACHING
    "rab"
    "oof"
    "rab"

    --
    vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
     
    Joel VanderWerf, Jan 14, 2007
    #18
  19. Joel VanderWerf wrote:
    > Gavin Sinclair wrote:
    >> def x
    >> @cache[:x] ||= begin
    >> # do stuff
    >> end
    >> end

    >
    > Or (saving an exception handler setup):


    Does begin...end really have some sort of overhead? I've found that one
    the nicest looking yet, and I'd hate to dismiss it based on a false
    perception.

    Devin
     
    Devin Mullins, Jan 14, 2007
    #19
  20. Devin Mullins wrote:
    > Joel VanderWerf wrote:
    >> Gavin Sinclair wrote:
    >>> def x
    >>> @cache[:x] ||= begin
    >>> # do stuff
    >>> end
    >>> end

    >>
    >> Or (saving an exception handler setup):

    >
    > Does begin...end really have some sort of overhead? I've found that one
    > the nicest looking yet, and I'd hate to dismiss it based on a false
    > perception.


    The overhead is smaller than I remembered, pretty negligible apparently:

    require 'benchmark'

    def meth_with_begin_end
    x = begin 3 end
    end

    def meth_without_begin_end
    x = 3
    end

    N = 10000000

    Benchmark.bmbm do |b|
    b.report("meth_with_begin_end") do
    N.times {meth_with_begin_end}
    end
    b.report("meth_without_begin_end") do
    N.times {meth_without_begin_end}
    end
    end

    __END__

    Rehearsal ----------------------------------------------------------
    meth_with_begin_end 5.648000 0.000000 5.648000 ( 5.729000)
    meth_without_begin_end 5.458000 0.000000 5.458000 ( 5.458000)
    ------------------------------------------------ total: 11.106000sec

    user system total real
    meth_with_begin_end 5.708000 0.000000 5.708000 ( 5.718000)
    meth_without_begin_end 5.608000 0.000000 5.608000 ( 5.608000)


    --
    vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
     
    Joel VanderWerf, Jan 14, 2007
    #20
    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.

Share This Page