在Lisp中(我仍在使用SBCL学习Lisp),局部变量用let
声明,范围仅在该表达式内。这是为什么?与其他命令式语言(如C / C ++ / Java ...)不同,我们可以在其功能范围内的任何位置自由使用局部变量。
答案 0 :(得分:6)
再一次了解什么是什么。它基本上是一个匿名函数的应用程序“向后拼写”。
我将使用JavaScript作为插图,因为它更像是C语言,它很好地说明了这个概念。
(function(variableA, variableB){
console.log("variableA = " + variableA);
console.log("variableA * variableB = " + variableA * variableB);})(6, 7);
现在,让我们命名部分:从function
到;}
是函数定义。 (definition)(arguments)
是应用程序。让表达式基本上做同样的事情,即它调用带有参数的匿名函数,你在函数内部使用它作为变量。所以,如果你考虑前面的例子,用let形式重写它会产生类似的东西:
(let(variableA = 6, variableB = 7){
console.log("variableA = " + variableA);
console.log("variableA * variableB = " + variableA * variableB);});
(JavaScript不支持let,但是,上面不是一个有效的代码示例,但它应该是一个例子)
您还应该注意, 并非那么简单。因为在更复杂的情况下,您可能希望在构造另一个时引用其中一个参数 - 然后您将使用(let* ...)
,或者您希望使用函数作为此表达式的参数,然后您将使用{{1 }或(flet ...)
。但总体思路是一样的。
答案 1 :(得分:4)
Lisp有一个用于引入局部变量的构造。它建立了一个范围。您可以在允许表单的任何地方使用它。这两个主要构造是LET和LET *。 Ait允许我们独立于函数定义局部变量。当我们需要局部变量时,我们不需要引入函数,并且我们使用它来使局部变量具有最小范围。
另请注意,DEFUN允许您声明局部变量:它允许参数列表中的& AUX引入它们。
答案 2 :(得分:3)
let
与你所指的其他风格之间的区别仅仅是语法糖。在一种可以在任何地方引入新变量的语言中,仍然存在嵌套的作用域,只有它们在表面语法中被展平。例如
{
x = 3;
x++;
y = 4;
print "hi";
z = 42;
}
这里只有一个范围,但范围不同。 x
的范围以x = 3
开头。然后y
的范围以y = 4
开头。如果您在该范围之前引用y
,则表示您有错误。
这种事情被遗漏在Lisp之外,因为它为处理代码的代码的开发增加了很多努力。这种语言的编译器必须分析该代码并恢复显示嵌套let
结构的抽象语法树结构,以便编译器的剩余通道不必重新分析代码重新发现这些信息。
在Lisp中,我们直接在那个抽象语法树结构中编写,就是这样。这使语言统一。一切都是形式,如果它是一个复合形式,它在最左边的位置有一个操作符,它以无上下文的方式确定该形式其余部分的含义。
例如,请参阅最近的一个问题:find free variables in lambda expression。如果通过绑定特殊形式(如let
)或宏扩展为这些特殊形式的小型曲目,可以更轻松地查找lambda表达式中的自由变量。
另请注意,功能样式虽然不是由Lisp强制执行,但比那些类型的语言更为普遍(请注意我在虚构" {}语言中的变量定义中有一些命令性语句&# 34;。)如果您编写的代码中没有命令性陈述,那么您就不会遇到这种情况。
在功能代码中,可以以let*
的形式进行连续绑定:
(let* ((x 1) x = 1;
(y (1+ x)) y = x + 1;
(z (/ x y)) z = x / y;
(sqrt z)) return sqrt(z);
let*
中的后续初始化可以引用先前的绑定。