Crystal: Lazy getter macro

Created on 20 Jul 2016  路  3Comments  路  Source: crystal-lang/crystal

This idiom is pretty common:

class Foo
  def time
    @time ||= Time.now
  end
end

class Foo
  def time
    @time ||= Time.now
  end
end

foo = Foo.new
p foo.time # => 2016-07-20 17:31:19 -0300
sleep 1
p foo.time # => 2016-07-20 17:31:19 -0300

It would be nice if the standard library provided a macro for this. Just very few strokes would be saved, but it's probably more clear and idiomatic this way.

Implementing this is very easy. For example:

class Object
  macro lazy_getter(name)
    def {{name.target.id}}
      @{{name.target.id}} ||= {{name.value}}
    end
  end
end

class Foo
  lazy_getter time = Time.now
end

But maybe it doesn't look very nice. Some thoughts for an API:

lazy_getter time = Time.now
getter lazy: time = Time.now
lazy getter: time = Time.now

These last two can be implemented as an overload with required named arguments. I personally like the second form, but I wouldn't mind the first one.

Thoughts?

accepted compiler

Most helpful comment

Also both, getter(time) { Time.now } and getter time do Time.now end will work too.

All 3 comments

What about letting getter take block?

getter time : Time { Time.now }

That can allow for the more complex, multline cases where you would normally do @foo ||= begin; ... end

Looks good at first, but what if I don't need to specify the type? Just Time.now is enough here to guess the type from that. But this doesn't work:

getter time { Time.now }

because the block is bound to time. But we could use a symbol and problem solved, though it's not consistent to other forms of getter that allow just a name. That is, this works:

getter :time { Time.now }

(I don't mind having to use a symbol, specially because the lazy form is less common than other forms)

Also both, getter(time) { Time.now } and getter time do Time.now end will work too.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jhass picture jhass  路  3Comments

oprypin picture oprypin  路  3Comments

relonger picture relonger  路  3Comments

paulcsmith picture paulcsmith  路  3Comments

lgphp picture lgphp  路  3Comments