是否存在以不扩展到封闭函数的方式定义范围的语言?换句话说,有一种语言,其中的代码如下(类似Python的语法):
>>> x = 3
>>> def fact(n):
... print x
... return reduce(lambda u, v: u*v, xrange(1, n+1), 1)
...
会出错,因为x未在函数fact
中定义?
一般情况下,任何函数的范围是否包含在其中定义的函数?
修改:感谢您提供丰富的评论。我之所以想到这一点,是因为内部函数能够访问其包含函数所提供的所有环境的情况听起来非常接近我对Joe Armstrong在他的argument against OOP中所描述的情况:
因为问题所在 面向对象的语言是他们的 得到了所有这种隐含的环境 他们随身携带。您 想要一个香蕉,但你得到的是一个 大猩猩拿着香蕉和 整个丛林。
同样重要的是,我听说语言Newspeak没有全局命名空间,但我不知道它是如何工作的。
我可以想象下面Brian的评论中提到的内置函数(从Pythonspeak中的__builtins__
导入的函数或许多其他语言中的System中导入的函数)在每个函数中由解释器/编译器人为引入。毕竟他们几乎总是特别用语言对待。另一种选择是将它们作为对象的方法作为参数传递给函数或从内部作为模块导入。
答案 0 :(得分:8)
我将尝试大致概述它在Newspeak中的工作原理。
您编写的任何代码都必须位于模块中。 Module是一种类,因为在Newspeak类中可以包含其他类,Module本质上是一个顶级类 - 一个不包含在另一个类中。 Newspeak的特别之处在于您不能参考模块之外的任何内容。
那么如何在Newspeak中打印到控制台?打印属于Console类(a.k.a. Smalltalk的Transcript),它是Platform模块的一部分。为了能够打印到控制台,您的模块将采用Platform构造函数参数,从平台获取控制台,将控制台存储在插槽中,然后使用它进行打印。
基本上它就像在语言级别强制执行依赖注入一样。语言IDE和运行时可帮助您打包和引导程序,但如果您要查找更多详细信息,请转到Gilad Bracha's blog,例如,请参阅this post,或查看Newspeak Modules paper。
P.S。新闻既不是不切实际也不是无法使用,因为它在工业环境中被使用,现在它周围有一个小的(但正在增长的)开源社区。 Newspeak是一个非常新的和不断发展的,当然,但从个人经验来看 - 编写程序非常简单有趣。
答案 1 :(得分:0)
我相信你可以创建一种编程语言,其中全局范围被替换为,例如,包含函数和对象的关联数组,然后将其作为工作环境传递给每个被调用的函数。
考虑以下示例。在常规Python程序中,你会写这样的东西:
import foo
def square(x):
return x*x
print(square(int(raw_input("give a number: "))))
在没有全局变量的程序中,你宁愿写下这样的东西:
def main(environment):
environment['import']('foo')
environment['square'] = lambda x: x*x
environment['print'](environment['square'](int(environment['raw_input']("give a number:"))))
并且此代码将在以下上下文中执行:
def import_foo(modulename):
# dummy example
if modulename == 'foo':
import foo
environment = {
'import': import_foo,
'print': print,
'raw_input': raw_input
}
main(environment)
在使用这种方法且没有全局变量的程序中,程序中的函数几乎可以完全与所有东西隔离,除了它们可以通过它们获得的参数访问它们。然后,您还可以为函数创建替代环境,然后在" jails"中运行它们。库和功能就像电路中的电子元件,您需要的地方,但也可以将各个部分连接到您想要的任何部分。设计这种模式的编程语言可能有一些语法糖,以方便自动传递一个隐含的"默认"环境到函数调用,但你总是可以明确强制它们使用你想要的任何替代环境。
例如,在无全局语言中,如果您有一个用于访问操作系统文件系统或网络中数据的库,则可以提供备用环境并监视I / O或使库使用您自己的虚拟文件系统或VPN连接,而不是常规文件系统和网络。
答案 2 :(得分:-5)
实际上,这样的事情永远不会存在。考虑一下 - 当您打印到控制台时,控制台句柄来自何处?当你引用一个函数时,那个函数来自哪里?它确实不存在于您调用它的函数的堆栈上。这是对的 - 这是一个全球性的。实际情况是,没有全局变量,你永远不会引用任何不直接在你的堆栈或堆中的东西 - 这意味着没有机器指令,这要归功于DEP。对于堆,你会从哪里获得堆?你不能调用OS函数来为你分配一些实际的新内存 - 这是一个全局内存。
理论上,你可以创建这样的语言或程序,但实际情况是它更像是Brainfuck而不是实际可用的任何东西。