要求提供有关代码风格最佳实践的意见

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

我想按照这个在Java中的实现,用Common Lisp实现一种编程语言(https:/craftinginterpreters.comcontrol-flow.html。).

其中有一点是非常麻烦的,就是到处都是大量的槽值。

固然我可以在每个函数中添加一行with-slots,但这也是重复的,而且鉴于我的符号不是:use,而是我用包来引用,因为有很多模块的符号,我不想失去它们从哪里来的踪迹,即使with-slots也需要完整的限定名。所有这些在我看来都是非常糟糕的代码味道。

我上网查了一下,发现rutils。有了它的@object.slot接入器,我成功地清理了我的代码。看看最后的提交 https:/github.comAlbertoEAFcl-loxcommit84c0d62bf29bff9a2e0e77042a9108c168542b96?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你可以使用函数namegiven作为参数的 :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.