LINUX.ORG.RU
ФорумTalks

Зачем придумывают всё новые языки-велосипеды?

 , ,


0

1

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

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

Профессия размывается, за всем нереально уследить. Раньше, с некоторой натяжкой, всё было более-менее понятно: пэхэпэшник пишет бэк под веб, на джаваскрипте ваяют фронт, на делфи пилят формы, сишники — лоулэвл, крестовики — молодцы вообще ребята. А сейчас одно и то же можно сделать сотней разных способов. И вроде бы это хорошо, но вот глядишь на вакансии и там: требуется знания языка X123 (от 5 лет), опыт работы с фреймворком Y456, и ещё тулзы Z789, Z798 и Z897.

Да чёрт возьми, а если я знаю X321 и Z888? Мы вам перезвоним. А потом такие, ко-ко-ко, на рынке дефицит нормальных девелоперов, а юные вайтишники опыть наклепали говна и сорвали дедлайн трижды.

Наболело.


Зачем нужен элексир, когда есть шарпик, который знает каждая мартышка?

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

Зачем изобретают го, вместо развития сишечки?

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

Зачем нужна нода

Затем что много носителей языка, которые больше ни во что не умеют.

зачем нужен питон, когда есть руби?

За тем, что руби это уродливый опаскаленный них-питон.

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

Насчёт лиспа не уверен, мало где кроме конфигов stumpwm на старом буке и рисования картинок его использовал. Потыкал, посмотрел, прикольная вещь, убрал в шкаф обратно. Кложура задолбала лютейшими тормозами и прожорливостью, тоже в шкаф.
А в ракете система контрактов (в дишечке, между делом, тоже есть). Статику не заменит (контракты это всё таки про рантайм), но от многих ошибок оградит. не говоря о том, что есть typed/racket.
До guile руки не доходят плотнее её поглядеть, если контрактов там нет, то это грустно. monk, помнится, писал развёрнутый ответ, где контракты интереснее статики.

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

За тем, что руби это уродливый опаскаленный них-питон.

По моему вполне симпатичное поделие относительно питона, пусть живёт (или доживает).

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

Хорошо, если из этого что-то дельное выйдет. А если нет? Получится ещё один хаскель-лайт в лучшем случае.

Я Racket ценю в первую очередь за адекватную виртуальную машину.

Поэтому «ничего нового сверх уже существующего» вряд ли про неё. Ну или укажите язык, где существуют: call/cc, метки продолжений, гигиенические макросы, эфемероны, шапероны и имперсонаторы, исполнители воли, сторожа, контроль доступа к данным через инспекторов, контроль доступа к внешним данным через охранников, возможность из макросов добавлять код в модуль, где раскрывается макрос, ...

Я где-то половину уникальных возможностей перечислил. Причём если гигиенические макросы и call/cc есть хотя бы в Scheme, то всё остальное практически нигде.

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

typed/racket

Меня в нем удивил overhead. Меняешь base на typed и старт приложения с 200 мс, что уже дофига, становится 600 мс. Мне кажется язык с такими выкрутасами в рантайме фундаментально не совместим с типами. Сложно за всем уследить

Я вообще только Chicken смотрел. Показался наиболее адекватным за счет компиляции в натив.

vertexua ★★★★★
()
Последнее исправление: vertexua (всего исправлений: 1)
Ответ на: комментарий от WitcherGeralt

За тем, что руби это уродливый опаскаленный них-питон.

ну попробуй напиши на питоне

require "continuation"
arr = [ "Freddie", "Herbie", "Ron", "Max", "Ringo" ]
callcc{|cc| $cc = cc}
puts(message = arr.shift)
$cc.call unless message =~ /Max/
monk ★★★★★
()
Ответ на: комментарий от vertexua

Меня в нем удивил overhead. Меняешь base на typed и старт приложения с 200 мс, что уже дофига, становится 600 мс. Мне кажется язык с такими выкрутасами в рантайме фундаментально не совместим с типами. Сложно за всем уследить

