ruby-optics
Simple library with common functional optics for Ruby.
Supported Ruby versions
This library officially supports the following Ruby versions:
- MRI >=
2.3.0
Installation
Add this to your Gemfile
gem 'ruby-optics'
and then run
bundle install
Or install it manually
gem install ruby-optics
Usage
Lens - is an object which encapsulates getter/setter functionality for immutable data in composable way.
Any lens consist of two functions set
and get
. get
describes how can retrieve a value from a whole object, and set
- how to update this value without mutating the object.
Example for getting/setting value by key from hash:
def hash_get(key)
-> (hash) { hash[key] }
end
def hash_set(key)
-> (new_value, hash) { hash.merge(key => new_value) }
end
To create lens you need to specify both these functions:
lens = Lens.new(hash_get(:foo), hash_set(:foo))
Then you can use the lens to retrieve, set and modify value by the key in arbitrary hash:
object = { foo: 1, bar: 2 }
lens.get(object)
=> 2
lens.set(3, object)
=> { foo: 3, bar: 2 }
lens.modify(object) { |foo| foo * 10 }
=> { foo: 10, bar: 2 }
object
=> { foo: 1, bar: 2 }
Note that set
and modify
operations don't mutate original value, thus keeping it unchanged.
The real power of lens comes from their compositional properties, which allows to creates lenses that works with arbitrary nested objects by composing them from simpler ones.
foo_lens = Lens.new(hash_get(:foo), hash_set(:foo))
bar_lens = Lens.new(hash_get(:bar), hash_set(:bar))
lens = foo_lens.compose_lens(bar_lens)
object = { foo: { bar: 1 } }
lens.get(object)
=> 1
lens.set(3, object)
=> { foo: { bar: 3 } }
lens.modify(object) { |foo| foo * 10 }
=> { foo: { bar: 10 } }
object
=> { foo: { bar: 1 } }
The library provides lens constructors for common cases, so you don't need to composes lenses yourself
lens = Optics.hash_lens(:foo, :bar)
License
See LICENSE
file.