简体   繁体   English

通用Lisp调用功能

[英]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 numberundefined 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参数给出:

  • namely (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: 与您的代码的区别是:

  • You check each function in head position, which is good for safety and can be replicated with a list of authorized symbols. 您可以在头部位置检查每个功能,这对安全性有好处,并且可以与授权符号列表一起复制。
  • You discard remaining arguments, if they exist (eg (+ 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应该大声失败,因为这可能不是任何人所期望的。
  • Note also that the let which rebinds A to a local variable name A is not useful here. 还要注意,将A重新绑定到本地变量名称Alet在这里没有用。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM