问题描述
刚开始学习和编写lisp, 我正在尝试创建一个程序,该程序将持续接受一个数字,并且仅当且仅当最后一个输入数字是前一个数字的两倍时才停止。
这是我的代码
----------
(let((a 0)
(b 0)
(count 0))
(loop
(= a b))
(princ"Enter Number: ")
(defvar a(read))
(format t "~% a = ~d" a)
(setq count (1+ count))
(while
(!= b(* a 2) || <= count 1)
(princ "Program Terminated normally")
)
谢谢
解决方法
一点反馈
(let ((a 0)
(b 0)
(count 0))
(loop
(= a b)) ; here the LOOP is already over.
; You have a closing parenthesis
; -> you need better formatting
(princ"Enter Number: ")
(defvar a(read))
(format t "~% a = ~d" a)
(setq count (1+ count))
(while
(!= b(* a 2) || <= count 1)
(princ "Program Terminated Normally")
)
一些改进的格式:
(let ((a 0)
(b 0)
(count 0))
(loop
(= a b)) ; LOOP ends here,that's not a good idea
(princ "Enter Number: ")
(defvar a(read)) ; DEFVAR is the wrong construct,; you want to SETQ an already defined variable
(format t "~% a = ~d" a)
(setq count (1+ count))
(while ; WHILE does not exist as an operator
(!= b(* a 2) || <= count 1) ; This expression is not valid Lisp
(princ "Program Terminated Normally")
)
在真正编写这样的循环之前,您可能需要学习更多的 Lisp 运算符。您可能还想以交互方式使用 Lisp 并尝试一些东西,而不是尝试将代码写入编辑器并且从不从 Lisp 获得反馈......
,这里的答案绝对不是您在现实生活中的做法,但如果您了解它的作用,您就会了解 Lisps 的两大重要事项之一。
(如果您理解为什么等效程序在 Scheme 中不能可靠地工作,那么您也会理解编写安全程序的重要事项之一!幸运的是,这是 Common Lisp,而不是 Scheme,所以它是好的。)
首先让我们编写一个小辅助函数来读取整数。这只是一些繁琐的细节:这并不重要。
(defun read-integer (&key (prompt "Integer: ")
(stream *query-io*))
;; Read an integer. This is just fiddly details
(format stream "~&~A" prompt)
(values (parse-integer (read-line stream))))
好的,现在这里有一个有点奇怪的函数,叫做 mu
(代表“mutant U”):
(defun mu (f &rest args)
(apply f f args))
现在这是我们的程序:
(defun read-integers-until-double-last ()
(mu (lambda (c getter current next factor)
(if (= next (* current factor))
(values current next)
(mu c getter next (funcall getter) factor)))
#'read-integer
(read-integer)
(read-integer)
2))
它正在起作用:
> (read-integers-until-double-last)
Integer: 0
Integer: 4
Integer: 3
Integer: -2
Integer: -4
-2
-4
为了更加神秘,您基本上可以在此处扩展对 mu
的调用,这会使其更清晰或更不清晰:我不太确定是哪个:
(defun read-integers-until-double-last ()
((lambda (c)
(funcall c c
#'read-integer
(read-integer)
(read-integer)
2))
(lambda (c getter current next factor)
(if (= next (* current factor))
(values current next)
(funcall c c getter next (funcall getter) factor)))))
再说一次,这不是你在现实生活中的做法,但如果你了解它的作用以及它是如何做的,你就会理解关于 Lisps 及其理论基础的一件非常重要的事情。这不是他们的全部(甚至不是大部分)有趣的事情,但我认为这是值得理解的事情。