Consider the following, which prints ‘calling full’ twice:
module Types
include Dry::Types.module
NonEmptyString = Types::Strict::String.constrained(format: /\S+/)
end
class Person < Dry::Struct
attribute :first, Types::NonEmptyString
attribute :last, Types::NonEmptyString
def full
puts 'calling full'
first + ' ' + last
end
end
p = Person.new(first: 'John', last: 'Smith')
p p.full
p p.full
Of course I manually memoize full, or do it with a gem like memoist, etc:
def full
return @full if @full
puts 'calling full'
@full = first + ' ' + last
end
But with an immutable value object, this is redundant in a sense, because any function of my immutable values is guaranteed by referential transparency to be safe to memoize.
While there may be some edge cases where you don’t want to memoize for reasons like memory consumption, you very often do.
Does Dry::Struct offer any mechanism by which I can, at one fell swoop, say “memoize all the methods I add this value object”?
Or is Dry::Struct intended only for the base data, preferring to put “derived” data like the method full above into decorator objects?
@jonahx Personally, I have no problem with a method like this…
def full
first + ' ' + last
end
…being fully executed upon each invocation. It’s simply not a slow method. Memoization feels like overkill here.
I feel like having dry-struct automatically memoize ordinary methods added to the class would violate principle of least surprise. This is not how usual Ruby classes work, and I don’t think people would consider dry-struct’s purview to cover this, particularly when there are any number of memoizing libs already available (including Dry::Core::Memoizable).
If you wanted all your structs to memoize all their methods, one way would be to create your own in-app struct superclass which inherits from Dry::Struct and also implements its own .method_added which can then add in the memoizing logic.
Yeah that one ofc doesn’t matter… it was merely illustrative of the concept. You can imagine cases where the computation is slow enough that you want memoization, and I think it doesn’t hurt for cases like this.
and I don’t think people would consider dry-struct’s purview to cover this
Had been looking at memoist but wasn’t aware Dry provided one, thanks for pointing this out.
would be to create your own in-app struct superclass which inherits from Dry::Struct and also implements its own .method_added which can then add in the memoizing logic.