关于代码风格/最佳实践的请求输入

问题描述 投票:0回答:1

我正在尝试通过遵循Java(https://craftinginterpreters.com/control-flow.html)中的这种实现来在Common Lisp中实现一种编程语言。

真正令人烦恼的事情之一就是到处都有很多插槽值。

保证我可以在每个带有with-slot的函数中添加一行,但这也是重复的,并且鉴于我的符号不是:us,而是由包引用,因为许多模块中都有很多符号,我不想丢失它们的来源,即使是插槽也需要完整的合格名称。在我看来,所有这些似乎都非常难闻的代码气味。

我用Google搜索并找到了rutils。通过其@ object.slot访问器,我设法极大地清理了我的代码。只需查看最后的提交https://github.com/AlbertoEAF/cl-lox/commit/84c0d62bf29bff9a2e0e77042a9108c168542b96?diff=split摘录:

enter image description here

(我可以粘贴代码,但是所有代码都可以在该仓库中使用,我想显示差异突出显示)

不仅删除了一些字符,而且更重要的是,要考虑的深度(插槽值调用)和括号要少一个级别,这对平凡的功能很有帮助,但对平凡的功能来说是有用的。

[当我有很多符号名称时,情况变得更糟,因为我开始在符号中出现冲突,因此无法再全部导出它们。

你们能给我输入代码吗?现在看起来好多了,但我很好奇,似乎是更好的解决方法?

谢谢!

coding-style common-lisp clos
1个回答
3
投票

在类定义中定义访问器函数还可以节省一些键入时间,而不必使用非标准语法

如果您这样定义CLOS类:

(defclass person ()
  ((name
    :initarg :name)))

(defparameter *p* (make-instance 'person 
                     :name "John"))

访问name*p*插槽的插槽值的唯一方法是:

(slot-value *p* 'name)
;; "John"

(with-slots (name) *p*
  name)
;; "John"

(with-slots ((nm name)) *p*
  nm)
;; "John"

但是如果为每个插槽定义一个:accessor,则可以使用功能名称作为:accessor的参数给出,而不必使用slot-valuewith-slots访问并对其进行更改(setf-可行!)。

(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方法(通用函数)特定于以下对象这个班。因此,您不必担心名称空间冲突。

(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.
;; 

© www.soinside.com 2019 - 2024. All rights reserved.