LINUX.ORG.RU

Vim или Emacs? А LISP в 2021?

 , ,


1

4

https://www.youtube.com/watch?v=8Q9YjXgK38I&t=42s

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

А ведь Crashbandicoot была годной игрой…

Что выбрать? Vim или Emacs?
Изучать в 2021 году Lisp? Если изучать, какой? Практика?
А не засмеют сотрудики?

Времени в сутках маловато, на всё не хватает.


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

завоевав исконно лисповую нишу

ЛИСП никогда не использовался коннективистами (ну массово). ЛИСП это про символьный подход.

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

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

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)
Ответ на: комментарий от Siborgium

Главный смысл всего этого развлечения – оптимизация – работает очень условно

Так по ссылке как раз написано, что с неё всё хорошо. По типам автоматически выкидываются лишние проверки.

Все, связанное с дженериками, находится в зачаточном состоянии.

??? Там вроде всё хорошо. Если не брать примеры типа map cons (где оба аргумента полиморфные). Я ещё понимаю, если бы про продолжения претензия была.

Все по ссылке https://docs.racket-lang.org/ts-guide/caveats.html

Постепенно чинится

Я в свое время попробовал на этом писать, и понял, что на untyped racket писать значительно проще, при этом я почти ничего не теряю.

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

Например, если есть


(: size auth-admin (-> User Admin))
(: action1 (-> Admin ...))
(: action2 (-> Admin ...))
...
(: action_n (-> Admin ...))

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

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

Разгадка проста: ЛИСП это закрытая система.

В смысле???

Вроде исходники всего открыты и расширяемы. Пакеты доступны через quicklisp. Чем питон более открыт?

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

И что же думает по этому поводу Intel? Давайте засунем в процессор аппаратный декодер Quick Sync

То же, что делала IBM последние 20 лет.

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

В смысле???

В прямом смысле. Вещь в себе. Упрощённо: написанное на ЛИСПе нельзя использовать вне ЛИСПа. Написанное не на ЛИСПе сложно (крайне костыльно, теряются все преимущества системы) использовать в ЛИСПе.

Вроде исходники всего открыты и расширяемы

Ты не путай открытые исходники и открытые системы.

Чем питон более открыт?

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

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

Так по ссылке как раз написано, что с неё всё хорошо. По типам автоматически выкидываются лишние проверки.

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

Если не брать примеры типа map cons (где оба аргумента полиморфные).

Это примитивщина. Если не осилили это, значит, от дженериков там одно название.

Постепенно чинится

Никакой разницы нет, чинится это или не чинится. В данный момент это не починено.

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

Т.е. получаю то, что дает любой статически типизированный язык, но с кучей ограничений и недоделок.

Siborgium ★★★★★
()
Ответ на: комментарий от no-such-file

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

Ну не знаю. Я делал привязку к GTK для Common Lisp’а и смотрел как сделан аналогичный для питона. Для питона пришлось делать ещё набор костылей на си, чтобы всё работало. Для лиспа основной проблемой было правильно отобразить на CLOS.

Вообще, написанное не на лиспе отлично интегрируется в лисп, а если ещё лисп с финализаторами (SBCL, Racket), то и все преимущества сборщика мусора получаем.

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

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

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

Как её проводить, если может прийти любой Real? Или что значит «типы известны»? (define (f [x : Float]) : Float (+ x 2.5)) транслируется в (define (f x) (unsafe-fl+ x 2.5)). Если же тип указан Real, то складывать их как float уже нельзя.

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

Это примитивщина.

Так помоги им, если знаешь как.

Т.е. получаю то, что дает любой статически типизированный язык, но с кучей ограничений и недоделок.

Практически в любом статическом языке ограничений на фоне системы типов Typed Racket намного больше.

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

привязку к GTK

Это именно привязка сбоку, преимущества ЛИСПа потеряны, ты пишешь на ЛИСПе как на любом другом рандомном языке. Тогда нафиг нужен ЛИСП? Ну вот никто и не использует.

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

Это именно привязка сбоку, преимущества ЛИСПа потеряны, ты пишешь на ЛИСПе как на любом другом рандомном языке.

