在Ruby中,一个方法可以使用块/ lambdas,并使您能够编写看起来像是语言一部分的构造。例如,times
类上的Fixnum
方法:
2.times do
# whatever code is between do and end, will be executed 2 times
end
或者例如open
类中的File
方法:
File.open(some_file) do |file|
# do something with the file; once the block finishes execution, the handle is automatically closed
end
open方法可以有类似的实现(原谅Ruby“伪代码”):
class File
def open(file,mode="r",&blk)
begin
handle = probably_sys_open(file)
if block_given?
blk.call(handle)
close(handle)
else
return handle
end
rescue SomeException => e
# whatever error handling goes on here
end
end
end
我怎样才能在elisp中编写这样的函数/方法,这样当我使用它们时,我只需要关心任务的“相关”部分,而不是一直遍历所有样板?
答案 0 :(得分:5)
我如何在elisp中编写这样的函数/方法,以便在我使用时 他们,我只需要关心任务的“相关”部分, 而不是一直经历所有的样板?
您可以使用宏。
例如,如果没有dotimes
,您可以轻松地自己编写类似内容:
(defmacro do-times (n &rest body)
(let ((i (gensym)))
`(do ((,i 0 (1+ ,i)))
((= ,i ,n))
,@body)))
现在,(do-times 3 (princ 'x))
会做你期望的事情(你可能需要先(require 'cl)
)。
这可以通过编写为您编写样板文件的代码来实现。我不会在这里给你一个完整的宏教程 - 快速谷歌搜索将为你提供足够的教程和其他信息来开始。
您可以对文件处理执行相同的操作。请查看with-temp-file
以获取emacs lisp示例。例如,在CL中,有with-open-file
,它与第二个Ruby片段具有几乎相同的功能。所以:
File.open(some_file) do |file|
# do something with the file; once the block finishes execution, the handle is automatically closed
end
变为:
(with-open-file (file "some_file")
# do something ...
)
除了你可以用宏做的语法抽象,你还可以编写更高阶的函数:
(defun times (n function)
(do-times n (funcall function)))
现在,此函数将采用计数和另一个函数,该函数将执行n
次。 (times 3 (lambda () (princ 'x)))
会做你期望的事。或多或少,Ruby块只是这类事物的语法糖。