无法返回引用
数据传递包括两种,返回值和参数。
很可惜,newlisp的返回值只进行值拷贝,也就是返回副本,并没有方法返回引用。
那么看看参数吧,通过参数有两种方法传递引用,一种是通过使用单引号,另一种是利用context.
单引号symbol传递参数引用
(define (change-list aList) (push 999 (eval aList)))
(set 'data '(1 2 3 4 5))
; note the quote ' in front of data
(change-list 'data) → (999 1 2 3 4 5)
data → (999 1 2 3 4 5)
这种方法很简单,推荐使用。但是注意一个缺点:实参不能和形参名称相同。
> (set 'aList '(a b c d))
(a b c d)
> (change-list 'aList)
ERR: list or string expected : (eval aList)
called from user defined function change-list
通过context的default functor保存引用
context的default functor可以接受变参,因此可以将数据通过变参传递给context的default functor,加以保存
;; the default functor for holding data
(define Mylist:Mylist '(a b c d e f g))
(Mylist 3) → d
(setf (Mylist 3) 'D) → D
Mylist:Mylist → (a b c D e f g)
如果将Mylist保存到文件里面,可以看到:
(save "/opt/mm" 'Mylist)
(context 'Mylist)
(set 'Mylist:Mylist '(MAIN:a MAIN:b MAIN:c MAIN:D MAIN:e MAIN:f MAIN:g))
(context MAIN)
通过context的default functor访问和改变数据
既然可以保存,就可以访问和修改。
(first Mylist) → a
(reverse Mylist) → (g f e D c b a)
(set 'Str:Str "acdefghijklmnop")
(upper-case Str) → "ACDEFGHIJKLMNOP"
通过context传递参数引用
是的,既然context是一个symbol,也可将其作为参数传递,只不过不需要前面用单引号来表示引用传递。
下面是通过default functor保存数据,然后将context作为参数传递给另一个函数
;; use a default functor to hold a list
(set 'Mydb:Mydb (sequence 1 100000))
(define (change-db obj idx value)
(setf (obj idx) value))
; pass by context reference
(change-db Mydb 1234 "abcdefg")
(Mydb 1234) → "abcdefg"
通过context的symbol保存数据和传递参数引用
其实不一定非要default functor,context的symbol也行。
;; pass data by context reference
(set 'Mydb:data (sequence 1 100000))
(define (change-db obj idx value)
(setf (obj:data idx) value))
(change-db Mydb 1234 "abcdefg")
(nth 1234 Mydb:data) → "abcdefg"
; or
(Mydb:data 1234) → "abcdefg"
这种方法有个缺点,就是函数内部需要理解context的内部结构,比如例子中的obj:data.