我用的是SBCL,Emacs和Slime。因此,我可以:
CL-USER> (defvar example #'(lambda (x) (* x 20)))
EXAMPLE
CL-USER> (funcall example 10)
200好的。它如预期的那样工作。利用图书馆的德克萨多,我也可以这样:
CL-USER> (ql:quickload :dexador)
To load "dexador":
Load 1 ASDF system:
dexador
; Loading "dexador"
.......
(:DEXADOR)
CL-USER> (dex:get "http://www.paulgraham.com")
"big HTML ommited"
200
#<HASH-TABLE :TEST EQUAL :COUNT 11 {10029F1443}>
#<QURI.URI.HTTP:URI-HTTP http://www.paulgraham.com>
#<SB-SYS:FD-STREAM for "socket 10.0.0.193:44936, peer: 74.6.52.135:80" {1002681F73}>现在,我试图把要被传递的参数变成一个函数!更具体地说,dex:get函数。我尝试过不同的方法,但都没有成功:
CL-USER> (defvar example-failing #'(lambda (x) (x "http://www.paulgraham.com")))
; in: DEFVAR EXAMPLE-FAILING
; (LAMBDA (X) (X "http://www.paulgraham.com"))
;
; caught STYLE-WARNING:
; The variable X is defined but never used.
; in: DEFVAR EXAMPLE-FAILING
; (X "http://www.paulgraham.com")
;
; caught STYLE-WARNING:
; undefined function: COMMON-LISP-USER::X
;
; compilation unit finished
; Undefined function:
; X
; caught 2 STYLE-WARNING conditions
EXAMPLE-FAILING
CL-USER> (funcall example-failing dex:get)
; Evaluation aborted on #<UNBOUND-VARIABLE GET {1002C57103}>.
CL-USER> (funcall example-failing 'dex:get)
; Evaluation aborted on #<UNDEFINED-FUNCTION X {1002DEA263}>.
CL-USER> (funcall example-failing #'dex:get)
; Evaluation aborted on #<UNDEFINED-FUNCTION X {1002F906C3}>.
CL-USER> (funcall example-failing (function dex:get))
; Evaluation aborted on #<UNDEFINED-FUNCTION X {1003147F83}>.我设法做到了:
CL-USER> (defvar hacky-eval #'(lambda (x) (eval x)))
HACKY-EVAL
CL-USER> (funcall hacky-eval (dex:get "http://www.paulgraham.com"))
"big html omitted"但是,这感觉很糟糕。有的另一种方法来解决这个问题吗?
谢谢
发布于 2022-04-25 17:25:15
你的代码:
(defvar example-failing
#'(lambda (x)
(x "http://www.paulgraham.com")))这在公共Lisp中是没有意义的。x是一个变量。您不能像在(x arg)中那样将变量用作函数。在通用Lisp中,函数和变量有不同的名称空间。例如,LET引入了一个局部变量,而FLET引入了一个本地函数。
调用绑定到变量的函数的方法如下:
(funcall x arg)
(apply x (list arg))因此,正确的例子是:
(defvar example-failing
#'(lambda (x)
(apply x (list "http://www.paulgraham.com"))))或
(defvar example-failing
#'(lambda (x)
(funcall x "http://www.paulgraham.com")))您的解决方案不是解决方案
这就是你的例子:
CL-USER> (defvar hacky-eval #'(lambda (x) (eval x)))
HACKY-EVAL
CL-USER> (funcall hacky-eval (dex:get "http://www.paulgraham.com"))
"big html omitted"这不像你想的那样有效。
(funcall hacky-eval (dex:get "http://www.paulgraham.com"))就像
(funcall hacky-eval "big html omitted")然后
(eval "big html omitted")然后
"big html omitted"对eval的所有调用都是将字符串计算给自己。
您确实需要理解Lisp中的基本评估规则:
(defun foo (arg)
(eval arg))
(foo (+ 3 4))与以下内容完全相同:
(defun foo (arg)
arg)
(foo (+ 3 4))这和
(identity (+ 3 4))注意:如果您只将自评估数据传递给EVAL,那么它所做的就是返回数据。
函数调用(foo (+ 1 2))的工作方式如下:
function
#'foo 3)
返回值(S)
发布于 2022-04-25 14:52:05
我被你的问题弄糊涂了,虽然没有你看上去那么困惑。您似乎已经知道,要调用作为变量值的函数,您需要
funcall如果只有一个参数列表,则所有参数都是单独的things;apply;得到需要(function thing)或等效#'thing1的东西的函数值。
但是,在您的函数中,您忘记了这一点,而不注意来自SBCL的大量警告。
所以
(defvar *example* (lambda (f) (funcall f "http://www.paulgraham.com")))
...
(funcall *example* #'dex:get)请注意,所有这些(以及问题中的任何内容)都不依赖于词法范围:这在任何历史的Lisp中都是可行的。
1:您不需要#'只用于(lambda ...),因为lambda是一个扩展到(function (lambda ...))的宏。非常老的代码有时使用显式的#'(lambda ...)表单,因为这个宏并不总是存在于CL中。
发布于 2022-04-26 06:43:15
从使用适当的defun开始
(defun request (url)
(dex:get url))
CL-USER> (request "http://…")现在,您想使用dex:get以外的其他东西吗?Well…编写另一个函数,因为它们的参数处理、标头返回值…可能不一样。
(defun request-drakma (url)
(drakma:… url))也许在以后的代码中,您想要引用任何一个函数?
(defun do-request (url &optional (get-fn #'request))
(funcall get-fn url))(defvar example #'(lambda (x) (* x 20)))这里给匿名函数…取了一个名字只需使用defun^^
https://stackoverflow.com/questions/72001208
复制相似问题