为了在计划中模仿简单的OOP(只是为了好玩),我发现自己一遍又一遍地重复以下模式:
(define my-class ; constructor
(let ((let-for-name-encapsulation 'anything))
; object created from data is message passing interface
(define (this data)
(lambda (m)
(cond ((eq? m 'method1) (method1 data))
((eq? m 'method2) (method2 data))
(else (error "my-class: unknown operation error" m)))))
;
(define (method1 data)
(lambda (arg1 ...)
... )) ; code using internal 'data' of object
;
(define (method2 data)
(lambda (arg2 ...)
... ))
;
; returning three arguments constructor (say)
;
(lambda (x y z) (this (list 'data x y z)))))
我决定将所有内容都包含在let ((let-for-name-encapsulation ...
内,以避免在全局环境中泄露名称
能够为每个内部函数名称使用define
构造,从而增强可读性。我更喜欢这个难看的构造(let ((method1 (lambda (...
的解决方案,但由于有点人为的let-for-name-encapsulation
,我仍然不是很开心。任何人都可以建议一些简单的东西,使代码看起来更好吗?我是否需要学习宏以超越它?
答案 0 :(得分:3)
我经常使用该模式,但您实际上并不需要定义任何变量:
(define binding
(let ()
(define local-binding1 expression)
...
procedure-expression)))
我在SRFI的参考实现中已经看过它,所以它是一种常见的模式。基本上它是一种使letrec
没有额外的身份和lambda的方法。它可以很容易地成为一个宏,使它更平坦:
(define-syntax define/lexical
(syntax-rules ()
((_ binding body ...)
(define binding
(let ()
body ...)))))
;; test
(define/lexical my-class
(define (this data)
(lambda (m)
(cond ((eq? m 'method1) (method1 data))
((eq? m 'method2) (method2 data))
(else (error "my-class: unknown operation error" m)))))
(define (method1 data)
(lambda (arg1 ...)
... )) ; code using internal 'data' of object
(define (method2 data)
(lambda (arg2 ...)
... ))
;; returning three arguments constructor (say)
(lambda (x y z) (this (list 'data x y z))))
;; it works for procedures that return procedures as well
(define/lexical (count start end step)
(define ...)
(lambda ...))
当然,您也可以使用宏来简化对象系统。