共计 1394 个字符,预计需要花费 4 分钟才能阅读完成。
背景痛点:新手常踩的语法坑
刚接触 Skill 语言时,很多从 Python/JavaScript 转过来的开发者会下意识用其他语言的思维写代码。最典型的比如:

- 忽略动态类型检查 :Skill 不会自动做类型转换,但新手常写出
(concat 1 "2")这样的代码,导致运行时报错 - 混淆 list 和 array:
'(1 2 3)和array(1 2 3)在内存结构和操作 API 上有本质区别 - 误用过程定义 :
defun定义的函数如果不显式返回t/nil,可能产生非预期副作用
; 错误示例:缺少返回值的过程
(defun riskyFunc (x y)
(println (+ x y)) ; 这里没有 return 语句
)
语法精讲:Lisp 系语言的特有规则
1. 数据结构处理
- List:用单引号定义的惰性求值结构,注意
'(a b)和(list'a 'b)在宏展开时的区别 - Dict:相比 Python 字典,Skill 的
makeTable需要预声明键类型:
; 正确创建哈希表
(setq deviceTable (makeTable 'deviceTable 0))
(tablePut deviceTable "width" 100)
2. 函数定义三要素
- defun必须包含:参数列表、docstring(推荐)、显式返回值
- &optional和 &rest 参数的特殊处理:
(defun drawRect (width height &optional (layer "top") &rest options)
"绘制矩形,支持可变参数"
(when options (println "Extra opts:" options))
t ; 显式返回
)
代码实战:PCB 设计自动化脚本
带类型检查的参数验证
(defun checkLayerName (name)
(unless (stringp name)
(error "图层名必须是字符串"))
(unless (member name '("top""bottom" "inner1" "inner2"))
(error "非法图层名"))
t
)
; 时间复杂度 O(n) - member 函数遍历列表
递归文件遍历实现
(defun walkDirectory (path callback)
(foreach file (getDirFiles path)
(when (isDir file)
(walkDirectory file callback))
(funcall callback file) ; 执行回调
)
)
避坑指南:三大内存陷阱
- 动态作用域链 :
setq创建的变量会污染全局命名空间 - 未释放的表资源 :
makeTable创建的哈希表必须手动destroyTable - 闭包滥用:lambda 捕获的上下文变量可能导致意外引用
性能优化:skill++ 编译技巧
- 类型声明 :使用
declare指令帮助编译器优化 - 热点循环 :将递归改为
for迭代可提升 5 -10 倍性能
; 优化前(递归)(defun factorial (n)
(if (<= n 1) 1
(* n (factorial (1- n)))))
; 优化后(迭代)(defun factorial-opt (n)
(declare (number n))
(let ((result 1))
(for i 2 n
(setq result (* result i)))
result))
思考题
如何在不破坏现有代码的情况下,实现 Skill 5.0 到 6.0 新增语法的兼容层?建议从这几个方向考虑:
- 用
cond判断版本号加载不同实现 - 通过宏包装新语法特性
- 运行时动态检测函数是否存在
正文完
