请求有关代码风格/最佳实践的输入
Request input regarding code style / best practices
我正在尝试按照 Java (https://craftinginterpreters.com/control-flow.html) 中的此实现来用 Common Lisp 实现编程语言。
真正令人烦恼的事情之一是到处都有大量槽值。
当然我可以在每个带有槽的函数中添加一行,但这也是重复的,并且考虑到我的符号没有 :used 但我通过包引用它们,因为有很多符号来自许多模块,我不想忘记它们的来源,即使 with-slots 也需要完整的限定名称。所有这些在我看来都是非常糟糕的代码味道。
我用谷歌搜索并找到了金红石。通过它的 @object.slot 访问器,我设法极大地清理了我的代码。看看最后一次提交 https://github.com/AlbertoEAF/cl-lox/commit/84c0d62bf29bff9a2e0e77042a9108c168542b96?diff=split 摘录:
(我可以粘贴代码,但所有代码都可以在那个 repo 上找到,我想展示差异亮点)
它不仅删除了一些字符,更重要的是,减少了一层深度(槽值调用)和需要考虑的括号 - 这对琐碎的函数有很大帮助。
当我有很多符号名称并且无法再将它们全部导出时,情况会变得更糟,因为我开始在符号中发生冲突。
你们能给我输入代码吗?现在看起来好多了,但我很好奇是否有更好的方法?
谢谢!
在 class 定义中定义访问器函数还可以节省您的输入时间,同时不必使用非标准语法
如果您这样定义 CLOS class:
(defclass person ()
((name
:initarg :name)))
(defparameter *p* (make-instance 'person
:name "John"))
访问 *p*
中 name
插槽值的唯一方法是:
(slot-value *p* 'name)
;; "John"
(with-slots (name) *p*
name)
;; "John"
(with-slots ((nm name)) *p*
nm)
;; "John"
但是如果你为每个插槽定义一个:accessor
,你可以使用函数名
作为 :accessor
的参数给出,不必使用 slot-value
或 with-slots
,以
访问并改变它(setf
-able!)。
(defclass person ()
((name
:initarg :name
:accessor nm)))
(nm *p*)
;; "John"
(setf (nm *p*) "Doe")
;; "Doe"
(nm *p*)
;; "Doe"
然而,约定是,使用插槽名称也作为 :accessor
方法的名称
姓名:
(defclass person ()
((name
:initarg :name
:accessor name))) ;; but better use the slot name as accessor
(name *p*)
;; "John"
(setf (name *p*) "Doe")
(name *p*)
;; "Doe"
:accessor
方法(泛型函数)是针对对象的
这个class。因此,您不必担心名称-space 冲突。
(defclass house ()
((address
:initarg :address
:accessor addr)))
;; you cannot use `address` because it is already occupied
;; by a system's function/symbol -> see under `(describe 'address)`
(defparameter *h* (make-instance 'house :address "Bakerstreet 1"))
(name *h*)
;; EVAL: undefined function name OR:
;; NO-APPLICABLE-METHOD error (in the case
;; that other classes exist with a `name` accessor method.
(addr *h*)
;; "Bakerstreet 1"
(addr *p*)
;; *** - NO-APPLICABLE-METHOD: When calling #<STANDARD-GENERIC-FUNCTION ADDR>
;; with arguments (#<PERSON #x1B06B79E>), no method is applicable.
;;
我正在尝试按照 Java (https://craftinginterpreters.com/control-flow.html) 中的此实现来用 Common Lisp 实现编程语言。
真正令人烦恼的事情之一是到处都有大量槽值。
当然我可以在每个带有槽的函数中添加一行,但这也是重复的,并且考虑到我的符号没有 :used 但我通过包引用它们,因为有很多符号来自许多模块,我不想忘记它们的来源,即使 with-slots 也需要完整的限定名称。所有这些在我看来都是非常糟糕的代码味道。
我用谷歌搜索并找到了金红石。通过它的 @object.slot 访问器,我设法极大地清理了我的代码。看看最后一次提交 https://github.com/AlbertoEAF/cl-lox/commit/84c0d62bf29bff9a2e0e77042a9108c168542b96?diff=split 摘录:
(我可以粘贴代码,但所有代码都可以在那个 repo 上找到,我想展示差异亮点)
它不仅删除了一些字符,更重要的是,减少了一层深度(槽值调用)和需要考虑的括号 - 这对琐碎的函数有很大帮助。
当我有很多符号名称并且无法再将它们全部导出时,情况会变得更糟,因为我开始在符号中发生冲突。
你们能给我输入代码吗?现在看起来好多了,但我很好奇是否有更好的方法?
谢谢!
在 class 定义中定义访问器函数还可以节省您的输入时间,同时不必使用非标准语法
如果您这样定义 CLOS class:
(defclass person ()
((name
:initarg :name)))
(defparameter *p* (make-instance 'person
:name "John"))
访问 *p*
中 name
插槽值的唯一方法是:
(slot-value *p* 'name)
;; "John"
(with-slots (name) *p*
name)
;; "John"
(with-slots ((nm name)) *p*
nm)
;; "John"
但是如果你为每个插槽定义一个:accessor
,你可以使用函数名
作为 :accessor
的参数给出,不必使用 slot-value
或 with-slots
,以
访问并改变它(setf
-able!)。
(defclass person ()
((name
:initarg :name
:accessor nm)))
(nm *p*)
;; "John"
(setf (nm *p*) "Doe")
;; "Doe"
(nm *p*)
;; "Doe"
然而,约定是,使用插槽名称也作为 :accessor
方法的名称
姓名:
(defclass person ()
((name
:initarg :name
:accessor name))) ;; but better use the slot name as accessor
(name *p*)
;; "John"
(setf (name *p*) "Doe")
(name *p*)
;; "Doe"
:accessor
方法(泛型函数)是针对对象的
这个class。因此,您不必担心名称-space 冲突。
(defclass house ()
((address
:initarg :address
:accessor addr)))
;; you cannot use `address` because it is already occupied
;; by a system's function/symbol -> see under `(describe 'address)`
(defparameter *h* (make-instance 'house :address "Bakerstreet 1"))
(name *h*)
;; EVAL: undefined function name OR:
;; NO-APPLICABLE-METHOD error (in the case
;; that other classes exist with a `name` accessor method.
(addr *h*)
;; "Bakerstreet 1"
(addr *p*)
;; *** - NO-APPLICABLE-METHOD: When calling #<STANDARD-GENERIC-FUNCTION ADDR>
;; with arguments (#<PERSON #x1B06B79E>), no method is applicable.
;;