LINUX.ORG.RU

Зачем нужны динамические языки?


0

0

Собственно не пойму. Вроде обещают более быструю разработку, но за счет чего? За счет того, что не надо писать тип при объявлении переменной? Так это ведь глупость, никакой скорости разработки это не добавит. Естественно, такие языки можно использовать только для прототипирования, но не проще ли сразу использовать язык, который обеспечит и скорость разработки и скорость выполнения, тем более, что динамический язык принципиально нельзя ускорить (имеется ввиду компилятор)? (я имею ввиду современные языки с выводом типов)

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

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

Скорее всего, когда говорят о "преимуществах", сравниваю что-то вроде c++ или java с каким-нибудь пистоном, на котором действительно проще и быстрее. Правда при этом, путают причину со следствием, man Пираты и Глобальное Потепление.

http://ru.wikipedia.org/wiki/Летающий_Макаронный_Монстр#.D0.9F.D0.B8.D1.80.D0...

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

> Гуглем страничку Qi II поищи, там даже автор книжку пишет.

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

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

> Нет. Написать ещё один селектор, который вернёт съедобную для утилитных классов информацию. И его можно сделать тривиальным для ускорения, а селектор с "подписями" --- несколько более сложным (хотя чего сложного в том, чтобы поставить -mailbox первым аргументом, а -dir вторым?).

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

А вот в языках со статикой тебе можно этот селектор будет не указывать. Его будет выводить компилятор через систему типов. => Экономия клавиш и улучшение читабельности.

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

> (хотя чего сложного в том, чтобы поставить -mailbox первым аргументом, а -dir вторым?).

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

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

>> 1. я считаю неправильным иметь доступ к АСТ не через прослойку

> Для лиспа её и нет. Можно специфичным для реализации способом добраться до ICR или аналога, но это на столько специфично, то для другой реализации всё может быть абсолютно по другому сделано.

s/ACT/AST/

В лиспе аналог AST -- это s-expr представляющая наш исходник.

Что касается ICR, то тут все мне кажется должно быть не реализационно-зависимым, а стандартным, примерно как стандарна реализация С.

> но лисп умеет жить там, где машинных пойнтеров, как таковых, нет.

Это ты про что, про использование лиспа как язык скриптования-чего-то-там, или про архитектуры железа?

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

FIX:

- а стандартным, примерно как стандарна реализация С.

+ устроена ожидаемым образом, примерно как у всех компиляторов с++ vtable, хотя и не стандартизирована, устроена ожидаемым образом.

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

>> (хотя чего сложного в том, чтобы поставить -mailbox первым аргументом, а -dir вторым?).
> И вот мы опять пришли к позиционным аргументам, источнику ошибок в языках с динамикой!


Когда они используются только в _одном_ месте, то ошибка переходит в другую категорию.

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

>> Нет. Написать ещё один селектор, который вернёт съедобную для утилитных классов информацию. И его можно сделать тривиальным для ускорения, а селектор с "подписями" --- несколько более сложным (хотя чего сложного в том, чтобы поставить -mailbox первым аргументом, а -dir вторым?).
> Если я тебя правильно понял, то этот селектор придется всегда указывать явно, когда ты передаешь свой объект в утилитные функции, ожидающие коллекцию.


Да.

> А вот в языках со статикой тебе можно этот селектор будет не указывать. Его будет выводить компилятор через систему типов. => Экономия клавиш и улучшение читабельности.


Неявное преобразование --- причина уже других ошибок. Так что сложность снизить не получится :)

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

> Неявное преобразование --- причина уже других ошибок.

Какое еще неявное преобразование? Не выдумывай :)

> Так что сложность снизить не получится :)

Нет, получится :D

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

>> Неявное преобразование --- причина уже других ошибок.
> Какое еще неявное преобразование? Не выдумывай :)


Ну это когда operator OtherType1(), operator OtherType2() определяются. Такие преобразования глазами очень сложно отследить. В результате опять возвращаемся к ошибке из того же класса, что и "приведение указателя к целому типу".

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