Только GUI. Всё остальное как на лиспе. Да и в GUI были добавлены конструкции типа (with-progress-bar ….). Классы и методы GUI являются классами и обобщёнными функциями CLOS, соответственно расширяются как положено.

Кроме того, работают все преимущества лиспа: можно менять окошки не выходя из программы, при получении ошибки GTK я её вижу в отладчике и могу исправить. Объекты GTK собираются сборщиком мусора.

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

Как её проводить

Как в расте.

если может прийти любой Real?

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

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

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

Ничего не понял. Тип аргумента Real. Для каких типов надо генерировать? И как определять какой тип из сгенерированных выбрать на определённое значение? Дополнительный typecase делать? Так + его и делает и только этим и отличается от unsafe-fl+.

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

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

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

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

Да. По твоим ссылкам же пишут, что два диалекта лиспа в одном редакторе — перебор, а если писать без elisp’а, то надо с нуля.

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

Может быть общий движок буферно-оконный, который не важно, на каком языке расширять.

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

В C++ проблема в том, что строка a = b >> c; может делать что угодно. Может быть, это просто вычисление. А может быть запись на жёсткий диск.

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

Разве что стандартная библиотека подаёт «плохой пример». Кстати, кроме стримов есть и filesystem (где «не по назначению» используется деление).

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

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

Это только отчасти правда. Примерно точно так же можно сказать, что для обучения Java нужно учить C, ведь есть библиотеки и методы Java, которые работают с нативной реализацией через JNI. Хотя, никакого C синтаксиса там нет. И точно так же с Clojure, для вызова java не надо учить java в прямом смысле этого слова. Часто уже готовы обертки над java библиотеками. Ну и для самого обучения Clojure (синтаксису, иммутабельности, подходу к многопоточности, макросам и в целом подходу к REPL разработке) не нужно изучать ни Java ни JVM. Хотя, конечно, для реализации каких-то серьезных проектов, особенно тех, которые куда-то интегрируются - там вероятно, придется какие-то Java библиотеки подключить, но часто там достаточно просто их обернуть в Clojure стилистику. При этом, абсолютно аналогично все обстоит с другими лиспами, только Java нужно заменить на C/C++ и это часто скорее минус, чем плюс.

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

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

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

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

мономорфизация дженериков

union U { i: i32, f: f32}
enum Tag { I, F}

struct Real { t: Tag, d: U }

fn myadd (x: Real, y:Real) -> Real
// ...

А ты точно знаешь, что такое дженерики?

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

(f 3.5) # кодогенерация для Positive-Float

Здесь скорее будет кодогенерация для 4.5. Вычисления от константы без побочных эффектов почти всегда свёртываются.

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

А ты точно знаешь, что такое дженерики?

Так ты же Real назвал дженериком.

Хочешь дженерик, пиши

(: f (All (a) (-> a a)))

Но тогда нельзя использовать +, так как он определён для конкретного типа, а не для произвольного.

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

Пихай проверку и будет можно.

B0B
() автор топика
Ответ на: комментарий от no-such-file

Это именно привязка сбоку, преимущества ЛИСПа потеряны, ты пишешь на ЛИСПе как на любом другом рандомном языке. Тогда нафиг нужен ЛИСП? Ну вот никто и не использует.

Раскрой мысль. Где утиная любовь? Кто, как и чем ломает неокрепшие умы? Почему это происходит? Как можно повлиять на данную ситуацию и стоит ли?

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

Так ты же Real назвал дженериком. Хочешь дженерик, пиши

(: f (All (a) (-> a a)))

Полагаю, имелось в виду что-то вроде

myadd : (t <: Real) => t -> t -> t

Т.е. для любого типа t, являющегося (подтипом) Real. При этом, для каждого конкретного t генерируется специализированый код, а не используется один общий для всех Real.

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

А ты точно знаешь, что такое дженерики?

Честно говоря, я тоже не понял почему ты считаешь, что в ракете тип Real должен быть дженериком. Отношение между Any <- Real <- Integer - это наследование, почему тут должна быть мономорфизация? В расте если (трейт) B наследуется от А, то для функции fn foo(x: &B) мономорфизация тоже не будет выполняться.

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

Т.е. для любого типа t, являющегося (подтипом) Real.

