gpt4 book ai didi

lisp - 如何在 LISP 中覆盖 (defun eval (expr)) 函数

转载 作者:太空宇宙 更新时间:2023-11-03 18:42:54 24 4
gpt4 key购买 nike

我是 LISP 编程的新手,现在是学期末,我们的老师要求我们做这个项目,我一直在努力做到这一点,但我被困住了,所以任何帮助都将不胜感激。该项目是用 Lisp 编写一个 eval (expr) 函数来覆盖已经存在的函数。这是详细信息:

项目描述:算术表达式中的项用空格分隔;

; Input:
; 1. The form of arithmetic expression given in prefix notation like LISP
; Assumptions:
; 1. binary operations for +, -, *, and /
; 2. integer division, no reals
; 3. an arithmetic expression occupies only one line
; 4. nested arithmetic expressions permitted
; 5. all given inputs are syntax correct
; 6. no need for error handling

我写了一个代码,可以对简单的算术表达式进行求值,而且它有效!!但我无法让它在嵌套算术运算上工作。我认为递归部分有问题我做错了什么但它到底是什么 idk :(

这是我的代码:

; Assign a character string to a global variable input-prompt
; treat input-prompt as a constant global variable
(setf input-prompt "Please input an arithmetic expression: ")

(setf output-prompt "The value is: ")

(defun prompt-for-input (msg)
(format t msg)
(format t "~%")) ; ~% new line

(defun prompt-for-output (msg)
(format t msg))

(defun output-msg (result)
(format t "~S" result) ; ~S takes the result into the print message
(format t "~%"))

(defun eval (expr)
(print "My EVAL Function is Working *_*")
(if (numberp expr) expr)
(cond
((eq (car expr) '+)
(if (and (numberp (cadr expr))
(numberp (caddr expr))) ;to check if we have simple expression
(+ (cadr expr) (caddr expr)) ;in case both are numbers we add normally
(if (not (numberp (cadr expr)))
;in case the second argument is not number
;we need to call eval again to check the expression
((eval (cadr exp)))
(if (not (numberp (caddr expr)))
;in case the third argument is not a number
;we need to call eval again to check the expression
((eval (caddr exp)))
(0)))))
((eq (car expr) '-)
(if (and (numberp (cadr expr))
(numberp (caddr expr))) ;to check if we have simple expression
(- (cadr expr) (caddr expr)) ;in case both are numbers we add normally
(if (not (numberp (cadr expr)))
;in case the second argument is not number
;we need to call eval again to check the expression
((eval (cadr exp)))
(if (not (numberp (caddr expr)))
;in case the third argument is not a number
;we need to call eval again to check the expression
((eval (caddr exp)))
(0)))))
((eq (car expr) '*)
(if (and (numberp (cadr expr))
(numberp (caddr expr))) ;to check if we have simple expression
(* (cadr expr) (caddr expr)) ;in case both are numbers we add normally
(if (not (numberp (cadr expr)))
;in case the second argument is not number
;we need to call eval again to check the expression
((eval (cadr exp)))
(if (not (numberp (caddr expr)))
;in case the third argument is not a number
;we need to call eval again to check the expression
((eval (caddr exp)))
(0)))))
((eq (car expr) '/)
(if (and (numberp (cadr expr))
(numberp (caddr expr))) ;to check if we have simple expression
(/ (cadr expr) (caddr expr)) ;in case both are numbers we add normally
(if (not (numberp (cadr expr)))
;in case the second argument is not number
;we need to call eval again to check the expression
((eval (cadr exp)))
(if (not (numberp (caddr expr)))
;in case the third argument is not a number
;we need to call eval again to check the expression
((eval (caddr exp)))
(0)))))))

; it should have eval(expr) function which returns the value of the
; arithmetic expression
; for instance,
; (+ 2 3) outputs 5
; (+ (* 3 2) (/ 4 2))) outputs 8
; (* (- 2 3) 5) outputs -5

; driver accepts the input arithmetic expression
; evaluate the arithmetic expression
; output the reulst of the evaluation of the arithmetic expression
; execution is in the loop; to exit the loop; type cntrl-c

(defun driver ()
(prompt-for-input input-prompt)
;to print "Please input an arithmetic expression
(let ((expression (read)))
(output-msg expression)
(let ((result (eval expression)))
(prompt-for-output output-prompt)
(output-msg result)))
(driver))

最佳答案

首先,基本的调用是......鼓声...... -

(apply (symbol-function (car expr)) (cdr expr))

暂时假设表达式中的所有参数都已经是数字。

这一行替换了代码中的所有四种情况,它们都是彼此的精确副本,直到要执行的操作为止。

现在,为了确保我们有数字,我们只需要对每个数字调用相同的 eval。如果它们是数字,它们将保持原样,如果不是,它们将被评估。

让我们调用我们的新函数 calc,代替“计算”:

(defun calc (expr)     ; our "eval"
(cond
((numberp expr) expr)
(T (call (car expr)
(mapcar #'calc (cdr expr))))))

(defun call (op args) ; our "apply"
(apply (symbol-function op)
args))

就是这样。如果考虑到这种作弊,您可以手动调用该操作,但您仍然不需要为此复制同一代码块四次。 :)

如果您确实自己编写了call 来手动调用操作,请注意(*) 的默认值为1,而不是0;并且 Common Lisp 中的 (-)(/) 没有默认值(在 CLisp 中测试过)。此外,(/2) 应返回 1/2

关于lisp - 如何在 LISP 中覆盖 (defun eval (expr)) 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16198053/

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