syntax: (set sym-1 exp-1 [sym-2 exp-2 ... ])
下面是例子:
> (set 'mysymbol "ebd")
"ebd"
> (upper-case mysymbol)
"EBD"
上面第一句设置了一个symbol, 值为字符串。
第二句使用该symbol。注意此时无需单引号。
注意:
1. 这里set定义了全局的symbol, 不过只能在当前context下可见。
2 如果有多个sym和exp,则set返回最后一组exp求值的结果
如果使用let,则只定义了局部的symbol.
local和let差不多,只不过会将所有symbol初始化为nil
这应该是本文最重要的部分。lisp的动态特性在这里充分展现。在很多语言里面,你声明一个变量的工作必须在编译期间或者更早之前完成,在运行时声明一个变量是不可能的。而sym允许这样做。
syntax: (sym string [sym-context [nil-flag]])
syntax: (sym number [sym-context [nil-flag]])
syntax: (sym symbol [sym-context [nil-flag]])
你可以在运行时从一个web server获得一个字符串,然后用(sym)将其转变成一个symbol,之后就可以对其赋值。
(set (sym "var") 345) → 345
var
这就可以解决我之前的一个问题,我想在运行时从Tree创建一个新的Context的时候,之前的写法是固定的:
(new Tree 'MyTree)
其实'MyTree可以在运行时变成若干个,比如在一个循环算法中,变成三个: 'MyTree1, 'MyTree2 和 'MyTree3
就要靠(sym)来解决:
#!/usr/bin/newlisp
(define (update-tree tree-name key value)
(let (mm (new Tree (sym tree-name)))
(mm key value)))
(update-tree "MyTree" "a" 1)
(update-tree "MyTree" "b" 2)
(println ((eval (sym "MyTree")))) ;; (("a" 1) ("b" 2))
(println ((eval (sym "MyTree")) "a")) ;; 1
(set 'name-list '("A" "B"))
(dolist (name name-list)
(update-tree name "x" 1)
(update-tree name "y" 2))
(println ((eval (sym (name-list 0))))) ;; (("x" 1) ("y" 2))
(println ((eval (sym (name-list 1))))) ;; (("x" 1) ("y" 2))
(exit)
update-tree 函数是关键,可以指定tree的context名称(string类型),然后内部使用sym将tree-name转换成symbol,就可以调用(new Tree ..)了。
注意获得tree的时候需要eval。下面是输出结果:
(("a" 1) ("b" 2))
1
(("x" 1) ("y" 2))
(("x" 1) ("y" 2))
sym第三个重载形式可以获取symbol的字符串名称,不过为了防止求值,这里可以利用宏来帮一下忙:
> (define-macro (get-symbol-name s) (sym s))
(lambda-macro (s) (sym s))
> (set 'Foo "xx")
"xx"
> (get-symbol-name Foo)
Foo
sym还可以创建在newLISP中原本不合法的symbol,比如:
;; using sym for simulating hash tables
(set (sym "John Doe" 'MyDB) 1.234)
(set (sym "(" 'MyDB) "parenthesis open")
(set (sym 12 'MyDB) "twelve")
(eval (sym "John Doe" 'MyDB)) → 1.234
(eval (sym "(" 'MyDB)) → "parenthesis open"
(eval (sym 12 'MyDB)) → "twelve"
;; delete a symbol from a symbol table or hash
(delete (sym "John Doe" 'MyDB)) → true
注意delete可以删除symbol.
未完待续...