LINUX.ORG.RU

Что хорошего можно написать на Схеме?


0

2

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

В планах - расти как программист. Стоит ли менять Руби на Схему как на более пригодный для чего-то (чего?) инструмент?


Ответ на: комментарий от buddhist

но тьюринг-неполные языки не могут быть языками общего назначения.

Задачи, которые обычно требуется решать при помощи ЯП общего назначения, тьюринг-полноты не требуют.

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

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

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

Написание интерпретатора тьюринг-полного языка, очевидно же :)

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

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

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

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

gnucash, lilypond, texmacs, gimp, причем в некоторых схемы совсем немного (для протокола: лично я только за, чтобы приложений было больше).

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

Только два примера: исследования Actor Model и язык программирования Arc.

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

Гораздо существеннее то, что она широко применяется (наряду с некоторыми другими языками) для научных исследований в области CS.

Это косвенно, а то можно придти к тому, что ее изучение благоприятно повлияло на CS-специалистов. То есть, не совсем честно отвечать в таком ключе на претензию скорее практического применения:

Судя по тому, что за все десятилетия существования схемы на ней вообще ничего хорошего так и не написали

anonymous
()

Например R это самописный интерпретатор Схемы.

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

Это косвенно, а то можно придти к тому, что ее изучение благоприятно повлияло на CS-специалистов. То есть, не совсем честно отвечать в таком ключе на претензию скорее практического применения

Согласен.

Но зачем замыкаться на применении именно в том смысле? Если такового практически нет, то что - Scheme уже не нужна вообще? Просто будем считать, что сфера ее применения - «программирование языков программирования». :)

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

я намекал на очень специфичный синтаксис лисповых языков.

по вопросу, если серьезно. понимание что такое ФП в любом случае нужно. схему по-серьезному применять... эм... ну...

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

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

А на кой нужны эти «CS-специалисты»? Программировать-то все эти теоретики не умеют, только дисеры писать.

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

А на кой нужны эти «CS-специалисты»? Программировать-то все эти теоретики не умеют, только дисеры писать.

Шариков? Опять будешь про переписку Энгельса с Каутским говорить?

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

А что, на Агде нельзя написать интерпретатор Brainfuck?

Вроде того. Зато типизированное лямбда исчисление со строгой нормализацией заводится в несколько строчек.

А допилить Тьюринг-полноту невозможно без изменения языка.

Если говорить про агду, то там полнота за счёт FFI к хаскелю. Есть, например, REST'ful фреймворк - сервер и всякое I/O там на хаскеле (то что оно нетерминируемо агде не видно), а на агде всякая верификация.

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

Задачи, которые обычно требуется решать при помощи ЯП общего назначения, тьюринг-полноты не требуют.

А как же event loop писать?

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

А как же event loop писать?

А зачем его писать? Компилятор просто подхватывает ф-ю с типом Event -> Action и генерит код, который ее будет вызывать при наступлении соответствующего события, например.

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

Компилятор просто подхватывает ф-ю с типом Event -> Action и генерит код, который ее будет вызывать при наступлении соответствующего события, например.

Типа receive foo -> bar end в эрланге? Если событие никогда не наступит, то программа никогда не остановится. Итого, receive может с тем же успехом дополнить тотальный язык до тьюринг полного как и бесконечные циклы, общая рекурсия и т.п. Другое дело, что тут получается как с IO в хаскеле, где, в отличии от более древних языков, можно выбирать - писать гарантированно steteless код или stateful код. Также в агде, например, можно выбирать - писать гарантированно терминируемые термы или нет (с помощью inf-типов).

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

Типа receive foo -> bar end в эрланге? Если событие никогда не наступит, то программа никогда не остановится.

Да нету никакого receive. Просто если есть функция, типом аргумента которой является некий event, то ф-я будет запущена.

Также в агде, например, можно выбирать - писать гарантированно терминируемые термы или нет (с помощью inf-типов).

В нашем случае все термы будут гарантировано терменируемые, т.к. терма выражающего луп в языке не существует. Мы можем выразить ф-ю, которая будет вызвана во время лупа (терменируемую), а вот сам луп - нет. Короче говоря - если язык не тьюринг-полон, то мы не можем написать ф-ю, которая работает как черный ящик. Но мы можем написать ф-ю, которая сгенерирует этот черный ящик :)

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

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

Просто если есть функция, типом аргумента которой является некий event, то ф-я будет запущена.

Ну значит луп будет в самом рантайме.

И всё равно - как предполагается вызывать такую функцию в языке? Обычно можно видеть AMP (как в ерланге), callback-и (как в node.js) или неблокирующее IO (как в хаскельном STM).

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

Ну значит луп будет в самом рантайме.

Ну да.

И всё равно - как предполагается вызывать такую функцию в языке?

Как и любую другую, а в чем проблема?

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