>>> Неявное преобразование --- причина уже других ошибок.
>> Какое еще неявное преобразование? Не выдумывай :)


> Ну это когда operator OtherType1(), operator OtherType2()

> определяются. Такие преобразования глазами очень сложно отследить. В

> результате опять возвращаемся к ошибке из того же класса, что и

> "приведение указателя к целому типу".


Не путайте преобразование типов (которое дает тварь складывать float с int и случайно впихивать int в bool) с перегрузкой функций.

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

>> Какое еще неявное преобразование? Не выдумывай :)

> Ну это когда operator OtherType1(), operator OtherType2() определяются.

Я понял. Но это специфическая фишка Си++, которую можно не использовать. Да и неинтересен Си++ в контексте обсуждения :)

tailgunner ★★★★★
()

Зачем нужны вообще языки программирования если вся обработка данных идет в базе? Что вы на них пишете? SQL наше всё

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

> В лиспе аналог AST -- это s-expr представляющая наш исходник.

Мой исходник может быть жутким коллажом макросов и мутировавшей read table, там даже sexp'ов может не быть ;)

> Что касается ICR, то тут все мне кажется должно быть не реализационно-зависимым, а стандартным, примерно как стандарна реализация С.

Внутренняя форма представления - это дело компилятора. Вы вообще видели язык, который на уровне стандарта регламентирует внутренности компилятора?

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

> Зачем нужны вообще языки программирования если вся обработка данных идет в базе? Что вы на них пишете? SQL наше всё

Какое эталонное быдлокодеришко выползло. Срочно изловить и отправить в Париж, в палату мер и весов!

К слову, знает ли экспонат про PL/SQL и прочие языки программирования на стороне базы?

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

> Все вызываемые слова без специальных ухищрений жёстко определяются на этапе компиляции, а не во время исполнения.

Это как-то мешает без малейших сомнений заюзать строку как число (получив мусор, естественно)?

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

> Собственно, лисповый компилятор в SBCL написан полностью на лиспе, и его можно модифицировать на лету.

Дико извиняюсь, но, даже будучи написанным на лиспе, этот компилятор не является изменяемым. Ибо он уже скомпилирован.

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

> За опровергающий пример был бы благодарен. Впрочем, для этого надо знать их.

Ты приводил пример, как можно забоксить типы в С++ через шаблоны-обёртки. Этот пример не покрывает даже паскаля, я не говорю про лисп.
В Delphi при вот таком вызове
foo([a,'1234',4.56,TMyObject.Create()])

образуется (на стеке) массив TVarRec, где можно узнать тип каждого элемента (кроме объектов, но они обычно растут от TObject и есть RTTI). В лиспе всё ещё проще - есть функция type-of и функция list.

Я оставлю за скобками, насколько удобно писать

foo(box(a),box('1345'),box(4.56),box(new myObject()));

Может быть, перекрытием оператора "запятая" и тут можно что-то сделать. В конце концов, пишут же в поток разные типы через <<.

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

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

Касаемо же Хаскеля, то я даже не буду смотреть на этот язык, т.к. в нём извращённый императив. Для меня этого вполне достаточно, чтобы поставить жирный крест навсегда. Я не люблю нарочитые извращения, подаваемые как высокое искусство. Придание художественного смысла извращениям - это явный симптом декаданса, а декаданс - это смертельно опасное заболевание даже не отдельных людей, а целых цивилизаций. Я стараюсь держать такие вещи как можно дальше от себя (кажется, я воздержался от слова "говно"?)

>> В CL я во время компиляции могу делать что угодно.

> Я тебя обрадую: компилятор ты всё равно менять не можешь.

Я прошу прощения, но ты просто не в теме. Марш в библиотеку :-)

> Однако deprecated тебя не спасет, если ты в *динамическом языке* все-таки пропустишь в одном из мест поменять сигнатуру вызова после смены сигнатуры определения функции.


