分享刚刚发现的一个elisp入门文档

如题 分享一个elisp的入门文档,希望能帮到刚刚入门学习elisp的同学。

2 个赞

论坛搜索这个链接,有六个搜索结果(包括你的),应该有不少人已经知道了。

大概是 2007 年写的,这十多年里 Emacs 加了

  • Lexical Binding
  • Generalized Variables
  • Pattern Matching

这些很常用,也很有用的新特性,值得介绍。此外, 正则表达式部分,rx 也值得一提。

3 个赞

谢谢! 我去找一下呢

lexical binding:

GV其实没有那么常用,我只看了onlisp上的相关内容

Pattern Matching我看的是pcase的manual

传说中的rx,看这个,还有rx自己的docstring就够了

「常用」与否没法定量判断,所以…… 此外,Generalized Variables 的使用不仅包括 setf,像 pushcl-incf 等也有机会用到。

印象中官方的介绍太简陋了,当时我看了还是有很多不清楚,后来我装了 Emacs 27,看了新版的介绍感觉好多了。

好吧,原来cl-incfpush也能用GV… 我完全没有用过就是了

他们用的setf,setf用gv实现的

问个入门问题

(setq foo (lambda (name)
             (message "Hello, %s!" name)))

(foo "Tom") ; => 不正确  在scheme这种写法是可行的。
(funcall foo "Tom") ; => 正确

lisp把变量和函数空间进行了区分。这体现了scheme与lisp之间的区别吗?

若是区分的,下面这种写法又如何理解呢?

((lambda (name)
             (message "Hello, %s!" name)) "Tom")

lambda表达式的返回值可以直接调用,而把这个返回值赋值给一个变量就不可以直接调用这个变量。那么lambda的返回值,是一个函数空间的对象,却可以付给一个变量空间的对象?

1 个赞

因为这是唯一的特例。编译器/解释器对 lambda 会特殊处理。

谢谢!

也就是说, 在lisp中,函数空间和变量空间,除了lambda这个特例外,是严格区分的呗。

我觉得emacs自带的emacs lisp intro也很不错, 从简单的源码开始一步步了解elisp.

谢谢你的推荐 我去看下呢

Emacs不建议用这种形式直接调用lambda。所以其实统一用funcall最好

(byte-compile '((lambda (x) (1+ x)) 4))
;; Warning: Use of deprecated ((lambda (x) ...) ...) form

好的,scheme和lisp我接触的都不是很深,针对elisp目前有些疑问点。

  1. scheme有一个RSR5, RSR6的标准,lisp有common lisp,那elisp呢?它虽然是独立发展,应该也有个规范吧。

  2. 我是从学习perl时知道名字空间隔离的,如变量名和函数名不共享在一个名字空间下,从你推荐的博文里看到这是LISP-1和LISP-2的区别。正好也解答了,我以前在本帖上提的问题。LISP-2的这种设计方式,除了能解决变量名和函数名冲突的问题之外,还有什么优势吗? 我自己倒是挺喜欢scheme和js的那种方式。变量有可执行属性的话,可以直接调用,而不是借助与funcal/apply

没有,硬要说就是自带的 Info 文档,同理 Python, Ruby, Lua, 都只有事实标准。

(defun hello () (print "hello, master"))
(funcall (read))
> 'hello
hello, master

In Scheme it requires using eval to achieve it, though funcall can be ten to hundred times faster than eval

1 个赞

原来如此,对于函数的调用,funcall在速度上有优势。我再问个问题,从管道或文件得到一个S表达式,想让它执行,不管是lisp还是scheme,都是用eval吧?在这方面,lisp没有自己独有的方法吧?

現在多数 Lisp 都是先 compile 再执行。

好的,谢谢!

另外歪个楼,国内现在是不是都在忙着准备过年呢?感觉这两天,发的帖子少了一些。

我还蛮喜欢李杀网站在那个elisp简明教程的,懒人入门推荐

http://ergoemacs.org/emacs/elisp.html

3 个赞
(setq foo '(("a" . 97) ("b" . 98)))     ; => (("a" . 97) ("b" . 98))

;; update value by setcdr
(if (setq bar (assoc "a" foo))
    (setcdr bar "this is a")
  (setq foo (cons '("a" . "this is a") foo))) ; => "this is a"
foo                         ; => (("a" . "this is a") ("b" . 98))

能否帮忙解释下这段代码,为什么(cons '(“a” . “this is a”) foo) 的结果只有一个(“a” . “this is a”)存入foo中? 这段代码在第五章的“把列表当关联表”这一节中。