LINUX.ORG.RU
ФорумTalks

сравнение ЯП с естественными языками

 


1

1

время от времени фофан экспериментирую с написанием простеньких интерпретаторов, и пришел к таким вот выводам.

Термин «язык» в применении к современным ЯП вообще не вполне подходит, в том смысле, что они не являются языками, разве что только в математическом смысле, с натяжкой.

Когда речь идет о естественных языках, предполагается, что интерпертатором этого языка является человек. Когда человек интерпретирует выражения языка, он формирует контекст на ходу. Например, рассмотрим два выражения:

1) С первыми криками петухов Василий проснулся.

2) В этом году природа проснулась очень рано, в феврале уже капали сосульки.

Очевидно, что «проснуться» тут означает несколько разные вещи. Наш интерпретатор исходит из контекста.

если мы берем выражение, например foo.bar.baz, то наш интерпретатор, как правило, абсолютно не видит текущего окружения. В лучшем случае, при наличии динамического связывания, baz может прочитать и зарезольвить лишь предыдущее слово, выполниться в его контексте, про foo на этапе выполнения baz ничего не известно, и никогда не будет, он исчез бесследно, и доступа к нему нет. Даже в наиболее динамичных языках, подобные возможности сильно ограничены, хотя кое какие попытки есть, например code-walking.

Думал, как можно было бы в теории решить эту проблему.

Пока думаю, ввести некий класс Interpreter, и каждое выражение им оборачивать. Нужно запоминать текущее выражение, и пытаться выполнить последующие слова в контексте предыдущих, которые уже схлопнулись Тут еще надо заметить, что разные объекты должны обрабатывать те же самые выражения по-разному.

Перемещено tailgunner из development



Последнее исправление: portquest2016 (всего исправлений: 3)

Ты круг-то нарисовал уже?

anonymous
()

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

А про (извините) банальную перегрузку методов? (Надеюсь, вы понимаете, что я намеренно утрирую и гипертрофирую, для контраста и более четкого оформления основного тезиса темы).

Ivana
()
Ответ на: комментарий от Ivana

нет, это не перегрузка методов. К тому же перегрузка — термин из быдлоязычков, в динамике перегрузка вообще не нужна Вы не поняли, видимо.

portquest2016
() автор топика
Ответ на: комментарий от Ivana

Можно сказать, что по «перегрузку», но в рантайме. Весь код выражения должен быть доступен, я привел пример с foo.bar.baz

portquest2016
() автор топика
Ответ на: комментарий от portquest2016

Можно сказать, что по «перегрузку», но в рантайме.

Нет :-) Перегрузка - термин из язычков :-) Вроде цепепе :-) Надо придумать что-то другое :-)

anonymous
()
Ответ на: комментарий от portquest2016

Повторюсь, я пытаюсь выяснить суть темы такими провоцирующими вопросами. Я тоже время от времени фофан балуюсь интерпретаторами, и например, могу придумать следующее: каждая лямбда у нас хранит контекст своего рождения, откуда она берет все свои свободные аргументы. Лексическое связывание как оно есть. Можем добавить динамическое - то есть лямбда будет брать часть свободных переменных из контекста своего вызова. Так работают рантаймовые макросы. Можно сделать маленьких простой шаг - при вычислении лямбды передавать дополнительно другую лямбду, контекст которой использовать в качестве контекста вычисления. Таким образом получаем не только лексическую (контекст создания) и динамическую (контекст вызова) области видимости, но и произвольные. Это ближе к тому, что имелось в виду?

Ivana
()

Ну, как писали ввыше в perl'e есть (было лол).

``` map { print } @values ```

print по умолчанию принимает в качестве аргумента $_. Можно так делать и для scalar'a:

``` for($val) { chomp print } ```

Те. можно было сделать метод, работающий с контекстной $_, если явно ничего не указано.

anonymous
()
Ответ на: комментарий от Ivana

грубо говоря, наш интерпретатор, например, джаваскриптовский, встречая foo.bar().baz() сначала разворачивает его в [bar_code]applay(foo) получает некий [another], затем разворачивает в [baz_code]apply(another), при этом про foo он уже ничего не знает, и узнать не может, надо иметь возможность зарезольвить baz с foo, в случае, если нужных имен в [another] не нашлось.

portquest2016
() автор топика
Ответ на: комментарий от Ivana

то есть лямбда будет брать часть свободных переменных из контекста своего вызова.

