我有一个如下所述的scheme中的对象列表。如何可能调用对象函数时,例如从列表中取出第一个元素?
(define persons false)
(define length 10)
(let loop ((n 0))
(if (< n length)
(begin
(define newp (make-person))
(send newp setage (- 50 n))
(cond
((= n 0)
(set! persons (list newp)))
(else
(set! persons (cons persons newp)))
)
(loop (+ n 1))
)
)
)
(define (firstpersonage)
(send (car persons) getage)
)
当调用firstpersonage时,我得到的错误信息是没有这样的方法。是否有办法将第一个对象"cast"为"person"类型?
谢谢!
首先,请务必学会正确缩进Lisp。
第二,您的问题是您决定使用一堆副作用来构建Scheme中的人员列表(因此,您忽略了列表建设)。
在这种情况下我要做的是写
(define persons
(map (lambda (n)
(let ((newp (make-person)))
(send newp setage (- 50 n))
newp))
(iota 10)))
(define (firstpersonage)
(send (car persons) getage))
即定义person
为年龄从50岁到41岁依次递减的10人的列表。这样做可以避免许多错误的可能性,包括你刚刚被咬的那个。
如果你绝对、肯定地不能忍受放弃你的set!
,错误似乎在
(set! persons (cons persons newp))
cons
不附加两个列表,它在列表的头部添加一个新元素。例如
(cons 3 (list 2 1)) => (3 2 1)
如果你用相反的方法,你将无法得到你想要的
(cons (list 1 2) 3) => ((1 2) . 3)
你得到错误,因为你使用cons
错误的方式;你没有构造一个合适的列表。(cons persons newp)
创建了一个新的配对,把人放在car
中,把newp
放在cdr
中,所以当你完成后,persons
的car
中的东西不是那些人-物之一。您可能会发现(cdr persons)
是一个人-对象,而您可以很好地执行(send (cdr persons) getage)
。(cdar persons)
和(cdaar persons)
也是人-物。所以它的有点像是一个列表,只有项目在cdr
s中,尾巴在car
s中(直到你得到你用(list newp)
创建的初始列表,它又反过来了)。
无论如何,如果你把它转换成(cons newp persons)
,它应该可以工作