如何使用Emacs Lisp动态范围? [英] How to live with Emacs Lisp dynamic scoping?

查看:126
本文介绍了如何使用Emacs Lisp动态范围?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我以前学过Clojure,真的很喜欢这种语言。我也喜欢Emacs,并且用Emacs Lisp攻击了一些简单的东西。有一件事情,阻止我精神上对Elisp做更多的事情。这是动态范围的概念。我只是害怕它,因为它对我来说很陌生,闻起来像半全局变量。



所以使用变量声明,我不知道哪些事情是安全的,哪些是危险的。从我所理解的,设置setq的变量落在动态范围之下(是吗?)让变量如何?在某个地方我读过,让让你做一个简单的词汇作用域,但是在别的地方我读过,也让vars也是动态的范围。



我最大的担心是我的代码(使用setq或let)意外地从我打电话的平台或第三方代码中打破了一些变量,局部变量意外搞乱。我该如何避免这种情况?有没有一些简单的经验法则,我可以直接跟踪并确切地知道范围会发生什么,而不会被困在一些奇怪的,难以调试的方式中?

解决方案

没有那么糟糕。



主要问题可以在函数中显示自由变量。

 (defun foo(a)
(* ab))

在上述函数 a 是一个局部变量。 b 是一个自由变量。在具有动态绑定的系统中,如Emacs Lisp,将在运行时查找 b 。现在有三种情况:


  1. b 未定义 - >错误

  2. b 是当前动态范围中的一些函数调用绑定的局部变量 - >取该值

  3. b 是一个全局变量 - >取该值

问题可以是:




  • 绑定值(全局或本地)被函数调用所遮蔽,可能不需要

  • 一个未定义的变量没有被遮蔽 - >访问错误

  • 一个全局变量不被遮蔽 - >拾取全局值,这可能是不需要的



在具有编译器的Lisp中,编译上述函数可能会生成一个有一个空闲变量的警告。通常,Lisp编译器将会这样做。解释者不会提供警告,只会在运行时看到效果。



建议




  • 确保您不会意外使用自由变量

  • 确保全局变量具有特殊名称,以便它们源代码容易发现,通常 * foo-var *



Don不要写

 (defun foo(ab)
...
(setq c(* ab ));其中c是一个自由变量
...)

写: ($)

 (defun foo(ab)
...
(let((c(* ab)))
...)
...)

绑定所需的所有变量使用,你想确保他们没有绑定到别的地方。



基本上是这样。



由于Emacs Lisp支持GNU Emacs版本24的词法绑定。请参阅:词汇绑定,GNU Emacs Lisp参考手册


I've learned Clojure previously and really like the language. I also love Emacs and have hacked some simple stuff with Emacs Lisp. There is one thing which prevents me mentally from doing anything more substantial with Elisp though. It's the concept of dynamic scoping. I'm just scared of it since it's so alien to me and smells like semi-global variables.

So with variable declarations I don't know which things are safe to do and which are dangerous. From what I've understood, variables set with setq fall under dynamic scoping (is that right?) What about let variables? Somewhere I've read that let allows you to do plain lexical scoping, but somewhere else I read that let vars also are dynamically scoped.

I quess my biggest worry is that my code (using setq or let) accidentally breaks some variables from platform or third-party code that I call or that after such call my local variables are messed up accidentally. How can I avoid this?

Are there a few simple rules of thumb that I can just follow and know exactly what happens with the scope without being bitten in some weird, hard-to-debug way?

解决方案

It isn't that bad.

The main problems can appear with 'free variables' in functions.

(defun foo (a)
  (* a b))

In above function a is a local variable. b is a free variable. In a system with dynamic binding like Emacs Lisp, b will be looked up at runtime. There are now three cases:

  1. b is not defined -> error
  2. b is a local variable bound by some function call in the current dynamic scope -> take that value
  3. b is a global variable -> take that value

The problems can then be:

  • a bound value (global or local) is shadowed by a function call, possibly unwanted
  • an undefined variable is NOT shadowed -> error on access
  • a global variable is NOT shadowed -> picks up the global value, which might be unwanted

In a Lisp with a compiler, compiling the above function might generate a warning that there is a free variable. Typically Common Lisp compilers will do that. An interpreter won't provide that warning, one just will see the effect at runtime.

Advice:

  • make sure that you don't use free variables accidentally
  • make sure that global variables have a special name, so that they are easy to spot in source code, usually *foo-var*

Don't write

(defun foo (a b)
   ...
   (setq c (* a b))  ; where c is a free variable
   ...)

Write:

(defun foo (a b)
   ...
   (let ((c (* a b)))
     ...)
   ...)

Bind all variables you want to use and you want to make sure that they are not bound somewhere else.

That's basically it.

Since GNU Emacs version 24 lexical binding is supported in its Emacs Lisp. See: Lexical Binding, GNU Emacs Lisp Reference Manual.

这篇关于如何使用Emacs Lisp动态范围?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