1

Take the following example:

greeting = "world hello".split.reverse.join(" ")
greeting << ", here me shouting!!"
greeting.upcase!

p greeting # "HALLO WORLD, HERE ME SHOUTING!!"

This uses the local variable greeting to store a string. Now if we had already used this variable earlier in the code, its original value would now be lost.

greeting = "Hi World."

...

greeting = "world hello".split.reverse.join(" ")
greeting << ", here me shouting!!"
greeting.upcase!

p greeting # "HALLO WORLD, HERE ME SHOUTING!!" ... original "Hi World." is gone.

So I was thinking if there was a way to create a scope for small snippets like these by using a block. The variable greeting would go in the block and would only shadow the outer variable, not override it:

greeting = "Hi World."

"world hello".scope do |greeting|
  greeting.split.reverse.join(" ")
  greeting << ", here me shouting!!"
  greeting.upcase!
  p greeting # "HALLO WORLD, HERE ME SHOUTING!!"
end

p greeting # "Hi World."

Note the method scope I used here. I monkeypatched this method into Object. scope takes the block and yields it with the local variable of self:

class Object
  def scope
    yield self
  end
end

I don't feel exactly comfortable, to rely on monkey-patching the Object class, especially with a method called scope, which seems likely to be overridden by other classes, whose instances then can't be scoped like this anymore.

So, is there a built-in way in Ruby that does this?

Also - if I have to stay with monkey-patching - I was thinking that self might be a better method name than scope. Even though also keyword, it can be defined as a method name; it works, I tested it. self seems pretty unlikely to be overriden by other classes. It would also fit well to the style of the other most commonly used "block-method" each:

collection.each do

"Execute the following block on each element."

object.self do

"Execute the following block on (your)self".

Are there any drawbacks of using self as a method name? (other naming suggestions appreciated).

Conkerchen
  • 720
  • 1
  • 4
  • 15
  • 2
    Is http://stackoverflow.com/questions/5010828/something-like-let-in-ruby relevant? Still using the same name in nested scope seems confusing to me. – Jokester Feb 22 '13 at 12:24

1 Answers1

1

This question has been asked repeatedly. One way is:

"world hello".instance_eval do
  ...
end

but this is heavy, and is not preferred. A better way suggested is:

"world hello".tap do |s|
  ...
  break s
end

But in your particular case, method chain is the simplest:

"world hello"
.split
.reverse
.join(" ")
.concat(", here me shouting!!")
.upcase
.tap{|s| p s}
sawa
  • 165,429
  • 45
  • 277
  • 381
  • This is not about method chaining but about namespaces. My examples were probably not the best to demonstrate what I had in mind. `tap` does exactly what I want, though. Thanks! – Conkerchen Feb 22 '13 at 16:55
  • Namespace is relevant when you consider constants. As long as you deal with local variables, namespace is irrelevant. – sawa Feb 22 '13 at 17:33