То есть выразительность тьюринг-худого ЯП ничем не меньше, чем у тьюринг-полного.

Ну хорошо, пусть будет язык с только тотальными и терминируемыми функциями (рекурсия общего вида запрещена) и я хочу на таком языке написать 24/7 сервис - как мне это можно сделать?

Если есть AMP, то такой терм:

test() ->
  receive
    foo -> bar
  end.

уже может не отработать за конечное время. Такой терм:

test chan f = atomically (readTChan chan) >>= f

тоже уснёт пока в chan не появится запись.

То есть, такой тотальный язык, если его дополнить какой-то реализацией событийной модели в рантайме (не в самом языке) должен будет с этим рантаймом как-то взаимодействовать, а значит, уже можно сделать нетерминируемый терм. Вместе с примитивами рантайма язык получается как раз тьюринг-полный, а без таких примитивов не получится запускать функции Event -> Action (или получится?).

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

Как и любую другую, а в чем проблема?

Кто даст функции test : Event -> Action терм типа Event? Рантайм? Рантайм не детерминирован и этот Event может никогда не наступить. Если я напишу

-- | Total function.
test : Event -> Action
test = ...

foo : Action
foo = test gimmeEventPlease

то относительно foo (а это терм) нельзя дать никаких гарантий - он не терминируем, тьюринг-полнота возвращается.

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

VisualBasic в Ъ

Воистину. Только VB6. Только On Error Resume Next.

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

Ну хорошо, пусть будет язык с только тотальными и терминируемыми функциями (рекурсия общего вида запрещена) и я хочу на таком языке написать 24/7 сервис - как мне это можно сделать?

Сгенерировать на этом ЯП некоторое конечное описание, по которому рантайм впоследствии будет исполнять 24/7 сервис.

Как я уже упоминал - в предельном случае можно сгенерировать просто бинарник программы, которая и будет этим 24/7 сервисом.

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

Нет, можно построить взаимодействие так, что событийная модель в рантайме будет, а нетерминируемых термов - не будет. Ну вот как тот же пример с лупом - мы описываем, например, одну единственную ф-ю f: MouseLeftClick -> IO (), f = showMessage «Click!». Все термы терменируемы, но крутятся рантаймом в бесконечном лупе. т.е. в данном случае мы сгенерировали конечное описание нашего лупа.

а без таких примитивов не получится запускать функции Event -> Action (или получится?).

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

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

Кто даст функции test : Event -> Action терм типа Event? Рантайм?

Может, и рантайм, а может и мы сами как-то можем событие сгенерировать (если у Event есть конструктор).

Рантайм не детерминирован и этот Event может никогда не наступить.

Ну значит он никогда не наступит, в чем проблема? :)

то относительно foo (а это терм) нельзя дать никаких гарантий - он не терминируем

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

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

То етсь такой ситуации, в которой foo не будет вычислен за конечное время быть не может.

Ерунда, если f - терминируема, а g - нет, то f(g()) может не быть терминируемой. Тут test терминируема, а gimmeEventPlease - нет, так что foo может быть нетерминируемой.

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

Агда допиливается до тюринг-полного языка параметром --no-termination-check. Но даже без него если ты уверен что юзер не будет ждать час пока твоё творение тупит можно просто задать лимит итераций и язык с точки зрения нетерпеливого юзера ничем не будет отличатся от тюринг полного. Разница между полным и адекватным неполным языком заметна только бессмертным и бесконечно терпеливым существам.

А на практике не полнота нужна языку, а ffi. Вот без него язык можно считать неполноценным и, скорее всего, есть задачи которые на нём не разрешимы, в то время как на любом языке с ffi они разрешимы. ffi, а не тьринг-полнота позволяет агде делать сервисы. Потому что без ввода-вывода, который идет через ffi и недетерминирован по определению event loop никому не нужен. Да и сама программа тоже.

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

Ерунда, если f - терминируема, а g - нет, то f(g()) может не быть терминируемой. Тут test терминируема, а gimmeEventPlease - нет, так что foo может быть нетерминируемой.

gimmeEventPlease терменируема. нетерменируемых ф-й в ЯП нет.

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

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

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

gimmeEventPlease терменируема

Т.е. если она должна вернуть, например, char который ввёл пользователь - это терминируема? Она может ждать этот char и не дождаться его.

нетерменируемых ф-й в ЯП нет.

Ну да, а значит нет IO, конкурентности, сообщений, а программы предлагается писать посредством написания компилятора (терминируемого) из спецификации в бинарник. И после этого ты говоришь что такой язык ничем не уступает в выразительности традиционному тьюринг-полному языку с возможностью явно использовать event loop? Речь ведь идёт именно про ЯП который можно _использовать_, а не просто про некую мета-теорию со строгой нормализацией которая может стоять за этим ЯП. То о чём ты говоришь это вообще совсем другой подход, довольно мало связанный с традиционным (читай, с тем что обычно ассоциируется со словами «выразительный ЯП»), я вообще не видел ни одной программы где бы он использовался как-то иначе, чем просто вспомогательный подход.

