[英]Common Lisp call function
I'm new in Common Lisp. 我是Common Lisp的新手。 And recently started to learn it.
并且最近开始学习它。 And I have a little problem how to call one function in another?
我有一个小问题,如何在另一个函数中调用一个函数? I have a function
mrg
and function my_eval
. 我有一个函数
mrg
和函数my_eval
。 And how call this function mrg
in my_eval
by typing this for example (print (my_eval '(mrg '(1 1 2 1 2 1 3) '(5 3 3 1 2 2))))
. 以及如何通过键入例如
(print (my_eval '(mrg '(1 1 2 1 2 1 3) '(5 3 3 1 2 2))))
在my_eval
调用此函数mrg
。 I tried but I had some errors like it's not a real number
or undefined function A
. 我尝试过,但是遇到一些错误,例如
it's not a real number
或undefined function A
Please help me. 请帮我。
This is my code: 这是我的代码:
(defun mrg (w v)
(merge 'list (sort w #'<) (sort v #'<) #'<))
(defun my_eval (A)
(cond
((atom A) A)
((equal 'car (car A))
(let ((A A)) (funcall (car A) (my_eval (cadr A)))))
((equal 'cdr (car A))
(let ((A A)) (funcall (car A) (my_eval (cadr A)))))
((equal 'atom (car A))
(let ((A A)) (funcall (car A) (my_eval (cadr A)))))
((equal 'cons (car A))
(let ((A A)) (funcall (car A) (my_eval (cadr A)) (my_eval (caddr A)))))
((equal 'list (car A))
(let ((A A)) (funcall (car A) (my_eval (cadr A)) (my_eval (caddr A)))))
((equal 'equal (car A))
(let ((A A)) (funcall (car A) (my_eval (cadr A)) (my_eval (caddr A)))))
((equal '* (car A))
(let ((A A)) (funcall (car A) (my_eval (cadr A)) (my_eval (caddr A)))))
((equal '/ (car A))
(let ((A A)) (funcall (car A) (my_eval (cadr A)) (my_eval (caddr A)))))
((equal '+ (car A))
(let ((A A)) (funcall (car A) (my_eval (cadr A)) (my_eval (caddr A)))))
((equal '- (car A))
(let ((A A)) (funcall (car A) (my_eval (cadr A)) (my_eval (caddr A)))))
((equal '= (car A))
(let ((A A)) (funcall (car A) (my_eval (cadr A)) (my_eval (caddr A)))))
((equal 'mrg ))
(T A)))
(print (my_eval '(mrg '(1 1 2 1 2 1 3) '(5 3 3 1 2 2))))
You're close but both function definitions have minor issues. 您接近了,但是两个函数定义都有一些小问题。 In the mrg function definition, you need to pass a form (ie parenthesize what you want to execute) after the function declaration:
在mrg函数定义中,您需要在函数声明后传递一个表单(即,括号中要执行的内容):
(defun mrg (w v)
(merge 'list (sort w #'<) (sort v #'<) #'<))
And your my_eval function is incomplete for the mrg condition: 而对于mrg条件,您的my_eval函数不完整:
(defun my_eval(A)
(cond
((atom A) A)
((equal 'car (car A)) (let ((A A)) (funcall (car A) (my_eval (cadr A)))))
((equal 'cdr (car A)) (let ((A A)) (funcall (car A) (my_eval (cadr A)))))
((equal 'atom (car A)) (let ((A A)) (funcall (car A) (my_eval (cadr A)))))
((equal 'cons (car A)) (let ((A A)) (funcall (car A) (my_eval (cadr A)) (my_eval (caddr A)))))
((equal 'list (car A)) (let ((A A)) (funcall (car A) (my_eval (cadr A)) (my_eval (caddr A)))))
((equal 'equal (car A)) (let ((A A)) (funcall (car A) (my_eval (cadr A)) (my_eval (caddr A)))))
((equal '* (car A)) (let ((A A)) (funcall (car A) (my_eval (cadr A)) (my_eval (caddr A)))))
((equal '/ (car A)) (let ((A A)) (funcall (car A) (my_eval (cadr A)) (my_eval (caddr A)))))
((equal '+ (car A)) (let ((A A)) (funcall (car A) (my_eval (cadr A)) (my_eval (caddr A)))))
((equal '- (car A)) (let ((A A)) (funcall (car A) (my_eval (cadr A)) (my_eval (caddr A)))))
((equal '= (car A)) (let ((A A)) (funcall (car A) (my_eval (cadr A)) (my_eval (caddr A)))))
((equal 'mrg (car A)) (let ((A A)) (funcall (car A) (my_eval (cadr A)) (merge 'list (sort A #'<) (sort A #'<) #'<))))
(T A)
)
)
(it looks like you're still missing the action (ie another form) for the mrg test but I'm not sure what you wanted to do in this case) (看起来您仍然缺少MRG测试的操作(即另一种形式),但是我不确定在这种情况下您想做什么)
If looking at the other calls, the condition clause for 'mrg must be 如果查看其他调用,则“ mrg”的条件子句必须为
((equal 'mrg (car A)) (let ((A A)) (funcall (car A) (my_eval (cadr A)) (my_eval (caddr A)))))
A
must be a list, since it failed the first cond
-clause (atom A)
. A
必须是一个列表,因为它未能通过第一个cond
子句(atom A)
。
Since mrg
requires in this implementation two arguments, like in this eval the built-in functions 由于
mrg
在此实现中需要两个参数,例如在此eval中,内置函数
`cons`
`list`
`equal`
`*`
`/`
`+`
`-`
`=`
also do, after copying the list A
to the local symbol A
(the (let ((AA)) ...)
part), funcall
is applied to the first element of the ist A
(which is mrg
) and then the two following elements in the list A
are given as arguments for the mrg
funcall
-call: 将列表
A
复制到本地符号A
( (let ((AA)) ...)
部分之后,也将funcall
应用于ist A
的第一个元素(即mrg
),然后将其后的两个列表A
中的元素作为mrg
funcall
参数给出:
(cadr A)
(which is synonym to (second A)
) and (cadr A)
(与(second A)
同义词)和 (caddr A)
(which is synonym to (third A)
). (caddr A)
(这是(third A)
同义词)。 Since each of the arguments themselves can be atoms or other function calls or special forms, you have to wrap a my_eval
call around them and evaluate each of the arguments. 由于每个参数本身可以是原子或其他函数调用或特殊形式,因此您必须在其周围包装一个
my_eval
调用并评估每个参数。
-- This is by the way what always happens if you call Lisp functions - each argument (which is an expression) is evaluated fully for itself before handling over the result to the main function call. -顺便说一句,如果您调用Lisp函数,通常会发生这种情况-在处理结果到主函数调用之前,将对每个参数(即一个表达式)进行完全评估。
(In contrast, in macro calls, the arguments are not evaluated by default like in the function calls. Instead, you have in the function body the full control over when each of the arguments will be evaluated or treated as a symbol). (相反,在宏调用中,默认情况下不像在函数调用中那样对参数进行求值。相反,在函数主体中,您可以完全控制何时将每个参数求值或视为符号)。
In your comment to @blihp's answer, you quoted A ( 'A
) twice in the let
-form and this prevents A to be taken as the list which it stands for actually. 在为@ blihp的回答您的意见,您引用了一个(
'A
中)两次let
-构型,这可以防止被视为它代表了真正的名单。
Another problem I see is that your my_eval
doesn't look for quote
and I am also not sure whether your my_eval
implementation which is a very rudimentary implementation, can handle '
correctly. 我看到的另一个问题是您的
my_eval
不查找quote
,我也不确定您的my_eval
实现是非常基本的实现,是否可以正确处理'
。 Thus in the test mrg
call, I recommend to use (list 1 3 4 2 4 ...)
instead of '(1 3 4 2 4 ...)
to prevent further complications. 因此,在test
mrg
调用中,我建议使用(list 1 3 4 2 4 ...)
而不是'(1 3 4 2 4 ...)
以防止进一步的并发症。
Invalid number of arguments: (EQUAL MRG)
无效的参数数量:(EQUAL MRG)
As other answers pointed out, there is an arity mistmatch: EQUAL
takes 2 parameters but was called with 1 argument in (EQUAL MRG)
. 正如其他答案所指出的那样,存在Arity模糊匹配:
EQUAL
具有2个参数,但在(EQUAL MRG)
被称为1个参数。
Notice also that you are duplicating code a lot. 还要注意,您正在重复很多代码。
In all cases, you compare the head of a list with a constant symbol, then you funcall it by giving it as arguments the result of calling my_eval
to the first, and sometimes the second, elements of the same list. 在所有情况下,您都将列表的头部与常量符号进行比较,然后通过将
my_eval
调用同一列表的第一个元素(有时是第二个元素)的结果作为参数来my_eval
地调用它。 Basically, your code is doing this: 基本上,您的代码正在执行此操作:
(apply (first list) (mapcar #'my-eval (rest list)))
The APPLY
function takes a function designator and call it with an arbitrary number of arguments. APPLY
函数采用一个函数指示符 ,并使用任意数量的参数进行调用。 Here, that list of arguments is the result of applying my_eval
to each remaining elements in the list. 在这里,该参数列表是将
my_eval
应用于列表中其余每个元素的结果。
The differences with your code are: 与您的代码的区别是:
(+ 1 4 9)
would evaluate to 5 under my_eval
). (+ 1 4 9)
在my_eval
下的my_eval
5)。 IMHO, my_eval
should rather fail loudly in that case, because that's probably not what anyone would expect. my_eval
应该大声失败,因为这可能不是任何人所期望的。 let
which rebinds A
to a local variable name A
is not useful here. A
重新绑定到本地变量名称A
的let
在这里没有用。 If you want to retain that approach but remove some code duplication, you may try this; 如果您想保留该方法但要删除一些代码重复,则可以尝试此方法。 the following function should be called you determined the form to evaluate is a cons-cell.
您应该确定要评估的表单为cons单元格,然后应调用以下函数。
(defun my-eval/apply (cons)
(check-type cons cons)
(destructuring-bind (head . tail) cons
(let ((size (length tail))
(arity (case head
((car cdr atom) 1)
((cons list equal * / + - = mrg) 2))))
(cond
((not arity) (error "Unknown function ~a" head))
((= size arity) (apply head (mapcar #'my_eval tail)))
(t (error
"Arity mismatch: ~a takes ~d parameter~:p but was ~
called with ~d argument~:p in ~s" head arity size cons))))))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.