Last active
January 3, 2016 05:29
-
-
Save timyates/8416286 to your computer and use it in GitHub Desktop.
Functional Lenses and Groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import groovy.transform.* | |
// Immutable test object | |
def tim = new Person( 'tim', new Address( 'Woo', 123 ) ) | |
// Lens for setting address for a person | |
Lens personAddress = new Lens( { p -> p.address }, { p, a -> new Person( p.name, a ) } ) | |
// And one for setting zipcode for an address | |
Lens addressZipcode = new Lens( { a -> a.zip }, { a, z -> new Address( a.street, z ) } ) | |
// Compose them into one for setting zipcode for a person | |
Lens personZipcode = addressZipcode << personAddress | |
// Simplistic test | |
assert personZipcode( tim, 100 ) == new Person( 'tim', new Address( 'Woo', 100 ) ) | |
////////////////////////////////// | |
// Test classes | |
@Immutable | |
class Address { | |
String street | |
Integer zip | |
} | |
@Immutable | |
class Person { | |
String name | |
Address address | |
} | |
////////////////////////////////// | |
// Lens implementation | |
@Immutable | |
class Lens { | |
Closure getter | |
Closure setter | |
def call( a ) { getter( a ) } | |
def call( a, b ) { setter( a, b ) } | |
Lens leftShift( Lens other ) { | |
new Lens( { a -> get( other.getter( a ) ) }, | |
{ a, b -> other.setter( a, setter( other.getter( a ), b ) ) } ) | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Maybe simpler with copyWith() ?
http://mrhaki.blogspot.fr/2013/11/groovy-goodness-create-copywith-method.html