Reputation: 89
Looking for a little wisdom from fellow Rubyists. For a while now, I've used the following for convenience in some of my applications, and I'm wondering if there's a language feature I'm just missing:
class Object
def as_block
yield
end
end
There are other uses, but the normal case for me is a conditional assignment that requires a little non-trivial logic. Two obvious ways to do this:
# via a second method:
def foo
@foo ||= set_foo
end
# via conditional logic:
def foo
if @foo
@foo
else
# do complicated stuff
end
end
Both of these approaches seem kind of ugly: in the first case, #set_foo seems extraneous, and the second just looks kind of nasty. So, instead, I like this:
def foo
@foo ||= as_block do
# do complicated stuff
end
end
The problem here (aside from monkey patching Object) is that it's really a dependency (on the monkey patch) that looks like a language feature. That is, something like this really shouldn't be in (say) a Rails initializer---it seems like it should be in a gem, so the dependency can be managed correctly. Then I'm packaging an entire gem to run five lines of code to monkey patch Object...
So, my questions: 1. Anyone else use this, or something like it? 2. Has the Ruby team ever considered including something like this by default? It seems like a really easy way to use blocks as plain old expressions, but it's not there (as far as I know) which makes me wonder if there's some reason for not including it, or... 3. Is there already some better way of doing this that I'm just unaware of?
Thanks!
-E
Upvotes: 1
Views: 109
Reputation: 48368
What you're looking for is begin ... end
. This isn't the same thing as a block
or Proc
, as it's not an object you can pass around or a closure which creates a new scope, but it should serve your purpose just fine:
def foo
@foo ||= begin
# do complicated stuff
end
end
Upvotes: 5
Reputation: 4982
You could use a lambda:
def foo
@foo ||= lambda do
# do complicated stuff
end.call
end
Note that it is important to call the lambda to actually execute the expression, ie
def foo
@foo ||= lambda do
# do complicated stuff
end
end
will return a lambda rather than your evaluated expression.
Upvotes: 2