Вот это уже ближе. Но брать надо не только из вызывающей лямбды но и из вызывающей вызывающую и тп. Но в лиспе ужасный синтаксис, для таких вещей, то есть foo.bar.baz там приходится слова не по порядку ставить, а наоборот, типа Вася пошел гулять == (гулять (пошел Вася)) в сложных выражениях это все быстро превратится в адЪ

portquest2016
() автор топика
Ответ на: комментарий от portquest2016

Грубо говоря, если я правильно понял, то вычисление бар.баз у нас должно знать не только о текущем контексте и о собственных контекстах бар и баз, а еще и о контексте некоего фу ДЛЯ КОТОРОГО это бар.баз вычисляется. А если оно вычисляется одно для разных целей - то такое запретим или будем брать некий контекст по умолчанию (по соглашению). То есть читатель кода видит буквы бар.баз и при этом не может быть уверен, как оно вычислится, потому что имеет значение потребитель сего вычисления. В естественных языках это сплошь и рядом, да. Но вот идея пихать это в ЯП как минимум спорна. Хотя, если вы хотите написать свой Малболг с потребительскими контекстами, кто ж вам запретит :)

Ivana
()

экспериментирую с написанием простеньких интерпретаторов

если мы берем выражение, например foo.bar.baz, то наш интерпретатор, как правило, абсолютно не видит текущего окружения

Что-то тут не сходится

С контекстом, кстати, можно поступить очень просто - держать стек сущностей (переменных, например), и если текущий символ (токен) не имеет смысла, пробовать комбинировать его с предыдущими символами из стека. Что-то типа автоматического with из Паскаля.

vector a;
string b;

b = "";
a[3] = 0;
if (size > 3) {
    /* имеется в виду размер вектора a */
    b += " ";
    if (size > 3) {
        /* а здесь уже размер строки b */
    }
}

Это уже, впрочем, когда-то обсуждали на ЛОРе

Deleted
()
Ответ на: комментарий от portquest2016

не только из вызывающей лямбды но и из вызывающей вызывающую и тп.

именно так это и работает - иерархическое дерево фреймов = словарей связей имен. По крайней мере в Схеме и деривативах.

там приходится слова не по порядку ставить, а наоборот

это вкусовщина. Возможность этого механизма есть, а синтаксис - вещь субъективная. Не нравится префиксный Лисп - используйте поствиксный Форд :)

Ivana
()
Ответ на: комментарий от Ivana

Поправочка - Форд постфиксный используйте :)

Ivana
()
Ответ на: комментарий от Ivana

Да, примерно так. Правильно поняли.

Насчет пользы. Это будет, вне всякого сомнения очень медленно. Но для высокоуровневых вещей это самое то. Человеку, в тч программисту удобней читать тот код, котоый соответствует его представениям о том, как должен работать язык, к которому он привык IRL. Фактически, языки, особенно ООП, к этому и так стремятся, стремятся делать конструкции не бессмысленными а человекопонятными. например array foreach (multiplay) filter (even) -- уже довольно близко к естественному языку.

portquest2016
() автор топика

ананимус зарегился три с половиной раза и иногда дописывает в свои чудо-треды из под ананимуса. фееричнее не бывает.

anonymous
()
Ответ на: комментарий от Deleted

Что-то тут не сходится

я имел в виду в виде сырого кода

portquest2016
() автор топика
Ответ на: комментарий от portquest2016

Это будет, вне всякого сомнения очень медленно

На столько медленно, что неюзабельно. Причем скорость будет падать экспоненциально.

anonymous
()
Ответ на: комментарий от Ivana

По крайней мере в Схеме и деривативах.

стоп. В схеме это как раз работает строго наоборот:) Речь ведь была о динамическом связывании

portquest2016
() автор топика
Ответ на: комментарий от portquest2016

например array foreach (multiplay) filter (even) — уже довольно близко к естественному языку.

Это занудство :-) Читается как «Взять массив, и к каждому его элементу применить фильтр, отсеивающий чётные числа» :-) Гораздо проще «Отсеить из массива чётные числа» - filter_if(array, even).

anonymous
()
Ответ на: комментарий от anonymous

ну да, там еще умножение. filter_if(array, even) будет array filter(even) в ООП стиле. А вот при увеличении действий, например array map(one_action) filter (second_action) reduce (third_action) append (enother_array) — будет уже не так прозрачно в том стиле, который Вы показали

