gpt4 book ai didi

package - 为什么在我将代码打包到包中后,列表中只有两个元素不再被识别?

转载 作者:行者123 更新时间:2023-12-02 05:58:21 25 4
gpt4 key购买 nike

我开始接触 Lisp 中的 defpackage 并开始了一个可耻的开始,即一个我无法开始理解的错误。

下面的代码试图创建一种子语言来对向量执行中缀操作。我想将其用于涉及一些线性代数的项目。

我的代码的“核心”是 parse-infix。该函数找到具有最高优先级的运算符,调用apply-op 将所述运算符及其操作数替换为operator (operand, operand) 从而缩小列表,并迭代直到列表只包含结果。支持的运算符是四个规则、相等(将结果绑定(bind)到 Lisp 符号)和向量连接。

这是代码,完整无缺:

(defpackage :infix
(:use :common-lisp)
(:export operator-list
operators
parse-infix
infix))

(in-package :infix)

(defun parse-input (a)
"Turns symbols into numbers as necessary while reading an expression"
(if (symbolp a) (symbol-value a) a))

;; Definition of structure containing data for one operator

(defmacro mapf (op type)
""
`(lambda (a b)
(map ,type #'(lambda (x y)
(funcall ,op x y)) (parse-input a) (parse-input b))))

(defstruct (operator
(:conc-name op-)
(:constructor op (sym &key (func (mapf sym 'vector)) priority associativity n-operands)))
sym ; Operator symbol
func ; Function to be applied to operands
priority ; Other operators attributes
(associativity 'left-to-right) ; Evaluation order for operators
; that appear more than once in a row
(n-operands 2)) ; Number of operands (NOT IMPLEMENTED)

(defmacro operator-list (&body ops)
"Produces an operator list from a list of operator structs."
`(mapcar #'(lambda (y) (apply #'op
(mapcar #'(lambda (x) (if (listp x) (eval x) x)) y))) ',ops))


(defparameter operators
(operator-list
(+ :priority 4)
(- :priority 4)
(* :priority 3)
(/ :priority 3)
(^ :priority 2 :func expt :associativity right-to-left)
(& :priority 2 :func (lambda (x y) (concatenate 'vector x y)))
(= :priority 10 :func (lambda (x y) (set (intern (string x)) y))))
"Default set of operators, which perform arithmetic operations on
vectors lengthwise. If one vector is shorter than the other, the result
is truncated.")

(defun apply-op (b)
"Reads a segment of a list of the format operand/operator/operand (in 3 consecutive
cells) and leaves operator (operand, operand) in a single cell."
(setf (car b) (funcall (op-func (caadr b))
(car b)
(caddr b))
(cdr b) (cdddr b)))

(defun parse-infix (b &key (operator-list operators))
"Parses an infix expression by calling apply-op repeatedly until the entire
expression is processed."
(let ((expr (mapcar #'(lambda (x)
(case (type-of x)
(symbol (or (member x operator-list :key #'op-sym) x))
(cons (parse-infix x))
(otherwise x))) b)))
(loop while (cdr expr) do
(apply-op (reduce #'(lambda (x y &aux (op1 (caadr x)) (op2 (caadr y)))
(if (or (< (op-priority op2) (op-priority op1))
(and (= (op-priority op1) (op-priority op2))
(eq (op-associativity op1) 'right-to-left))) y x))
(remove-if #'listp (mapcon #'list expr) :key #'caddr)))
finally (return (car expr)))))

(defmacro infix (&rest b)
"Wrapper to create lists for parse-infix"
`(parse-infix ',b))

问题来了。这些功能似乎在工作...

? (infix (#(2 3) + #(4 5)) * #(2 2))
#(12 16)
? (infix (#(100) & (#(2 3) + #(4 5)) * #(2 2))) ; '& is concatenation
#(200 12)
? (infix A = #(5 5) + #(10 10))
#(15 15)
? A
#(15 15)

...但是当我离开包裹时,串联 (&) 运算符突然“死掉”:

? (in-package :cl-user)
#<Package "COMMON-LISP-USER">
? (infix:infix A = #(5 5) + #(10 10))
#(15 15)
? (infix:infix (#(2 3) + #(4 5)) * #(2 2))
#(12 16)
? (infix:infix (#(100) & (#(2 3) + #(4 5)) * #(2 2)))
> Error: The value & is not of the expected type LIST.
> While executing: (:INTERNAL INFIX:PARSE-INFIX), in process listener(1).
> Type :POP to abort, :R for a list of available restarts.
> Type :? for other options.
1 >

我试图跟踪包的功能并注意到,无论出于何种原因,当我离开 infix 包时,'& 不再被识别为运算符。我不知道为什么会这样。感谢任何输入。

附言。许多人可能已经注意到,所有这些都在 Clozure Common Lisp 中。

最佳答案

短篇小说

& 是包中的内部符号。

您需要将其导出以解决问题。

^ 也是如此:

(defpackage :infix
(:use :common-lisp)
(:export #:operator-list
#:operators
#:parse-infix
#:infix
#:&
#:^))

详情

当你输入时

(infix:infix (#(100) & (#(2 3) + #(4 5)) * #(2 2)))

cl-user 中包裹,符号 &+* 被读作 cl-user::&cl:+cl:* .请注意,后两者是从 common-lisp包,因此在您的 infix 包中也可用:

(eq 'infix::+ 'cl-user::+)
==> T
(eq 'infix::+ 'cl-user::+)
==> T

但是,第一个不同:

(eq 'infix::& 'cl-user::&)
==> NIL

find-all-symbols是你的 friend :

(find-all-symbols "+")
==> (+)
(find-all-symbols "*")
==> (*)
(find-all-symbols "&")
==> (INFIX::& CL-USER::&)

附言

请注意,我使用非内部符号作为 :export 参数在 defpackage -这样它们就不会被 read 驻留在 CL-USER 中。

关于package - 为什么在我将代码打包到包中后,列表中只有两个元素不再被识别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39150177/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com