Предполагается, что приложения на Racket должны работать хотя бы пару минут. А если очень нужна скриптота, то https://github.com/jFransham/racketd или https://github.com/willghatch/racket-rash

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

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

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

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

Большинство из этого кстати просто решает задачу инкапсуляции и sandboxing. Что тоже на уровне решено в куче других ЯП, просто по другому. А другие, вроде эфемеронов, есть где угодно как weak pointers/references.

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

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

Например, пишешь сайт. Можешь писать просто (синтаксис условный)

login,password = get_login_page()
if check_password(login, password) then
  start_page()
else
  error_page()

Функция get_login_page() выводит HTML страницу для ввода логина и пароля. Или возвращает пользователю 401, чтобы получить логин/пароль HTTP. Сохраняет точку выполнения и прерывает поток.

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

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

По сути то что решается или монадами, или генераторами, или async/await?

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

Системы актеров лучше справятся с этой проблемой

vertexua ★★★★★
()
Последнее исправление: vertexua (всего исправлений: 4)
Ответ на: комментарий от vertexua

А другие, вроде эфемеронов, есть где угодно как weak pointers/references.

При помощи эфемерона можно написать weak pointer, но при помощи weak pointer'а нельзя написать эфемерон. Это всё равно, что считать что call/cc есть где угодно как goto.

Что тоже на уровне решено в куче других ЯП, просто по другому.

Аналог шаперона, чтобы можно было описывать контракты в стиле «эта функция принимает набор чисел и возвращает функцию, которая возвращает число, которое больше любого из набора» я нигде не видел. Sandboxing там отдельно есть. А всё остальное скорее очень расширенный аналог private/protected/final/....

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

При помощи эфемерона можно написать weak pointer, но при помощи weak pointer’а нельзя написать эфемерон.

Мне показалось что это одно и то же. Так что там есть сверх weak ptr?

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

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

Я даже не беру Spring/Java EE, вот полегче - https://github.com/google/guice/wiki/AOP#example-forbidding-method-calls-on-weekends

vertexua ★★★★★
()
Последнее исправление: vertexua (всего исправлений: 2)
Ответ на: комментарий от vertexua

монадами,

Это немножко про другое

генераторами, или async/await

Да, это два из трёх основных применений продолжений. Третье — корутины. А подскажешь какую-нибудь библиотеку на генераторах или async/await, где такое можно делать? Вот на продолжениях есть: https://docs.racket-lang.org/continue/index.html#(part._.Using_.Formlets)

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

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

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

Я просто пытаюсь представить реальное применение в рамках например вебрсервиса. Который судя по тому как нынче все делается, сидит в докере и общается с бд. Можно ли написать такую абстракцию чтобы это все работало при перезагрузке или перенаправлении запроса на другую машину? Получается что чтобы все было так чисто нужно думать о сериализации, такое состояние должно ложиться в базу как Thrift/Protobuf/Json и потом оттуда оживать. В системах актеров с этим намного проще, потому что состояние очень четко отделено. На уровне системы типов требуй сериализируемость состояния и можно весь кластер потушить и восстановить. Весь стек сериализировать тяжелее и опаснее, там может быть ещё куча эфемерных объектов

vertexua ★★★★★
()
Последнее исправление: vertexua (всего исправлений: 3)
Ответ на: комментарий от vertexua

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

Всё просто потому, что они лалки, а на C++ умеют писать только царь и @Iron_Bug, а на C — только эдди, остальные не осилили.

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

Я от царя код блога жду, чистый, красивый, понятный, эффективный и надежный

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

Ну, попробуй напиши на руби:

Midnight takes your heart and your soul
While your heart is as high as your soul
Put your heart without your soul into your heart

Give back your heart

Desire is a lovestruck ladykiller
My world is nothing 
Fire is ice
Hate is water
Until my world is Desire,
Build my world up
If Midnight taking my world, Fire is nothing and Midnight taking my world, Hate is nothing
Shout "FizzBuzz!"
Take it to the top

If Midnight taking my world, Fire is nothing
Shout "Fizz!"
Take it to the top