portquest2016
() автор топика
Ответ на: комментарий от portquest2016

А вот при увеличении действий, например array map(one_action) filter (second_action) reduce (third_action) append (enother_array) — будет уже не так прозрачно в том стиле, который Вы показали

Мне видно хорошо :-) Это же добавить массив b к свертке по h, отфильтрованной по критерию g, после маппинга f на массив a: append(b, reduce(h, filter_if(g, map(f, a)))) :-)

anonymous
()
Ответ на: комментарий от anonymous

дело вкуса. Но факт в том, что последовательность действий описывается задом наперед(точней, изнутри наружу), и требуется передача явных дополнительных аргументов. Если говорить о соответствии именно естественным языкам, то это хуже

portquest2016
() автор топика
Ответ на: комментарий от portquest2016

Хотел написать что мне сабжевая идея в чем-то напоминает Рефал а в чем-то декларативные объявления, но вместо этого наверное запилю сегодня свою же идею eval-in-context как особую форму в своем интерпретаторе и буду баловаться, мутируя замыкания извне, еще на пол шага приблизившись к жаваскрипту :)

Ivana
()

Сравнение ЯП с естественными языками интересно в первый момент. У них разные задачи. Язык программирования это язык инструкций. Разговорный язык это язык описания. После понимания этого, интерес к такому сравнению полностью пропадает. И сопоставление этих двух предметов более ничего не даст.

sin_a ★★★★★
()

functionname(parameters) - что именно вызывается - зависит от контекста (области видимости).
modulename:functionname(parameters) - не зависит от контекста, или прямое указание оного.

Зачем плодить ещё какие-то страшные сущности?

blexey ★★★★★
()
Ответ на: комментарий от sin_a

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

Разговорный язык — это не всегда язык описания. И даже тогда, когда он имеет форму описания, он все равно имеет семантику инструкций. Например, когда один человек говорит другому: «погода хорошая», он неявно подразумевает: «прими к сведению, что погода хорошая»

portquest2016
() автор топика
Ответ на: комментарий от sin_a

И кроме того, есть обратная связь. Те машинные языки, которые принято называть декларативными, например, html, также неявно все равно подразумевают инструкции. <p>foo</p> — отрисовать параграф с содержимым foo. Декларативность, ИМХО, относится к форме, а не к содержанию(семантике)

portquest2016
() автор топика
Ответ на: комментарий от sin_a

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

portquest2016
() автор топика
Ответ на: комментарий от portquest2016

Всё можно назвать всем. И SQL это язык инструкций. И ассемблер это язык запросов к базе данных, где базой данных является память. Но зачем?

sin_a ★★★★★
()
Ответ на: комментарий от sin_a

это не просто называние. Это создание адекватной, концептуально правильной модели. Зачем? Для решения задач, например, для преодоления и контроля сложности в разработке.

portquest2016
() автор топика
Ответ на: комментарий от portquest2016

отрисовать параграф с содержимым foo

Узкий и категорически неверный взгляд (как и все остальное в этом топике). <p> говорит «foo является параграфом» и ничего больше. А дальше уже каждый волен как угодно пользоваться этой информацией. Рендерер браузера его нарисует используя стандартные для параграфа шрифт и верстку. Поисковый движок его проиндексирует и даст словам в результате какой-то вес (вероятно, меньший, чем в заголовке), Книго-читалка не будет включать foo в автоматически сгенерированное оглавление и т.д. Так что <p> - это именно декларация в чистом виде, никакого императива в ней нет.

ddos3
()
Ответ на: комментарий от portquest2016

У этих двух явлений принципиально разные задачи. И сходство их случайно и может только наводить иллюзию.

sin_a ★★★★★
()
Ответ на: комментарий от sin_a

И, опять, же, что значит можно называть все всем? Это не просто называние, это осмысленная интерпретация, где слова лишь формируют смысл. Ну, назвать то можно, допустим, огурец жопой, или браки — однополыми(оксюморон, если исходить из самого понятия «брак»), толку то что от такого называния?

portquest2016
() автор топика
Ответ на: комментарий от portquest2016

Если уже обобщать, то до конца. Язык является средством передать реципиенту информацию и таким образом повлиять на его внутренние состояние. Что может привести (а может и не привести) к какой-то активной реакции с его стороны. И да, мы обычно пользуемся языками, когда хотим изменить какое-то состояние, и чаще всего делаем это для того, чтобы добиться реакции. Но не обязательно.