Так их бесконечность. Потому что для каждого значения существует тип из одного элемента, а значений у Real счётная бесконечность (если предположить, что оперативная память не ограничена).

По-моему, плохая идея.

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

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

Это в Racket есть типы из одного значения и прочее такое, а в остальных языках --- нет.

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

Если у тебя объявлена такая функция, и фактически в коде применяется только к каким-нибудь double и rational, то и сгенерированы специализации будут только для double и rational.

Ну и для типов из одного значения можно генерировать код соответствующего типа-множества, например, для unit double генерировать как для double. А то и вообще свёртывать, раз значение известно из типа.

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

слово то какое придумали… мономорфизацыя… тьфу.. прости господи…

alysnix ★★★
()
Ответ на: комментарий от no-such-file

Ура, лиспосрач! В 2021!

В прямом смысле. Вещь в себе. Упрощённо: написанное на ЛИСПе нельзя использовать вне ЛИСПа. Написанное не на ЛИСПе сложно (крайне костыльно, теряются все преимущества системы) использовать в ЛИСПе.

Вообще-то, легко. Если говорить про общелисп, то легко дёргаются сишные API (не сложнее, чем в других языках, где FFI-обёртки нужны), и легко сишные API делаются, где это предусмотрено.

Хренадцать лет назад так и делали: уберсложная мегавафля была накатана на общелиспе, сконпелирована в минимальном виде (без REPL, конпелятора и с крайне обрезанным рантаймом - всё через штатные фичи LW) и покладена на диск в виде so. Который сишные утили подлинковывали в себя и дёргали лисповые функции.

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

Он так-то сбоку, но разговор шел про «питон vs лисп» и если если лисп так хорошо, то почему же новичок питон уничтожил лисп, завоевав исконно лисповую нишу?

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

Помнится, два раза по хренадцать лет назад, ещё будучи крестовым фанбоем, читал ночью на кухне CLtL2, и аж в голове щёлкнуло от натуги: «Как так?! Это вообще законно? А почему сейчас ничего такого нет, если это 30 лет назад уже в ANSI-стандарт даже пролезло?»

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

При том, что питонье убожество еще и не умеет комплиироваться! Насколько плох должен быть лисп, чтобы несмотря на все недостатки питона индустрия выбрала именно питон? Причем, это даже не столько индустрия, а сколько какой-нибудь гугл.

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

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

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

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

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

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

Давно написали.

В реальных проектах, с мультисотмиллионнодолларовым продакшеном, вижу переход на Раст, для большего контроля над потребляемой памятью. Мотивация простая: если голанговый миддлварь на гипервизоре занимает $20 памяти, $2 электричества в месяц и $50 в месяц недополученного ревеню за недопроданные виртуалки, то в масштабе 100к хостов это будут стартовые инвестиции в $2M на железо чисто под голанг, плюс операционные затраты $5.2M/месяц.

Это на локалхосте можно оттяпать половину памяти на хелловорд, подвернуть штанишки, хлебнуть смузи, и ничё. А в продакшене придёт злой CFO.

mv ★★★★★
()
Ответ на: Ура, лиспосрач! В 2021! от mv

дёргаются сишные API

Ну дергаются, а накладные расходы? Это во-первых, а во-вторых, в ЛИСПе есть например рестарты, а в Си нет ничего такого. Когда дергаются «сишные API» получается тупо Си со скобочками. Для питонов это не актуально, потому что питон сам по себе говно, а для ЛИСПа актуально. Почти любую «сишную либу» ты на ЛИСПе писал бы совершенно по-другому. В этом проблема открытых систем: там всё сводится к некоему общему знаменателю, по необходимости максимально тупому и примитивному.

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

Ну дергаются, а накладные расходы?

Кого в 2021 накладные вопросы колышут? В 2010 не волновало. И в 2000, впрочем, уже тоже.

Это во-первых, а во-вторых, в ЛИСПе есть например рестарты, а в Си нет ничего такого. Когда дергаются «сишные API» получается тупо Си со скобочками. Для питонов это не актуально, потому что питон сам по себе говно, а для ЛИСПа актуально. Почти любую «сишную либу» ты на ЛИСПе писал бы совершенно по-другому. В этом проблема открытых систем: там всё сводится к некоему общему знаменателю, по необходимости максимально тупому и примитивному.

