emacs.d/init.el at 7ce37fbcf598daaeda11645e1ae6bac2fe22b5c7 · purcell/emacs.d · GitHub 22行
(let ((normal-gc-cons-threshold (* 20 1024 1024))
(init-gc-cons-threshold (* 128 1024 1024)))
(setq gc-cons-threshold init-gc-cons-threshold)
(add-hook 'emacs-startup-hook
(lambda () (setq gc-cons-threshold normal-gc-cons-threshold))))
我猜测是 normal-gc-cons-threshold 这个变量的作用域是在let内,lambda函数运行的时候,已经不在let的作用域了,所以报错了?请指教
;; -*- lexical-binding: t -*-
(add-hook 'emacs-startup-hook
(lambda () (setq gc-cons-threshold normal-gc-cons-threshold)))
做的只有把(lambda () (setq gc-cons-threshold normal-gc-cons-threshold))
这个函数加入emacs-startup-hook
,然后你的let binding就结束了。当Emacs在之后运行emacs-start-up-hook
的时候(backtrack里的run-hooks xxx
),自然找不到这个变量。
用;; -*- lexical-binding: t -*-
声明使用lexical-binding的之后,lambda
返回的函数自动变成closure,closure会记录lexical环境,包括你的normal-gc-cons-threshold
。
3 个赞
如前面的回复所说,你要像 purcell 那样开启 Lexical Binding,之后这段代码才会有效。
(setq lexical-binding t)
;; => t
(let ((normal-gc-cons-threshold (* 20 1024 1024))
(init-gc-cons-threshold (* 128 1024 1024)))
(setq gc-cons-threshold init-gc-cons-threshold)
(add-hook 'emacs-startup-hook
(lambda () (setq gc-cons-threshold normal-gc-cons-threshold))))
;; => ((closure ((init-gc-cons-threshold . 134217728) (normal-gc-cons-threshold . 20971520) t) nil (setq gc-cons-threshold normal-gc-cons-threshold)))
开启 Lexical Binding 之后,(lambda ...)
的返回值变成了 (info “(elisp) Closures”),不再是普通的 (lambda ...)
列表了。
1 个赞
说起closure我正好有个问题想问你……
怎么把这种带closure的代码改为不需要lexical-binding的形式?
为什么?现在默认都应该用 Lexical Binding(推荐)。
回到你的问题,自然就需要放弃 Lexical Binding 提供的特性了,比如这样一个函数
;; -*- lexical-binding: t; -*-
(let ((x 123))
(lambda ()
x))
就得改成
;; -*- lexical-binding: nil; -*-
(lambda ()
(let ((x 123))
x))
或者
;; -*- lexical-binding: nil; -*-
(defvar x 123)
(lambda ()
x)
2 个赞
感谢
洁癖……至少在这个用注释开启的方法被改变之前我是尽量避免使用的
(setq-default lexical-binding t)
不行吗?我这里没问题
Python 也有类似的(Magic Comment),而且支持 Emacs 的写法:
#!/usr/bin/python
# -*- coding: utf-8; -*-
print("世界,你好!")
这个写法的源头似乎真的是emacs的file-local variable
LdBeth
12
1970 年 ITS 上的 TECO Emacs 就支持 -*- -*-
了。之后几乎所有 Emacs 版本都支持。
2 个赞