[racket] Applicable objects
On 12/14/10 11:53 AM, Jim Wise wrote:
> David Van Horn<dvanhorn at ccs.neu.edu> writes:
>> I learned that every Scala object that defines an apply method can be used
>> as a function. Cute. It's nice to see a language emphasize the symmetry
>> between objects and functions.
>
> Note that this is actually bi-directional in Scala -- any object which
> defines an unapply() method can be used in an ml-style pattern matching
> statement as if it were an algebraic type constructor...
I flushed out what Jay said using a match expander. This is the example
from the Scala tour:
http://www.scala-lang.org/node/112
#lang racket
(require test-engine/racket-tests)
(define applicable<%>
(interface* ()
([prop:procedure
(λ (obj x) (send obj apply x))])
apply))
(define-match-expander object
(λ (stx)
(syntax-case stx ()
[(object o x)
#'(app (λ (x) (send o unapply x))
(? (λ (x) x) x))])))
(define twice%
(class* object% (applicable<%>)
(define/public (apply x)
(* 2 x))
;; Number -> [Opt Number]
(define/public (unapply z)
(and (even? z) (quotient z 2)))
(super-new)))
(check-expect (match ((new twice%) 21)
[(object (new twice%) n) n])
21)
(check-error (match 21
[(object (new twice%) n) n])
"match: no matching clause for 21")
(test)