How about something like this:
===8<---cut here---
module Memoizer
def memoize(name, &blk)
var_name = "@#{name}"
define_method(name) do
if instance_variable_defined?(var_name)
puts "using existing value"
instance_variable_get(var_name)
else
puts "calling block"
instance_variable_set(var_name, blk.call)
end
end
end
end
# => :memoize
class Greeter
extend Memoizer # note that's *extend*, not *include*
memoize(:greeting) { "Hi!" }
memoize(:farewell) { "Bye!" }
def check_greeting
instance_variable_get(:@greeting)
end
def check_farewell
instance_variable_get(:@farewell)
end
def say_hi
puts greeting
end
def say_bye
puts farewell
end
end
# => :say_bye
g = Greeter.new
# => #<Greeter:0xsomebighexnumber>
g.check_greeting
# => nil
g.say_hi
# prints "calling block" and then "Hi!"
# => nil
g.check_greeting
# => "Hi!"
g.say_hi
# prints "using existing value" and then "Hi!"
# => nil
g.check_farewell
# => nil
g.say_bye
# prints "calling block" and then "Bye!"
# => nil
g.check_farewell
# => "Bye!"
g.say_bye
# prints "using existing value" and then "Bye!"
# => nil
===8<---cut here---
Of course, remove the "puts"es for production use! 
This is simple enough yet widely enough useful for those not versed in
metaprogramming themselves, that I wouldn't be at all surprised if
there's already something like this. If no, I'll gladly make a public
gem of it....
-Dave
···
On Fri, Jan 13, 2017 at 6:22 AM, Daniel Ferreira <subtileos@gmail.com> wrote:
Or why not:
lazy(:foo) do
"Foo"
end
--
Dave Aronson, consulting software developer of Codosaur.us,
PullRequestRoulette.com, Blog.Codosaur.us, and Dare2XL.com.