有没有办法在Common-Lisp中不传递参数,而不是传递“ NIL”?

时间:2019-01-15 14:30:04

标签: lisp common-lisp

我正在根据用户输入来调用函数,但是有些具有两个参数,而其他参数只有一个。不是在每个函数上都使用&optional参数(并且从不使用),而是有一种方法可以简单地在其值为“ NIL”时不传递参数?

这是一款用于交互式小说游戏的游戏,其中用户键入一些命令,然后将这些命令转换为函数调用。

(defun inputs (state)
    (format *query-io* "> ")
    (force-output *query-io*)
    (let* ((entry (cl-ppcre:split "\\s+" (string-downcase (read-line *query-io*))))
      (function (car entry))
      (args (cdr entry)))
      (if (valid-call function)
      (funcall (symbol-function (read-from-string function))
           state
           args)
      (progn
        (format *query-io* "Sorry, I don't know the command '~a'~%~%" function)
        (inputs state)))))

如果用户输入是“装备剑”,我需要通过传递'(“ Sword”)作为参数来调用函数“ equip”,但是如果用户输入是“ status”,则需要调用函数“状态”而不传递“ args”,而不是将其传递为“ NIL”

2 个答案:

答案 0 :(得分:4)

我认为您想使用apply 而不是funcallfind-symbol代替 read-from-string(这实际上对security reasons很重要!) 和destructuring-bind 而不是let*

(defun inputs (state)
  (format *query-io* "> ")
  (force-output *query-io*)
  (destructuring-bind (command &rest args)
      (cl-ppcre:split "\\s+" (string-downcase (read-line *query-io*)))
    (if (valid-call command)
        (apply (find-symbol command) state args)
        (progn
          (format *query-io* "Sorry, I don't know the command '~a'~%~%" command)
          (inputs state)))))

使用apply可使您的命令接受任意数量的参数,而不是一个。

实际上,您的valid-call应该返回要调用的函数:

(let ((f (valid-call function)))
  (if f
      (apply f state args)
      ...)

答案 1 :(得分:1)

您还可以使用简单的LOOP代替递归调用:

(defun inputs (state)
  (loop
   (format *query-io* "> ")
   (force-output *query-io*)
   (let* ((entry (cl-ppcre:split "\\s+" (string-downcase (read-line *query-io*))))
          (function (car entry))
          (args     (cdr entry)))
     (when (valid-call function)
       (apply (symbol-function (find-symbol function))
              state
              args)
       (return))
     (format *query-io* "Sorry, I don't know the command '~a'~%~%" function))))