Ты представляешь себе спагетти-код, смесь из вызовов маленьких сишных и лисповых функций, тогда так в гетерогенном софте код на одном языке вызывает обширный код на другом. Из Си в Лисп, с рестартами, MOP и прочим. А Лисп вообще сам дёргает сишный код, libpcap, там, всякий, и прочее - какая наглость!

Вобщем, всё это надуманные проблемы. Реальная проблема была - цена лицензии LW =)

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

Если у тебя объявлена такая функция, и фактически в коде применяется только к каким-нибудь double и rational,

Так в том-то и дело, что если в си-подобных языках есть только double и rational, а в Haskell вообще у значения может быть только один тип, то в Racket тип значения — любой тип, во множество значений которого попадает данное значение. Поэтому всё, что делает проверяльщик типов — заменяет все проверки, которые заведомо истинны, на истину. И если вызов подпадает под подстановку (inline), то оптимизация включиться автоматически.

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

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

У меня есть теория, что Земля круглая. Это как бы очевидная вещь, а проблема не в этой — проблема в том, что средний окрепший мозг в вакууме, который осилил лисп и решил «вкусить всю мощь», напишет лютейший говнокод, который потом кроме него никто не сможет прочитать... и даже он сам спустя пару лет, потому нынче он уже пишет код в другом, более кошерном стиле.

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

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

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

Питон с самого начала был подобием ранних лиспов. Он уже мог больше бейсика, уже мог строить эдикие мини-DSL-и. Там очень быстро в него начали тупо перетаскивать лисповые фичи, правда, «архитекторы» забыли продумать самый пустяк — как передать функцию аргументом другой функции.

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

И потому, наверное, половина индустрии теперь бэкэнды и просто сервисы пишет и переписывает на Go?

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

если голанговый миддлварь на гипервизоре занимает $20 памяти, $2 электричества в месяц и $50 в месяц недополученного ревеню за недопроданные виртуалки, то в масштабе 100к хостов это будут стартовые инвестиции в $2M на железо чисто под голанг, плюс операционные затраты $5.2M/месяц

Что это за продакшон такой лютый? Там вон пишут на питоне-руби, амазон и али на жаве, фейсбук компилирует свой пых — и им норм, а у тебя, видите ли, Go ресурсы жрет.

byko3y ★★★★
()
Ответ на: комментарий от no-such-file

ЛИСП никогда не использовался коннективистами (ну массово). ЛИСП это про символьный подход

А по-твоему в питоне дофига инструментов для «коннективистов»? Питон так-то чуть фичастее баша.

ЛИСП это закрытая система. К закрытой системе сложно что-то прикрутить сбоку. Тащить всё в себя в наше время не получится, слишком много всего. Поэтому другие закрытые системы, даже современные и продвигаемые тупо окукливаются в какой-то узкой нише (где есть интерес у спонсоров-продвигателей)

Чиво-о-о. Второй раз за тред я слышу от тебя какие-то абстракные обороты плана «лисп — это про справедливость и недвоевластие». Ты можешь как-то конкретнее выражаться? Коннективистов сюда приплел — еще бы с экзистенциалистами и бихевиористами связал.

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

Так же «фичи питона» «хорошо ложатся» на Си, позволяя дергать производительный код.

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

Уже есть генераторы биндингов для питона, которые позволяют дергать функции C/C++ с минимумом ручного кодописания.

А хаскель вообще идеально ложится

Не ложится по тем же причинам. Хотя отмечу, что из него С дергать проще, чем из питона

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

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

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

В некоторых реализация CL тоже.

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

А потому что общепринятые механизмы абстракции крестов чудовищно негибки

Какие?

Наследование же. То, с чего кресты начинали свое гниение в мире.

строки ты можешь иметь только такие, какие тебе дали.

А какие должны быть?

Логично, что они должны быть либо прибиты гвоздями к компилятору, аки Go, либо я должен иметь возможность хранить в компонентах Qt какой-нибудь UCS-4. Тем более, что стандартные крестовые строки это умеют. На наследование в Qt не оставляет шансов на переопределение работы с текстом.

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