ddos3
()
Ответ на: комментарий от ddos3

то что одно и то же сообщение может интерпретироваться различными акторами(реципиентами) по разному, ничего не меняет.

portquest2016
() автор топика

как можно было бы в теории решить эту проблему.

Сформулируй проблему. То, что ты описываешь в предыдущем параграфе, является лишь описанием твоей картины мира (которая может быть верной или, скорее всего, неверной), но проблемы как таковой не поднимает.

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

ddos3
()
Ответ на: комментарий от portquest2016

Меняет. То, что каждый может интерпретировать его по разному и предпринять (или не предпринять) любые действия на свое усмотрение, говорит о том, что автор сообщения - в общем случае - не вкладывал в него никаких конкретных инструкций к действию, а лишь передал какую-то информацию о foo. И тут как раз и лежит разница между императивом и декларацией.

ddos3
()
Ответ на: комментарий от ddos3

Ну, во первых, лично я не считаю глобальные переменные злом, зло не в инструменте, а в его неверном использовании(спички — зло, ведь может случится пожар!) То что какие то объекты скрывают свое состояние — это тоже нормально. Но программист должен иметь полный доступ к конфигурации поведения каждого из них, язык не должен за него это решать

portquest2016
() автор топика
Ответ на: комментарий от portquest2016

Нет, смотри мой предыдущий коммент. Язык может использоваться как для деклараций, так и для побуждения к действиям. И если копать глубже, то побуждения к действиям можно рассматривать как частный случай деклараций, но не наоборот. Ты же сделал неполное обобщение только до побуждения к действиям.

ddos3
()
Ответ на: комментарий от portquest2016

Это все еще не описание проблемы. Мне до сих пор не понятно, что плохого в текущем положении вещей, и пока ты мне этого не объяснишь, я не увижу проблемы.

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

ddos3
()
Ответ на: комментарий от ddos3

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

Например, callback-hell в JS обусловлен вовсе не лямбдами, как принято думать, а лексическим связыванием

function(foo){
   return new Promise(bar) // fuck! bar do not watching foo!!!
}

все у нас через жопу, невозможно проектировать, не запутавшись в километрах лапши, и это еще называют высокоуровневыми ЯП, по недоразумению.

portquest2016
() автор топика
Ответ на: комментарий от portquest2016

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

мой eval-in-context (с возможностью мутирующих операторов, разумеется) как раз решает эту задачу полностью, не? И никакого далекого замаха, а всего пара строчек кода добавить в интерпретатор.

Ivana
()
Ответ на: комментарий от portquest2016

Я не понял твой пример. Что ты там хотел сделать и не смог? Попробуй придумать пример как-то связанный с этой реальностью, чтобы мне было легче его понять и согласиться, что это реальная проблема, которая требует решения. А то так можно все что угодно куда угодно привязать.

ddos3
()
Ответ на: комментарий от Ivana

нет, в выражениях типа foo.bar.baz он не решит проблему того, что вызов baz ничего не знает о foo, и его контексте. Там какой то хитрый лукап писать, и сохранять весь контекст вызовов. А твой eval-in-context есть во многих ЯП в том или ином виде.

portquest2016
() автор топика
Ответ на: комментарий от ddos3

Этот пример связан с реальностью. Для того чтобы ты смог вставить bar в качестве коллбека, и при этом, чтобы этот bar резольвил в своем теле foo, тебе нужно динамическое связывание. Именно по этому, ты вынужден херачить голые, безымянные лямбды инлайн в качестве аргументов промисам, асинхронным функциям и тп

portquest2016
() автор топика

Если вкратце - ты хочешь притащить то говно натлангов, с которым упорно борются создатели конлангов, машинные переводчики, службы поддержки и юристы, в языки программирования?

anonymous
()

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

Прорыв в этом направлении мог бы состояться со стороны поисковых машин. Они вначале пытались анализировать запросы на естественном языке. Пока ничего не получилось (а может быть уже и не получится). Оказалось что люди легко учат гугл-язык и пишут на нем «память ддр купить москва»

Deleted
()
Ответ на: комментарий от anonymous

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

Ну, в каком то смысле да, но в программировании это имеет несколько иные корни, это идет от недостатка ума, и облегчения написания компиляторов, думается.

portquest2016
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.