Skip to content

Instantly share code, notes, and snippets.

@DenisVerkhoturov
Last active June 3, 2019 11:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DenisVerkhoturov/f1e3111735a40d398b0dcb476b9b076b to your computer and use it in GitHub Desktop.
Save DenisVerkhoturov/f1e3111735a40d398b0dcb476b9b076b to your computer and use it in GitHub Desktop.
Function-based objects
package metamer.cmdparser;
import org.junit.jupiter.api.Test;
import java.util.List;
import java.util.function.Function;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
class OopTest {
@Test
public void weDontNeedNoObjects() {
final Function<List<Object>, Function<List<Object>, Object>> User = fields -> {
final Object type = "User";
final Object firstName = fields.get(0);
final Object lastName = fields.get(1);
final Object age = fields.get(2);
final Function<Object, Function<List<Object>, Object>> methods = name -> arguments -> {
switch ((String) name) {
case "type" : return type;
case "firstName": return firstName;
case "lastName" : return lastName;
case "age" : return age;
case "fullName" : return String.format("%s %s", firstName, lastName);
case "sayHello" : return String.format("Hello, %s! =D", arguments.get(0));
case "equals" :
final Function<List<Object>, Object> another = (Function<List<Object>, Object>) arguments.get(0);
return type == another.apply(List.of("type"))
&& firstName == another.apply(List.of("firstName"))
&& lastName == another.apply(List.of("lastName"))
&& age == another.apply(List.of("age"));
default: return String.format("Method with name '%s' does not exist.", name);
}
};
return call -> {
final Object method = call.get(0);
final List<Object> arguments = call.subList(1, call.size());
return methods.apply(method).apply(arguments);
};
};
final Function<List<Object>, Object> jamesBond = User.apply(List.of("James", "Bond", 42));
final Function<List<Object>, Object> clone = User.apply(List.of("James", "Bond", 42));
final Function<List<Object>, Object> harryPotter = User.apply(List.of("Harry", "Potter", 11));
assertThat( jamesBond.apply(List.of("firstName")) , is("James") );
assertThat( jamesBond.apply(List.of("lastName")) , is("Bond") );
assertThat( jamesBond.apply(List.of("age")) , is(42) );
assertThat( jamesBond.apply(List.of("fullName")) , is("James Bond") );
assertThat( jamesBond.apply(List.of("sayHello", "world")) , is("Hello, world! =D") );
assertThat( jamesBond.apply(List.of("equals", clone)) , is(true) );
assertThat( jamesBond.apply(List.of("equals", harryPotter)) , is(false) );
}
}
(define (Any)
(define type "Any")
(define (dispatch method)
(cond ((eq? method 'type ) type )
((eq? method 'equal?) equal?)
)
)
dispatch
)
(define (User firstName lastName age)
(define type "User")
(define super Any)
(define (dispatch method)
; Private definitions
(define fullName (string-append firstName " " lastName))
(define (sayHello name) (string-append "Hello, " name "! =D"))
(define (_equal? that)
(for-all values (list
(equal? type (that 'type) )
(equal? firstName (that 'firstName))
(equal? lastName (that 'lastName) )
(equal? age (that 'age) ))
)
)
; Public definitions
(cond ((eq? method 'type ) type )
((eq? method 'firstName) firstName)
((eq? method 'lastName ) lastName )
((eq? method 'fullName ) fullName )
((eq? method 'age ) age )
((eq? method 'sayHello ) sayHello )
((eq? method 'equal? ) _equal? )
(else (super method))
))
dispatch
)
(define (PoliteUser firstName lastName age)
(define type "PoliteUser")
(define super (User firstName lastName age))
; Public definitions
(define (dispatch method)
(define (sayHello name) (string-append "Greetings, " name "."))
(cond ((eq? method 'type ) type )
((eq? method 'sayHello ) sayHello )
(else (super method))
))
dispatch
)
(define (test name boolean) (display (string-append (if boolean "[PASS]" "[FAIL]") " " name "\n")))
(define jamesBond (User "James" "Bond" 42))
(define clone (User "James" "Bond" 42))
(define harryPotter (User "Harry" "Potter" 11))
(test "Can get first name" (equal? (jamesBond 'firstName) "James"))
(test "Can get last name" (equal? (jamesBond 'lastName) "Bond"))
(test "Can get full name" (equal? (jamesBond 'fullName) "James Bond"))
(test "Can get age" (equal? (jamesBond 'age) 42))
(test "Can say hello" (equal? ((jamesBond 'sayHello) "world") "Hello, world! =D"))
(test "Can confirm if two users are equal" ((jamesBond 'equal?) clone))
(test "Can deny if two users are different" (not ((jamesBond 'equal?) harryPotter)))
(define alfred (PoliteUser "Alfred" "Pennyworth" 76))
(test "Alfer know his first name" (equal? (alfred 'firstName) "Alfred"))
(test "Alfer know his last name" (equal? (alfred 'lastName) "Pennyworth"))
(test "Alfer know his full name" (equal? (alfred 'fullName) "Alfred Pennyworth"))
(test "Alfer know his age" (equal? (alfred 'age) 76))
(test "Alfer greets politely" (equal? ((alfred 'sayHello) "world") "Greetings, world."))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment