racket/class: add send+ for functional style OO
This commit is contained in:
parent
db57b78e18
commit
fcab398081
|
@ -37,7 +37,7 @@
|
||||||
object% object? externalizable<%> printable<%> writable<%> equal<%>
|
object% object? externalizable<%> printable<%> writable<%> equal<%>
|
||||||
object=?
|
object=?
|
||||||
new make-object instantiate
|
new make-object instantiate
|
||||||
send send/apply send/keyword-apply send* dynamic-send
|
send send/apply send/keyword-apply send* send+ dynamic-send
|
||||||
class-field-accessor class-field-mutator with-method
|
class-field-accessor class-field-mutator with-method
|
||||||
get-field set-field! field-bound? field-names
|
get-field set-field! field-bound? field-names
|
||||||
private* public* pubment*
|
private* public* pubment*
|
||||||
|
@ -4195,6 +4195,7 @@ An example
|
||||||
(unless (symbol? method-name) (raise-argument-error 'dynamic-send "symbol?" method-name))
|
(unless (symbol? method-name) (raise-argument-error 'dynamic-send "symbol?" method-name))
|
||||||
(keyword-apply (find-method/who 'dynamic-send obj method-name) kws kw-vals obj args))))
|
(keyword-apply (find-method/who 'dynamic-send obj method-name) kws kw-vals obj args))))
|
||||||
|
|
||||||
|
;; imperative chained send
|
||||||
(define-syntax (send* stx)
|
(define-syntax (send* stx)
|
||||||
(syntax-case stx ()
|
(syntax-case stx ()
|
||||||
[(form obj clause ...)
|
[(form obj clause ...)
|
||||||
|
@ -4211,6 +4212,18 @@ An example
|
||||||
#f "bad method call" stx clause-stx)]))
|
#f "bad method call" stx clause-stx)]))
|
||||||
(syntax->list (syntax (clause ...)))))))]))
|
(syntax->list (syntax (clause ...)))))))]))
|
||||||
|
|
||||||
|
;; functional chained send
|
||||||
|
(define-syntax (send+ stx)
|
||||||
|
(define-syntax-class send-clause
|
||||||
|
#:description "method clause"
|
||||||
|
(pattern [name:id . args]))
|
||||||
|
(syntax-parse stx
|
||||||
|
[(_ obj:expr clause-0:send-clause clause:send-clause ...)
|
||||||
|
(quasisyntax/loc stx
|
||||||
|
(let ([o (send obj clause-0.name . clause-0.args)])
|
||||||
|
(send+ o clause ...)))]
|
||||||
|
[(_ obj:expr) (syntax/loc stx obj)]))
|
||||||
|
|
||||||
;; find-method/who : symbol[top-level-form/proc-name]
|
;; find-method/who : symbol[top-level-form/proc-name]
|
||||||
;; any[object]
|
;; any[object]
|
||||||
;; symbol[method-name]
|
;; symbol[method-name]
|
||||||
|
@ -5112,7 +5125,7 @@ An example
|
||||||
object% object? object=? externalizable<%> printable<%> writable<%> equal<%>
|
object% object? object=? externalizable<%> printable<%> writable<%> equal<%>
|
||||||
new make-object instantiate
|
new make-object instantiate
|
||||||
get-field set-field! field-bound? field-names
|
get-field set-field! field-bound? field-names
|
||||||
send send/apply send/keyword-apply send* dynamic-send
|
send send/apply send/keyword-apply send* send+ dynamic-send
|
||||||
class-field-accessor class-field-mutator with-method
|
class-field-accessor class-field-mutator with-method
|
||||||
private* public* pubment*
|
private* public* pubment*
|
||||||
override* overment*
|
override* overment*
|
||||||
|
|
|
@ -1156,6 +1156,33 @@ is the same as
|
||||||
(send o end-edit-sequence))
|
(send o end-edit-sequence))
|
||||||
]}
|
]}
|
||||||
|
|
||||||
|
@defform/subs[(send+ obj-expr msg ...)
|
||||||
|
([msg (method-id arg ...)
|
||||||
|
(method-id arg ... . arg-list-expr)])]{
|
||||||
|
|
||||||
|
Calls methods (in order) starting with the object produced by
|
||||||
|
@racket[obj-expr]. Each method call will be invoked on the result of
|
||||||
|
the last method call, which is expected to be an object. Each
|
||||||
|
@racket[msg] corresponds to a use of @racket[send].
|
||||||
|
|
||||||
|
This is the functional analogue of @racket[send*].
|
||||||
|
|
||||||
|
@defexamples[#:eval class-eval
|
||||||
|
(define point%
|
||||||
|
(class object%
|
||||||
|
(super-new)
|
||||||
|
(init-field [x 0] [y 0])
|
||||||
|
(define/public (move-x dx)
|
||||||
|
(new this% [x (+ x dx)]))
|
||||||
|
(define/public (move-y dy)
|
||||||
|
(new this% [y (+ y dy)]))))
|
||||||
|
|
||||||
|
(send+ (new point%)
|
||||||
|
(move-x 5)
|
||||||
|
(move-y 7)
|
||||||
|
(move-x 12))
|
||||||
|
]}
|
||||||
|
|
||||||
@defform[(with-method ((id (obj-expr method-id)) ...)
|
@defform[(with-method ((id (obj-expr method-id)) ...)
|
||||||
body ...+)]{
|
body ...+)]{
|
||||||
|
|
||||||
|
|
|
@ -1189,6 +1189,7 @@
|
||||||
(super-make-object))])
|
(super-make-object))])
|
||||||
(test 100 'priv (send (make-object c% 100) priv))
|
(test 100 'priv (send (make-object c% 100) priv))
|
||||||
(test 100 'priv (send* (make-object c% 100) (priv)))
|
(test 100 'priv (send* (make-object c% 100) (priv)))
|
||||||
|
(test 100 'priv (send+ (make-object c% 100) (priv)))
|
||||||
(test 100 'priv (with-method ([p ((make-object c% 100) priv)]) (p)))
|
(test 100 'priv (with-method ([p ((make-object c% 100) priv)]) (p)))
|
||||||
(test 100 'gen-priv-cls (send-generic (make-object c% 100) (generic c% priv)))
|
(test 100 'gen-priv-cls (send-generic (make-object c% 100) (generic c% priv)))
|
||||||
(test 100 'gen-priv-intf (send-generic (make-object c% 100) (generic i<%> priv)))
|
(test 100 'gen-priv-intf (send-generic (make-object c% 100) (generic i<%> priv)))
|
||||||
|
@ -1197,6 +1198,7 @@
|
||||||
(test #t object? (make-object c% 10))
|
(test #t object? (make-object c% 10))
|
||||||
(err/rt-test (send (make-object c% 10) priv) exn:fail:object?)
|
(err/rt-test (send (make-object c% 10) priv) exn:fail:object?)
|
||||||
(err/rt-test (send* (make-object c% 10) (priv)) exn:fail:object?)
|
(err/rt-test (send* (make-object c% 10) (priv)) exn:fail:object?)
|
||||||
|
(err/rt-test (send+ (make-object c% 10) (priv)) exn:fail:object?)
|
||||||
(err/rt-test (with-method ([p ((make-object c% 100) priv)]) (p)) exn:fail:object?)
|
(err/rt-test (with-method ([p ((make-object c% 100) priv)]) (p)) exn:fail:object?)
|
||||||
(err/rt-test (generic c% priv) exn:fail:object?)
|
(err/rt-test (generic c% priv) exn:fail:object?)
|
||||||
(err/rt-test (make-generic c% 'priv) exn:fail:object?))
|
(err/rt-test (make-generic c% 'priv) exn:fail:object?))
|
||||||
|
@ -1211,6 +1213,19 @@
|
||||||
(super-new)))])
|
(super-new)))])
|
||||||
(test 16 'send-using-local (send (new c%) pub 3)))
|
(test 16 'send-using-local (send (new c%) pub 3)))
|
||||||
|
|
||||||
|
;; ------------------------------------------------------------
|
||||||
|
;; `send+' tests
|
||||||
|
|
||||||
|
(let ([c% (class object%
|
||||||
|
(define/public (m . args) this)
|
||||||
|
(super-new))])
|
||||||
|
(syntax-test #'(send+ (new c%) (m 5) (m 10)))
|
||||||
|
(syntax-test #'(send+ (new c%) (m . (1 2 3))))
|
||||||
|
(syntax-test #'(send+ (new c%) (m 5) (m . (1 2 3))))
|
||||||
|
|
||||||
|
(test #t object? (send+ (new c%) (m 5) (m 15)))
|
||||||
|
(test #t object? (send+ (new c%) (m 5) (m . (1 2 3 4)))))
|
||||||
|
|
||||||
;; ------------------------------------------------------------
|
;; ------------------------------------------------------------
|
||||||
;; `new' tests
|
;; `new' tests
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user