您试图实现的想法通常称为消息传递。这通过创建闭包范围来工作。在这个范围内,东西是被定义的,默认情况下是范围内的东西。在关闭结束时,返回调度程序功能。调度员从捕获的范围中获取消息并返回内容。通过这个私人的东西被公开。通常返回功能。如果调用者获得一个函数,调用者可以用任何参数调用函数,该函数接受。
您的实施有一些化妆品问题和一些失败。
你应该保持一种定义函数的方式。无论是更详细的语法:
(define f (lambda() (display "Hello, World!\n")))
或者更紧凑的语法:
(define (f) (display "Hello, World!\n"))
但不要混合使用它们。
首先,您必须将字符串转换为列表才能在序列上使用car
。这是通过功能string->list
完成的。您不能在字符串上使用car
。
然后你必须执行next
和peek
做正确的事情。将它作为list
的别名是不够的。函数next
消耗输入流中的字符。这意味着代码在某个地方最有可能改变某种状态。这需要使用set!
。
调度功能只比较符号。比较符号case
而不是cond
更容易。您也可以使用cond
,但输入更多。
字符序列通常限于封闭范围。如果通过seq
选择器将序列公开给调用范围,则违反了封装的想法。这通常只用于调试。
如果将错误消息传递给调度程序函数,那么抛出错误而不是返回无用或未定义的东西是明智的。
这显示了根据上述建议的make-source
的代码。
(define (make-source seq)
(let ((seq (string->list seq))) ;; convert string into list
(define (next)
(if (pair? seq)
(let ((c (car seq)))
(set! seq (cdr seq)) ;; mutation of the sequence
c)))
(define (peek)
(car seq))
(define (endl arg1 arg2) ;; use of the arguments
(map list->string
(map (lambda (x)
(list arg1 x arg2))
seq)))
(lambda (selector)
(case selector
((seq) seq) ;; this is only for debugging
;; for correct messages, just return the functions
((endl) endl)
((next) next)
((peek) peek)
;; throw error
(else (error "undefined"))))))
如果你打电话make-source
它生成的调度功能:
(define s (make-source "abc"))
现在你可以在符号调度程序的形式传递消息。
以下函数返回查看字符的函数。
(s 'peek) ;; => <procedure>
为了执行它,您必须使用应用程序两次。
((s 'peek)) ;; => a
如果您对双重应用程序感到不舒服,可以给它一个名称。
(define peek-s (s 'peek))
(peek-s) ;; => a
但你不能定义泛型这种方式。泛型是一个称为peek
而不是peek-s
的函数,它可以从属于source
对象类的任何对象中窥视。我们已经定义了peek-s
,它仅从s
对象中窥视。为了定义泛型,您必须阅读Thant Tessman paper "Adding Generics to Scheme"。由于这个和其他限制,上述方法有时称为poor man's objects。但是几乎每个Scheme都有一些由Common Lisp启发的对象系统,称为CLOS(Common Lisp Object System)或tiny CLOS。
最后,将参数传递给外露函数与将参数传递给函数一样简单。如果你有暴露的函数,你可以传递函数接受的任何东西。
((s 'endl) #\< #\>) ;; => ("<a>" "<b>" "<c>")
'(make-source“abc”)'是一个函数。 “next”和“peek”的定义是“本地的”,并且只存在于“make-source”中,但是没有什么意义(如在REPL中定义它们并测试它们)。我怀疑你在计划书中跳过了很多内容,需要从第1章的某个地方开始。 – molbdnilo
'(car seq)'的含义与'(list-ref seq 0)'相同。两者都不适用于字符串。 – molbdnilo
@molbdnilo,谢谢你的回复。我以这个帖子为例https://stackoverflow.com/questions/2954642/methods-and-properties-in-scheme-is-oop-possible-in-scheme。你能提供代码来修复错误的例子吗? –