If Midnight taking my world, Hate is nothing
Say "Buzz!"
Take it to the top

Whisper my world
WitcherGeralt ★★
()
Ответ на: комментарий от vertexua

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

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

Ну как площадка откатывания хероты - тут лиспы сильны. С силу кастомизации AST.

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

Угадай, откуда взялись сборщики мусора например

vertexua ★★★★★
()
Последнее исправление: vertexua (всего исправлений: 2)
Ответ на: комментарий от monk

callcc в Ruby obsolete, и их скорее всего выпилят. А так согласен, что Ruby как язык гораздо интереснее питона.

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

Ну, попробуй напиши на руби:

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

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

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

vertexua ★★★★★
()
Последнее исправление: vertexua (всего исправлений: 1)
Ответ на: комментарий от vertexua

Во-первых, не лисп, а Racket.

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

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

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

А что насчёт того что я выше спросил, какие средства безопасного программирования даёт лисп, как предохраняет от вполне естественных для мозга человека ошибок?

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

За счёт каких средств Лисп защищает от ошибок, совершаемых программистом?

Если речь про Common Lisp, то он позволяет почти любую допущенную ошибку исправить на ходу без остановки программы. И даже если остановилась, то исправить и продолжить, а не любоваться трупом в виде core или следа стека.

Если речь про Racket, то там контракты (которые проверяются частично статически) и жёсткая изоляция модулей.

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

За счёт каких средств Лисп защищает от ошибок, совершаемых программистом

Clojure + spec?

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

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

Частично при компиляции. typed/racket целиком при компиляции.

Проверку в рантайме можно сделать в любой жабе через AOP

Вот есть функция

Function<Integer,Integer> f(Vector<Integer> a, String b);

Как к ней написать проверку, что любая функция, которую вернёт f для любого своего аргумента вернёт значение не меньшее, чем максимальное из вектора a?

При том, что использоваться может, например, как

v.add(f(a, "ok"));
v.add(g("xxx"));

....

v[calc()].apply(5); // это может быть результат f, а может нет

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

В Java AOP делается в рамках контейнера. Когда классы инстанциируются, то они опционально проксируются. Injection происходит прокси, а не оригинального класса. Вызывающий код этого не знает

vertexua ★★★★★
()
Последнее исправление: vertexua (всего исправлений: 1)
Ответ на: комментарий от theNamelessOne

With ★★★ (14.10.19 01:52:35) Феерический *******

Я все понимаю. Но почему подселенец-то? %)

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

Обычно языки на этапе компиляции защищают от ошибок

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

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

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

Ты не умничай, ты пальцем покажи (с) анекдот.

Можешь показать для моего примера, как в Java указать ограничение на результат f? Нет, если сильно приспичит, то можно написать для конкретного случая класс, который будет делать нужную проверку и имплементировать Function<Integer,Integer>. А для следующей функции ещё класс, а на третьей уже забить на проверку и надеяться, что тестов хватит.

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

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

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

Вот интересно как это работает в Typed Racket если люди могут потом менять код на лету. В Typed Python можно много чего проверить и люди могут выполнять код динамически только уж совсем через eval/exec.

Плюс у меня сложилось впечатление что Typed Racket имеет рантайм стоимость

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

Вот интересно как это работает в Typed Racket если люди могут потом менять код на лету.

В Racket на лету можно поменять только то, что позволяет разработчик модуля. И тип символа в Typed Racket поменять нельзя.

Плюс у меня сложилось впечатление что Typed Racket имеет рантайм стоимость

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

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

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

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

Система типов Haskell или Idris действительно помогает в некоторых случаях. Но ради этого приходится жертвовать мощностью самой системы типов. Обычный lisp'овый map уже не описать.

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

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

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

Обычный lisp’овый map уже не описать

Интересно, почему? Именно map, функцию превращения коллекции одних элементов в коллекцию других. Также поддерживается замена типа коллекции, так как по дефолту map в куче языков программирования не считает по дефолту что тип коллекции сохранился, возвращает итератор, stream или еще какую-то абстракцию

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