我试图理解Lisp-1和Lisp-2之间的区别以及它与Clojure的关系,但我仍然不理解.任何人都可以开导我吗?
Scheme为所有变量使用单个名称空间,无论它们是绑定到函数还是其他类型的值.Common Lisp将两者分开,这样标识符"hello"可以引用一个上下文中的函数,而另一个中引用一个字符串.
(注1:此问题需要上述示例;请随意编辑并添加一个,或通过电子邮件发送原作者,我会这样做.)
但是,在某些上下文中,例如将函数作为参数传递给其他函数,程序员必须通过使用明确区分他指定函数变量而不是非函数变量#',如:
(sort (list '(9 A) '(3 B) '(4 C)) #'< :key #'first)
我一直认为这有点像疣,但我最近遇到的一个论点是,这实际上是一个特征:
......重要的区别实际上在于形式的语法,而不在于对象的类型.在不了解所涉及的运行时值的情况下,很明显函数形式的第一个元素必须是函数.CL采用这一事实并使其成为语言的一部分,以及宏观和特殊形式,这些形式也可以(并且必须)静态地确定.所以我的问题是:当函数名称的主要用途出现在很少想要出现变量名的地方时,为什么你希望函数的名称和变量的名称在同一名称空间中?
考虑类名的情况:为什么名为FOO的类会阻止使用名为FOO的变量?我唯一一次通过名称FOO引用该类是在期望类名的上下文中.如果在极少数情况下我需要获取绑定到类名FOO的类对象,则有FIND-CLASS.
这个论点确实从经验中对我有所帮助; Haskell中有一个类似的字段名称,它也是用于访问字段的函数.这有点尴尬:
data Point = Point { x, y :: Double {- lots of other fields as well --} }
isOrigin p = (x p == 0) && (y p == 0)
Run Code Online (Sandbox Code Playgroud)
这是通过一些额外的语法解决的,NamedFieldPuns扩展特别好:
isOrigin2 Point{x,y} = (x == 0) && (y == 0)
Run Code Online (Sandbox Code Playgroud)
那么,对于问题,超越一致性,Common Lisp vs. Scheme以及一般来说,所有值的单个命名空间与函数和非函数值的单独命名空间有哪些优点和缺点?
我正在阅读Peter Norvig的人工智能编程范例,我遇到了一个我无法自己解决的问题(这是我对Lisp的介绍).真的,问题是相当小的问题,但显然不是我的小脑能解决的问题.
为什么当函数的值是lambda时,将该函数用作列表的第一个元素是错误的.例如:
Lisp的:
(defun some-func ()
#'(lambda (x) x))
;; At REPL
;; Does not work
> ((some-func) 1)
;; Does work
> ((lambda (x) x) 1)
;; Also works
> (funcall (some-func) 1)
Run Code Online (Sandbox Code Playgroud)
我希望这是有道理的!
任何lisps支持嵌套的s表达式吗?例如
((f 2) 3 4)
Run Code Online (Sandbox Code Playgroud)
对于这(f 2)大概计算一个函数/宏应用上3 4.
是否可以让lisp支持这样的事情?或者是否有技术限制禁止这种做法/使其不切实际?
我知道Common Lisp对函数和变量有不同的绑定环境,但我相信它还有另一个绑定环境用于标签体标签.是否有比这更具约束力的环境?如果是这样,那么将Common Lisp归类为Lisp-2是否公平?
这些问题并不意味着迂腐或自行车脱落,我只想更好地了解Common Lisp,并希望能够深入了解哪里可以深入挖掘其规格.
在Clojure中,我可以定义一系列函数,然后将它们称为任何其他值,如下所示:
(doseq [op [+ - * /]]
(println (op 1 2 3 4)))
Run Code Online (Sandbox Code Playgroud)
产生以下输出:
10
-8
24
1/24
nil
Run Code Online (Sandbox Code Playgroud)
尝试在Common Lisp中执行相同操作只会导致错误:
(dolist (op '(+ - * /))
(print (op 1 2 3 4))
; in: DOLIST (OP '(+ - * /))
; (LET ((OP (TRULY-THE (MEMBER / * - +) (CAR #:N-LIST671))))
; (SETQ #:N-LIST671 (CDR #:N-LIST671))
; (TAGBODY (PRINT (OP 1 2 3 4))))
;
; caught STYLE-WARNING:
; The variable OP is defined but never used.
; in: …Run Code Online (Sandbox Code Playgroud) 为什么这不起作用?
( ((lambda () (lambda (x) (funcall #'1+ x)))) 2)
; yields Compile-time error: illegal function call
Run Code Online (Sandbox Code Playgroud)
我遇到了这样的情况,后来发现它funcall修复了它,即
(funcall ((lambda () (lambda (x) (funcall #'1+ x)))) 2) ; => 3
Run Code Online (Sandbox Code Playgroud)
我很困惑,因为它似乎第一个应该工作,因为我实际上有一个我正在调用的函数,而不仅仅是一个可能属于任一命名空间的符号(即(type-of ((lambda () #'1+))) ; => FUNCTION).我认为这将是那种喜欢你怎么不需要以funcall拉姆达例如,如((lambda (x) x) :HI) ; => :HI.我错过了什么?
我想print在变量中存储一个函数,这样我就可以输入一些简短的函数p,例如:
In Scheme:
(define print display)
(print "Hello world\n")
;; alternate way
(define print 'display)
((eval print) "Hello world\n")
Run Code Online (Sandbox Code Playgroud)
同样的方法似乎不起作用Common Lisp:
(defvar p 'print)
;;(print (type-of p))
(p "Hello world") ;; Attempt 1
((eval p) "Hello world") ;; >> Attempt 2
((eval (environment) p) "Hello world") ;; Attempt 3
Run Code Online (Sandbox Code Playgroud)
我Attempt 1上面得到这个错误:
*** - EVAL: undefined function P
Run Code Online (Sandbox Code Playgroud)
而这与Attempt 2和3在Clisp:
*** - EVAL: (EVAL (ENVIRONMENT) P) …Run Code Online (Sandbox Code Playgroud) 在Ubuntu上,如果我运行MIT-Scheme,它将显示一个函数作为一个过程:
1 ]=> (define (sq x) (* x x))
;Value: sq
1 ]=> (sq 3)
;Value: 9
1 ]=> sq
;Value 11: #[compound-procedure 11 sq]
Run Code Online (Sandbox Code Playgroud)
和伯克利的STk将显示sq为一个闭包:
STk> (define (sq x) (* x x))
sq
STk> (sq 3)
9
STk> sq
#[closure arglist=(x) b73fab48]
Run Code Online (Sandbox Code Playgroud)
为什么Lisp(Common Lisp clisp),当我做同样的事情时,它会给我一个错误,我怎么能把一个函数显示为一个值(第一类值/对象)?
[1]> (defun sq(x) (* x x))
SQ
[2]> (sq 3)
9
[3]> sq
*** - SYSTEM::READ-EVAL-PRINT: variable SQ has no value
The following restarts are available:
USE-VALUE :R1 Input a value to …Run Code Online (Sandbox Code Playgroud) 此函数编译警告,fn已定义且从未在第一行中使用,并且fn是第二行中未定义的函数:
(defun test-function (fn)
(funcall #'fn))
Run Code Online (Sandbox Code Playgroud)
为什么?一般性解释或其链接将是伟大的.
PD:完整日志:
test.lisp:9:1:
style-warning:
The variable FN is defined but never used.
--> PROGN SB-IMPL::%DEFUN SB-IMPL::%DEFUN SB-INT:NAMED-LAMBDA
==>
#'(SB-INT:NAMED-LAMBDA TEST-FUNCTION
(FN)
(BLOCK TEST-FUNCTION (FUNCALL #'FN)))
test.lisp:10:3:
style-warning:
undefined function: FN
==>
(SB-C::%FUNCALL #'FN)
Run Code Online (Sandbox Code Playgroud) lisp-2 ×10
common-lisp ×8
lisp ×6
clojure ×2
scheme ×2
eval ×1
funcall ×1
head ×1
lambda ×1
namespaces ×1
nested ×1
s-expression ×1
variables ×1