Бывает ещё ситуация, когда я _не_хочу_ в данный момент менять все вызовы. Хочу поменять один, и прямо через 2 секунды получить результат с новой сигнатурой. А остальные дцать мегабайт зависимого кода мне неинтересны, т.к. заведомо известно, что я могу заняться ими послезавтра или что они вообще пойдут под нож. Конечно, тут лежат грабли, но наступать или не наступать на них - это моя священная свобода. Я скорее готов себе доверять, чем не доверять.

Кроме того, к слову, в нормальных динамических языках не нужно/не получится грепить исходники или запускать компилятор, чтобы узнать точки вызовов с неверной сигнатурой. Во-первых, для загруженного кода может быть непосредственно доступен граф перекрёстных ссылок (он записывается во время компиляции). Примеры таких языков - lispworks, и как минимум, firebird и MS SQL, хотя я думаю, это верно для всех SQL серверов. Кстати, я видел два проекта (и сейчас пишу третий) на SQL, где массированно используется МП и где без него были бы очень серьёзные трудности. Текст тупо порождается принтами и потом исполняется eval-ом. Кстати, SQL лишён идиотского ограничения, которое есть во множестве языков. В SQL можно переносить строковую константу на следующую строку. По этой причине, МП в нём делается очень легко без всякого квазицитирования, доступа к AST и прочим подобным вещам.

Также есть и методика, чтобы обойти проблему отсутствия проверки типов конкретно в случае изменения сигнатуры. Например. Меняем сигнатуру на какую-то нарочито неподходящую (например, сделаем ей 50 обязательных параметров). А функцию с правильной сигнатурой просто назовём "жопа". Во время перекомпиляции все ошибки всплывут точно так же, как и в плюсах. Заменим нашу функцию везде в этих местах на функцию "жопа". После исправления переименовываем всё обратно. Так что всё не так уж драматично, хотя расслабляться тоже не стОит.

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

Призываю сообщество, кстати, обратить внимание на boo (спасибо одному человеку с ЛОРа, не знаю, могу ли назвать его имя). Хотя язык, видимо, недобрал жизненных соков, он кажется мне на данный момент почти безупречным по заложенным в нём идеям. Если бы я стал делать свой язык, это было бы почти то же самое. Хотя я и склонен идеализировать :) И в общем-то, косяки в boo уже тоже нашлись.

>> В лиспе аналог AST -- это s-expr представляющая наш исходник.

> Мой исходник может быть жутким коллажом макросов и мутировавшей read table, там даже sexp'ов может не быть ;)


Именно поэтому, парадоксально, но жаба рулит. МП - это, как минимум, две вещи - это порождение исходника и машинное чтение исходника. Исходник жабы легко порождать и легко читать машиной. Кроме того, исходник жабы, которую может прочитать сама javacc или как её там, может быть прочитан и человеком.

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

А это - слишком сильное ограничение. Кроме того, даже если нам и удалось повеситься на макрорасширение (это возможно) и подсмотреть, что же там генерится перед машинным кодом, результат macroexpand может быть весьма неудобочитаем для человека (пример: loop). А уж когда мы падаем посреди этого безобразия в дебаггер, то это вообще ад. Т.е., в теории, это прочитать можно. На практике - с трудом. Производительность труда идёт при этом далеко лесом.

Так что лисп - это на самом деле не такая уж Ъ среда для МП.

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

> Мне тоже влом что-то за других бесплатно искать.

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

Что касается меня, то из лиспа мне кажется имеет смысл взять макросы и посмотреть на readtable, но в супервозможности Qi я не верю. Конечно, разговор был бы гораздо интереснее, если бы ты Qi пользовался и мы бы сейчас провели сравнение Qi <--> haskell <--> C++.

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

> Вы вообще видели язык, который на уровне стандарта регламентирует внутренности компилятора?

