Существуют ли языки программирования без глобальных переменных? - PullRequest
9 голосов
/ 22 ноября 2010

Существуют ли языки, в которых область действия определена таким образом, что не распространяется на вложенные функции? Другими словами, есть ли язык, где код похож на следующий (Python-подобный синтаксис):

>>> x = 3
>>> def fact(n):
...     print x
...     return reduce(lambda u, v: u*v, xrange(1, n+1), 1)
...     

выдаст ошибку, потому что x не определен внутри функции fact?

В общем, существуют ли языки, в которых область действия любой функции не будет включать функции, определенные в ней?

Редактировать : Спасибо за содержательные комментарии. Причина, по которой я подумал об этом, заключается в том, что ситуация внутренней функции, имеющей доступ ко всей среде, обеспечиваемой ее содержащими функциями, кажется мне подозрительно близкой к ситуации, описанной Джо Армстронгом в его аргументе против ООП :

Потому что проблема с объектно-ориентированные языки получил всю эту неявную среду, которая они носят с собой. Вы хотел банан, но то, что вы получили, было горилла держит банан и целые джунгли.

Также важно, что я слышал, что язык Newspeak не имеет глобального пространства имен, хотя я понятия не имею, как он работает.

Я могу представить себе проблему, поднятую в комментарии Брайана ниже, о встроенных функциях (функции, импортированные из __builtins__ в Pythonspeak или System во многих других языках), которые искусственно вводятся интерпретатором / компилятором в каждую функцию. Ведь с ними почти всегда обращаются специально на языке в первую очередь. Другой вариант - использовать их как методы объекта, передаваемого в качестве параметра функции или импортированного как модуль изнутри.

Ответы [ 3 ]

8 голосов
/ 25 декабря 2010

Я постараюсь в общих чертах описать, как это работает в Newspeak.

Любой код, который вы пишете, должен быть в модуле .Модуль является своего рода классом, поскольку в классах Newspeak могут содержаться другие классы, модуль по сути является классом верхнего уровня - классом, который не содержится в другом классе.Что особенного в Newspeak, так это то, что вы не можете ссылаться на что-либо вне вашего модуля .

Итак, как вы печатаете на консоли в Newspeak?Печать принадлежит классу Console (он же Transcript от Smalltalk), который является частью модуля Platform.Чтобы иметь возможность печатать на консоль, ваш модуль должен принять параметр конструктора Platform, получить консоль с платформы, сохранить консоль в слоте, а затем использовать ее для печати.

По сути, это похоже на внедрение зависимостей на уровне языка.Языковая среда разработки и среда выполнения помогут вам упаковать и загрузить программу, но если вам нужны подробности - перейдите на блог Гилада Брачи , см., Например, этот пост или ознакомьтесь с Newspeak Modules paper .

PS Newspeak не является ни непрактичным, ни непригодным для использования, к сведению - он использовался в промышленной среде, и теперь вокруг него есть небольшое (но растущее) сообщество открытого кода.Конечно, Newspeak очень новый и развивающийся, но из личного опыта - писать программы довольно легко и весело.

0 голосов
/ 01 марта 2015

Полагаю, вы могли бы создать язык программирования, в котором глобальная область видимости заменяется, например, ассоциативным массивом, содержащим функции и объекты, которые затем передаются в качестве рабочей среды для каждой вызываемой функции.

Рассмотрим следующий пример. В обычной программе на 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)

В программе с таким подходом и без глобальных функций, функции в программе могут быть почти полностью изолированы от всего, кроме того, что они могут получить доступ через аргументы, которые они получают. Затем вы могли бы также создать альтернативные среды для функций и затем запускать их в «тюрьмах». Библиотеки и функции будут похожи на электронные компоненты в цепи, где вам нужно, но также могут соединять части с тем, что вы хотите. Язык программирования, разработанный для этого шаблона, может иметь некоторый синтаксический сахар для удобства автоматической передачи неявной среды «по умолчанию» вызовам функций, но вы всегда можете явно заставить их использовать любую альтернативную среду, какую захотите.

Например, на глобальном языке, если у вас есть библиотека, предназначенная для доступа к данным в файловой системе или сети операционной системы, вы можете предоставить альтернативную среду и отслеживать операции ввода-вывода или использовать библиотеку. ваша собственная виртуальная файловая система или соединение VPN вместо обычной файловой системы и сети.

0 голосов
/ 22 ноября 2010

Реально, такая вещь никогда не могла бы существовать. Подумайте - когда вы печатаете на консоль, откуда берется этот дескриптор консоли? Когда вы ссылаетесь на функцию, откуда эта функция? Конечно, он не существует физически в стеке функции, из которой вы вызвали его. Это верно - это глобальный. Реальность такова, что без глобальных переменных вы никогда не сможете сослаться на то, что не находится непосредственно в вашем стеке или куче - что означает отсутствие машинных инструкций, благодаря DEP. И для кучи, где бы вы взяли кучу? Вы не можете вызвать функцию ОС для выделения вам некоторой новой памяти - это глобально.

Теоретически, вы могли бы создать такой язык или программу, но реальность такова, что это было бы больше похоже на Brainfuck, чем на что-то действительно полезное.

...