А так, отделение терминируемых программ от нетерминируемых на коданных и нетерминируемых использующих примитивы данной событийной модели (IO, сообщения, и т.п.) это, конечно, хорошо. Так же как отделение stateful кода от pure кода, которое уже произошло (Haskell & Co, Erlang).

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

Так же как отделение stateful кода от pure кода, которое уже произошло (Haskell & Co, Erlang)

+ Clojure. В Erlang, правда, у процессов есть мутабельное локальное окружение. И у динамических языков с compile-time гарантиями этого отделения не очень хорошо, они там могут быть чисто синтаксическими, как в Erlang.

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

Т.е. если она должна вернуть, например, char который ввёл пользователь - это терминируема? Она может ждать этот char и не дождаться его.

Она сгенерирует событие. Ждать ничего не будет.

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

Ну не знаю, вот в хаскеле нету ИО, конкурентности, сообщений, а программы пишут именно в виде спецификаций бинарника (точнее не самого бинарника - а вычислительного процесса, но это непринципиально). И все довольны. Видимо, подход не так плох?

И после этого ты говоришь что такой язык ничем не уступает в выразительности традиционному тьюринг-полному языку с возможностью явно использовать event loop?

Естественно. Важен результат. А результат - та же самая программа.

Речь ведь идёт именно про ЯП который можно _использовать_, а не просто про некую мета-теорию со строгой нормализацией которая может стоять за этим ЯП.

Ну и я об этом говорю.

То о чём ты говоришь это вообще совсем другой подход, довольно мало связанный с традиционным

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

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

Любая программа на хаскеле. Можешь посмотреть.

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

Ни в эрланге, ни в кложуре никакого такого отделения нет, не выдумывай. Там весь код вперемешку. В хаскеле тоже никакого отделения нет - там весь код чистый, а грязного кода написать нельзя (unsafePerformIO и ffi не считаем, понятное дело). Вообще ни одного ЯП, в котором было бы четкое отделение грязного кода от чистого я не припомню.

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

Ни в эрланге, ни в кложуре никакого такого отделения нет, не выдумывай.

На уровне философии/идеологии очень даже есть.

Ну не знаю, вот в хаскеле нету ИО, конкурентности, сообщений, а программы пишут именно в виде спецификаций бинарника

В хаскеле тоже никакого отделения нет - там весь код чистый, а грязного кода написать нельзя

Я, пожалуй, промолчу :)

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

На уровне философии/идеологии очень даже есть.

Чего нету/есть на уровне философии/идеологии - это дело вкуса. Для кого-то есть, для кого-то нет.

Я, пожалуй, промолчу :)

Ну зачем молчать? Можно же просто привести пример хоть одной «грязной» ф-и :)

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

хоть одной «грязной» ф-и :)

Чтобы не было вкусовщины в определении, какая ф-я грязная, а какая - нет, назовем грязной ту f, для которой не будет выполняться условие map f . g = map f . map g при каком-нибудь g (g пусть будет для определенности чистой).

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

Да нет, меня больше смущает заявление о том что нет IO, сообщений и конкурентности. Про чистые функции ещё ладно, пусть весь код будет чистым (зачем всё и затевалось с монадическим IO), stateful вычисления это делать не мешает. Короче - stateful вычисления, IO вообще, конкурентность, сообщения (channels, STM) и прочие императивные вещи (если я что-то не назвал). Без всего этого хаскель никогда бы не стал языком который можно применять на практике, так бы остался академической игрушкой вроде миранды.

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

Да нет, меня больше смущает заявление о том что нет IO, сообщений и конкурентности.

Нету ровно в том смысле, в котором их нету в тьюринг-худом ЯП. То есть написать программу, которая бы выполняла ИО, мы на хаскеле не можем. Мы можем написать программу, которая сгенерирует вычисление, выполняющее ИО. Если бы хаскель был тьюринг-худой, то мы точно так же могли бы генерить ио-термы, которые потом рантайм как-то подхватывает и потом исполняет. В предельном случае ИО-терм в хаскеле может представлять из себя бинарный код, а рантайм - процессор :)

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

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

Это софистика

Т.е. я тогда не понимаю, что мешает называть программу на си чистой спецификацией грязного control flow компилируемой за конечное время (не C++ с шаблонами, же), генерирующей бинарник выполняемый, возможно, сколь угодно долго. Разве что верификации в процесе компиляции производится меньше.

quasimoto ★★★★
()

Что хорошего можно написать на Схеме?

<fat>
emacs?!
</fat>
:-D

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