В следущем посте я поправился. Однако, кстати, кое-какие внутренности компилятора (та же vtable) иногда выплывают наружу и их можно дергать ручками, а не через компилятор.

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

> Кстати, SQL лишён идиотского ограничения, которое есть во множестве языков. В SQL можно переносить строковую константу на следующую строку. По этой причине, МП в нём делается очень легко без всякого квазицитирования, доступа к AST и прочим подобным вещам.

Ниасилил. Пример приведёшь?

> Исходник лиспа легко порождать, но я не знаю средства, как прочитать его машиной. Надёжно его можно прочитать только в краткий миг, когда он макрорасширяется. До этого он представляет из себя бурду из букв и скобок. После этого - машинный код. Все другие способы непереносимы.


А чем тебе "пропарсить бурду из скобок" --- не надёжный метод чтения лиспокода? В Tcl такой приём рулит, педалит и, главное, работает.

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

Буду отвечать постепенно

В кратце: не нравится с++ -- не учи. Только не надо его ругать, т.к. из моего примера ты явно не понял, что все что ты просишь делается 1 раз и навсегда, независимо от числа неоднокоренных иерархий классов. (В т.ч. type_of а-ля лисп для забоксованного значения, только в моем примере техника этого не показана, хотя она и сходная)

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

> Я оставлю за скобками, насколько удобно писать

В с++ практически ничего не удобно писать :-) я много раз писал, в т.ч. и в ЭТОЙ ветке, что у плюсов ужасный синтаксис.

Речь шла о полиморфизме, т.е. о настоящих массивах из-чего-попало. Давай различать синтаксис и семантику.

> Может быть, перекрытием оператора "запятая" и тут можно что-то сделать.

Да можно, слово box писать 1 раз на весь массив.

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

> Бывает ещё ситуация, когда я _не_хочу_ в данный момент менять все вызовы. Хочу поменять один, и прямо через 2 секунды получить результат с новой сигнатурой.

Попродробней? Я понимаю, как на ходу переделать внутренность функции, но с сигнатурой явно требуется конкретный пример.

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

> Дико извиняюсь, но, даже будучи написанным на лиспе, этот компилятор не является изменяемым. Ибо он уже скомпилирован.

А мужики-то не знают! И что же мешает этот компилятор перекомпилировать и уже перекомпилированным компилятором откомпилировать то, что надо, и так, как надо?

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

> Исходник лиспа легко порождать, но я не знаю средства, как прочитать его машиной. Надёжно его можно прочитать только в краткий миг, когда он макрорасширяется. До этого он представляет из себя бурду из букв и скобок. После этого - машинный код. Все другие способы непереносимы.

Ну я бы назвал это "избыточным МП", и считаю, что в частности по этой причине грамматика входного языка должны быть как-то ограничена. Это еще один аргумент в пользу гибкости по способу 2 (см. мой ответ mv)

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

> Касаемо же Хаскеля, то я даже не буду смотреть на этот язык,

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

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

> Однако, кстати, кое-какие внутренности компилятора (та же vtable) иногда выплывают наружу и их можно дергать ручками, а не через компилятор.

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

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

> Мой исходник может быть жутким коллажом макросов и мутировавшей read table, там даже sexp'ов может не быть ;)

Но макросам-то для работы требуется s-exp, ведь так?

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

> Что касается меня, то из лиспа мне кажется имеет смысл взять макросы и посмотреть на readtable, но в супервозможности Qi я не верю.

Qi - это Common Lisp, изменённый макросами и read table. Достаточно, чтобы подтвердить крутость CL в плане метапрограммирования?

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

> Иногда полезно просто отрывать голову за такое. Или менять язык, если без этого уже никуда.

Без этого можно жить (и живут 99.9% программ), но вот польза от этого все же больше, чем от разнообразия в имплементациях компиляторов.

Но я не хотел обсуждать ICR, это случайно вышло.

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

> Qi - это Common Lisp, изменённый макросами и read table. Достаточно, чтобы подтвердить крутость CL в плане метапрограммирования?

