Skip to content

Instantly share code, notes, and snippets.

@plexus
Created December 9, 2014 14:01
Show Gist options
  • Save plexus/42c6c9c63212182ee440 to your computer and use it in GitHub Desktop.
Save plexus/42c6c9c63212182ee440 to your computer and use it in GitHub Desktop.
# How to update values on immutable objects?
class Foo
def initialize(attrs)
@x = attrs.fetch(:x)
@y = attrs.fetch(:y)
freeze
end
end
foo = Foo.new(x: 5, y: 7)
# Option 0
# Use x=9. Would be great but doesn't work in Ruby, it will always
# return it's argument so you can chain assignments
# Option 1
class Foo
attr_reader :x, :y
def set_x(x)
self.class.new(x: x, y: y)
end
end
foo.set_x(9) # => #<Foo:0x007fbe1e7acc48 @x=9, @y=7>
foo # => #<Foo:0x007fbe1e7acd60 @x=5, @y=7>
# Option 2
Undefined = Object.new
def Undefined.inspect ; 'Undefined' ; end
class Foo
def x(x = Undefined)
if x == Undefined
@x
else
self.class.new(x: x, y: @y)
end
end
end
foo.x(9) # => #<Foo:0x007fbe1e7ac4c8 @x=9, @y=7>
foo # => #<Foo:0x007fbe1e7acd60 @x=5, @y=7>
# Option 3
# Same as #1, but with_x, apparently common in Scala/Java
# Option 4
# Anima style, use explicit "update" function
require 'anima'
class Foo
include Anima.new(:x, :y)
include Anima::Update
end
foo.update(x: 9) # => #<Foo x=9 y=7>
foo # => #<Foo x=5 y=7>
# Option 5
# ...
# Any other ideas?
@plexus
Copy link
Author

plexus commented Dec 10, 2014

Great to get so many replies on this! It seems some people also name their update / copy / with method new. I've seen this and think I might have actually used it at some point, although I'm not a fan because it's different enough from the class method new to cause confusion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment