Forum: Ruby return_on

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Trans (Guest)
on 2007-01-10 16:40
(Received via mailing list)
Sometimes i do this:

  return x if x

Anyway to code it as:

  return_on x

t.
Pit C. (Guest)
on 2007-01-10 18:00
(Received via mailing list)
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
Simon S. (Guest)
on 2007-01-10 18:29
(Received via mailing list)
On 1/10/07, Trans <removed_email_address@domain.invalid> 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?
Srinivas JONNALAGADDA (Guest)
on 2007-01-11 06:54
(Received via mailing list)
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
Devin M. (Guest)
on 2007-01-11 07:36
(Received via mailing list)
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.)
Trans (Guest)
on 2007-01-19 17:29
(Received via mailing list)
Simon S. wrote:
> 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.
Christian N. (Guest)
on 2007-01-19 17:29
(Received via mailing list)
"Trans" <removed_email_address@domain.invalid> writes:

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

def x
  @cache.fetch(:x) {
    @cache[:x] = result_of_stuff
  }
end
Pit C. (Guest)
on 2007-01-19 17:29
(Received via mailing list)
Trans schrieb:
> 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
Joel VanderWerf (Guest)
on 2007-01-19 17:30
(Received via mailing list)
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
Daniel F. (Guest)
on 2007-01-19 17:31
(Received via mailing list)
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.
Logan C. (Guest)
on 2007-01-19 17:31
(Received via mailing list)
On Wed, Jan 10, 2007 at 11:39:00PM +0900, Trans wrote:
> Sometimes i do this:
>
>   return x if x
>
> Anyway to code it as:
>
>   return_on x
>
> t.
>
This is pure unadulterated evil, however it did come up in #ruby-lang a
while ago, so I whipped up some good old fashioned homemade evil:

def try_return(&block)
   unless (blah = block.call).nil?
      GC.disable
      eval("return ObjectSpace._id2ref(#{blah.object_id})", block)
   end
ensure
  GC.enable
end

def f
  try_return { nil }
  try_return { 7 }
  0
end

p f
Devin M. (Guest)
on 2007-01-19 17:31
(Received via mailing list)
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?)
Trans (Guest)
on 2007-01-19 17:31
(Received via mailing list)
Pit C. wrote:
> > this gets rid of an extraneous variable too b/c otherwise, the more
>
>    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.
Rob S. (Guest)
on 2007-01-19 17:31
(Received via mailing list)
On 1/13/07, Trans <removed_email_address@domain.invalid> wrote:
> > >
>   def x
>     return r if r
>       break if result
>     end
>     if result
>       ...
>
> t.

Much like returning in ActiveSupport:
http://weblog.jamisbuck.org/2006/10/27/mining-acti...

- rob
Trans (Guest)
on 2007-01-19 17:31
(Received via mailing list)
Daniel F. wrote:
>   source = IO.read(__FILE__)
>   newName = ""
> #{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.
Gavin S. (Guest)
on 2007-01-19 17:31
(Received via mailing list)
On Jan 14, 1:34 am, "Trans" <removed_email_address@domain.invalid> 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
Trans (Guest)
on 2007-01-19 17:31
(Received via mailing list)
Rob S. wrote:

> Much like returning in ActiveSupport:
> http://weblog.jamisbuck.org/2006/10/27/mining-acti...

Yes, kind-a. However there's been a lot of focus on the more common
method cache usecase, but return_on could also be used multple times
too:

  def x(a,b)
    return_on foo(a)
    return_on foo(b)
    ,,,
  end

T.
Trans (Guest)
on 2007-09-26 00:30
(Received via mailing list)
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.
William J. (Guest)
on 2007-09-26 00:36
(Received via mailing list)
Joel VanderWerf wrote:
> >   @cache[:x] ||= begin
>    )
>
> 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"
Trans (Guest)
on 2007-09-26 00:42
(Received via mailing list)
Devin M. wrote:
> >       ...
>
> 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.
Joel VanderWerf (Guest)
on 2007-09-26 00:44
(Received via mailing list)
Gavin S. wrote:
>     # 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"
Joel VanderWerf (Guest)
on 2007-09-26 00:46
(Received via mailing list)
Devin M. wrote:
> 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)
Devin M. (Guest)
on 2007-09-26 00:46
(Received via mailing list)
Joel VanderWerf wrote:
> Gavin S. 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
Joel VanderWerf (Guest)
on 2007-09-26 00:47
(Received via mailing list)
William J. wrote:
>>>   @cache[:x] ||= begin
>> end
>> CACHING
> end
> "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"
This topic is locked and can not be replied to.