Не, меня интересует мощность системы типов, поддерживаемой Qi.

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

> > Мне тоже влом что-то за других бесплатно искать.

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


> Что касается меня, то из лиспа мне кажется имеет смысл взять макросы и посмотреть на

> readtable, но в супервозможности Qi я не верю. Конечно, разговор был бы гораздо интереснее,

> если бы ты Qi пользовался и мы бы сейчас провели сравнение Qi <--> haskell <--> C++.


Какие могут быть вообще сравнения haskell с C++, если в последнем нельзя написать 2 функции с 1 сигнатурой но разными возвращаемыми значениями?

Наряду с приведением типов втихаря это убивает в С++ всю красоту его шаблонов :[.

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

> Касаемо же Хаскеля, то я даже не буду смотреть на этот язык, т.к. в нём извращённый императив.

4.2 откровенное. В Хаскеле отличный императив, который, к тому же, гладко интегрирован в общий функциональный подход.

> Я прошу прощения, но ты просто не в теме. Марш в библиотеку :-)

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

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

> И что же мешает этот компилятор перекомпилировать и уже перекомпилированным компилятором откомпилировать то, что надо, и так, как надо?

И чем тут Лисп лучше любого другого языка? Хаскеля, плюсов, whatever?

К тому же, это не называется "менять", это называется "сделать другой". А кастомеры за такое чистят программеру чайник.

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

> Какие могут быть вообще сравнения haskell с C++, если в последнем нельзя написать 2 функции с 1 сигнатурой но разными возвращаемыми значениями?

> Наряду с приведением типов втихаря это убивает в С++ всю красоту его шаблонов :[.

+1.

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

Вы просто не понимаете, как Лисп работает. В лиспе работающая программа реально может внести изменения в компилятор (который, к слову, встроен в тот же образ, где крутится программа), перекомпилировать кусок самой себя же и получить совершенно другой код. Разница с whatsoever в том, что программа в это время не прекращает работать, т.е. нет раздельных стадий (пере)компилирования и (пере)запуска.

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

> Компилятор - бинарник, и хрен ты его поменяешь.

В классической реализации Лиспа собирается минимальное ядро компилятора (часто boostrap'ом из старой версии этого компилятора или вообще при помощи другой реализации), уже им собирается сам компилятор со всеми фенечками и свистелками, потом образ памяти живой программы сохраняется на диск. При последующем запуске этот образ загружается в память и происходит вызов указанной функции. Пользователю ничто не мешает изменить образ в памяти, сохранить его на диск вместо исходной сборки и в следующий раз видеть все внесённые ранее изменения. Собственно, "откомпилированные" лисповые программы на диске лежат в виде такого вот модифицированного образа. Компилятор от среды исполнения не отделим.

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

> Какие могут быть вообще сравнения haskell с C++, если в последнем нельзя написать 2 функции с 1 сигнатурой но разными возвращаемыми значениями?

Не понял, зачем это нужно? На пальцах объясни, или дай ссылку.

До недавнего времени нельзы было иметь const T1 f(T2) одновременно с T1 f(T2) -- это конечно неприятно (как стало в С++0х -- не знаю).

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

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

Бл*дь, какой ужас. Я ночь спать не смогу теперь.

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

> т.е. нет раздельных стадий (пере)компилирования и (пере)запуска.

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

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

> 1. http://en.wikipedia.org/wiki/Qi_%28programming_language%29 2. http://www.lambdassociates.org/doc.htm

1. Прошлый раз (давно) заходил в википедию -- там было что-то совсем не информативное. Щас прочел, интерено, надо почитать, т.к. такого подхода (а-ля логический вывод) я не видел.

2. Жаль что они сделали 15-минутное введение только для ML-щиков. Я его очень плохо знаю.

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

> Что в твоём понимании есть бинарный компилятор?

Это такая неизменная хрень, версию которой пишут в багрепортах :)

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