LINUX.ORG.RU

Трагедия CommonLisp

 ,


0

3

https://esdiscuss.org/topic/the-tragedy-of-the-common-lisp-or-why-large-langu...

Для Ъ не будет.

Кратко суть:

Once a language gets beyond a certain complexity --- say LaTeX, Common Lisp, C++, PL/1, modern Java --- the experience of programming in it is more like carving out a subset of features for one's personal use out of what seems like an infinite sea of features, most of which we become resigned to never learning. Once a language feels infinite, the specific benefits of a new feature are still apparent. But the general costs in added complexity are no longer apparent. They are no longer felt by those discussing the new feature. Infinity + 1 === Infinity. Even aLargeNumber + 1 === approximatelyAsLargeANumber. This is the death of a thousand cuts that causes these monstrosities to grow without bound.


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

Ты бы видел, ЧТО НАМ ПРИСЫЛАЛИ!!!

Даже интересно стало, вот пример:

void trimRight(char* s) {
    char* p = 0;
    while( *s )
        p = isspace(*s++) ? p : s;

    *(p?p:s) = 0;
}

Он достаточно ужасен, чтоб меня не взяли в DrWeb?

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

C++ templates

Это аналог лисповых макросов? Чего-то не достаточно?

yield

Это продолжения и сопрограммы. Да в CL с этим слабость, хотя есть cl-cont. Мне эти функции не особо нужны, т.к. для меня рантайм CL - лаборатория для экспериментов и анализа. Тебе не кажется, что подобные инструменты плохо влияют на читаемость кода и эффективнее их заменять более многословными эквивалентами?

Во всяком случае я говорил о лиспе к которому относятся схема и ракета. Там вроде с этим норма.

linq

Это встроенный SQL с бьющим по пальцам компилятором? Существуют аналогичные библиотеки.

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

Статическая типизация всего и вся?

В CL типы можно декларировать. Ещё существуют специальные лиспы повёрнутые на этом.

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

Не работает на строке из одних пробелов. Достаточно.

А ты знатный проверяльщик. Все там работает.

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

Подсказка - если одни пробелы, то p == 0, и в конце *s = 0, делает строку пустой. Вот такие вот «профи» и принимают на работу.

anonymous
()
Ответ на: комментарий от anonymous
Mikhails-MacBook-Pro:fuck mikhail$ cat trimRight.c
#include <stdio.h>
#include <ctype.h>
#include <string.h>
void trimRight(char*c);
int main() {
char *t = "     ";
char s[50];
strcpy(s, t);
trimRight(s);
printf(">%s<\n", s);
return 0;
}

void trimRight(char* s) {
    char* p = 0;
    while( *s )
        p = isspace(*s++) ? p : s;

    *(p?p:s) = 0;
}
Mikhails-MacBook-Pro:fuck mikhail$ gcc -o trimRight trimRight.c 
Mikhails-MacBook-Pro:fuck mikhail$ ./trimRight 
>     <

Не учи батьку детей делать.

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

и в конце *s = 0, делает строку пустой

Подсказка: в конце s — это не тот s, который был в начале. Чайник фигов.

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

Что не значит? Проверка типов есть. Оптимизация памяти есть. Возникающий компилятор есть. Интроспекция есть. Я конечно о sbcl говорю. Зачем статическая типизация ещё нужна?

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

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

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

Подсказка: в конце s — это не тот s, который был в начале. Чайник фигов.

Да я и без тебя догадался.

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

Что не значит?

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

Кстати, в нормальных статически типизированных языках очень многие аннотации типов можно не писать.

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

Не волнуйся, мы получали ГОРАЗДО худшие варианты. Мой любимый — когда после компиляции мы не нашли скомпилированного файла.

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

не то место, куда стремятся таланты.

Иными словами, создание ПО на илитарном коде требует особого местоположения. Для страны с 50млн населением таковых нет. Для нормальных языков всё есть, а для илитарный - нет. ЧТД.

и вообще я уже давно свалил.

Громкий хохот в зале. Это ты себя так забавно к «талантам» причислил?

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

Я не зря сказал, что Си выиграл борьбу за умы.

Ну с этим спорить смысла нет, только не уверен, что дело (только) в сложности.

DarkEld3r ★★★★★
()
Последнее исправление: DarkEld3r (всего исправлений: 1)

Кратко суть

This is the death of a thousand cuts that causes these monstrosities to grow without bound.

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

общелисп тоже такое же.

все в практичный и минималистичный лисп, посоны.

anonymous
()

сколько было пафоса в названии, а приведенный текст - так, пшик просто.

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

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

Критерий идиота.

loz ★★★★★
()

По сабжу на HN уже обсудили все, автор мудак и не осилил.

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

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

я и сам в это не верю

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

Это аналог лисповых макросов? Чего-то не достаточно?

Разумеется. Даже из простейшего

template <typename T> class Array<T> {
...
}

template <> class Array<bool> {
... // здесь оптимизированный bit-vector
}

как сделать на Lisp?

Или надо, чтобы объект хранился на диске, а по первому обращению читался. В С++:

template <typename T, typename Reader> class Proxy<T> {
   T* real = 0;
   string code;
   Proxy(_code) : code(_code) {}
   T* operator* () {
       if(!real)
         real = Reader::read();
       return real;
   };
   T& operator-> () {
       if(!real)
         real = Reader::read();
       return *real;
   }   
}

В лиспе приходится к такому объекту постоянно обращаться через акцессор.

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

как сделать на Lisp?

На дженериках, не?

В лиспе приходится к такому объекту постоянно обращаться через акцессор

А в крестах через 2 аксессора, понятно.

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

На дженериках

Дженерики научились параметризовать классы?

Поясняю. В С++

a = new Array<bool>;
b = new Array<int>;

a.length() // вызывается специализированный
b.length() // вызывается общий

В Lisp, чтобы (length a) и (length b) давали разный код, необходимо, чтобы a и b имели разные классы. Можно, конечно, на макросах сделать свой new, который будет делать defclass, но возникает проблема с именованием этих классов. Ведь классы могут быть Array<int>, Array<Array<int> >, Array<map<int, map<string, int> > >, ...

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

в крестах через 2 аксессора

Угу, невидимых.

a = new MyClass;
c = new Proxy<MyClass, FromFile>("data");

a->MyMethod();
a->myField;

c->MyMethod1();
c->MyField;

А в Lisp:

(defvar *a* (make-instance 'my-class))
(defvar *c* (make-instance 'proxy :class 'my-class :by 'from-file :from "data"))

(my-method *a*)
(slot-value *a* 'my-field)

(my-method (get *c*))
(slot-value (get *c*) 'my-field)

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

я говорил о лиспе к которому относятся схема и ракета

Ну если так, то я согласен.

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

Same here. Недавно был прецедент после сборки libpng. Они ныкают готовые бинарники в .lib на кой-то чёрт.

Только мне заголовок кажется бессмысленно пафосным? Первая ассоциация была почему-то с «Die Geburt der Tragödie» Ницше.

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

необходимо, чтобы a и b имели разные классы

В крестах тоже, Array<bool> и Array<int> разные классы.

но возникает проблема с именованием этих классов

array-int и array-bool, в чём проблема?

Угу, невидимых

А что -> уже не видно?

А в Lisp

Сахарок

(defun -> ((obj proxy) slot) (slot-value (get obj) slot))
(-> *c* 'my-field)

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

Только мне заголовок кажется бессмысленно пафосным?

Просто ТС способен испытывать тяжелейшие душевные муки из-за компьютера. Он ноу-лайфер

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

ЩИТО? Как так?

Мы тоже поначалу не поняли.

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

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

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

Сахарок

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

array-int и array-bool, в чём проблема

В необходимости делать отдельный defclass на каждый make-instance. + постоянная вероятность коллизии имён. Так как ArrayInt и Array<Int> должны бы быть разными классами, а при переписывании в CL они станут оба ArrayInt.

Ещё можно вспомнить перегрузку функций. Когда в C++ можно просто писать print(int x), print(int x, int y), print(bool x), print(string fmt, ...), а в лиспе придётся выдумывать по отдельному имени на каждый тип. Ну или саму функцию делать в виде typecase или generic generic нельзя, так как разное число аргументов.

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

Антивири параноидальные пошли. У меня зарубает вот это:

RemoveSpaces PROC
	;Backup base pointer register
	push ebp	;save ebp register
	mov ebp, esp	;put stack pointer into ebp
	;Save registers before we begin
	pusha
	mov eax, [ebp+8];at ebp+8 we have input string
	mov ecx, [ebp+8]
	;First, determine the length of the string
	xor bl, bl ; this will be used when we need to compare with zero
	mov bh, ' ' ; this will be used when we compare with space
	LengthLoopStart:
		cmp [eax], bl ; compare current byte with zero
		je LengthLoopEnd ; end loop if zero is found
		inc eax ; go to next byte in input string
		jmp LengthLoopStart
	LengthLoopEnd:
	dec eax ; decrement ecx because for now it points to zero
	;Now start from the end and compare character with space
	;If it is space, replace the character with zero
	SearchLoop:
	cmp [eax], bh ; if(strInput[i] == ' ')
	je SpaceFound
	jmp TheEnd ; jump to the end if current character is not space
	SpaceFound:
		mov [eax], bl ; strInput[i] = 0;
		dec eax ; i--
		cmp eax, ecx ; i >= 0
		jl TheEnd
		jmp SearchLoop
	TheEnd:
	;Restore registers
	popa
	;Restore base pointer
	pop ebp
	ret
RemoveSpaces ENDP
Хотя штука-то вроде безобидная:
>RemoveSpaces
>9546713820  9   0    <
>9546713820  9   0<

>RemoveSpaces
>       <
><
Аллергия на быдлокод у них, видимо.

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

У меня лисп в довольно нагруженном продакшне для одной интерконторы из СШП имеется. На ем писаны всякие кастомные правила проверки-выдачи кредитов / flows / и тп. херня ради которой кодировать класики или там городить конфиги XML не комильфо. Все остальное - на донетах.

Однако, в данном сраче неудвачников с прагматиками меня ни разу не тянет подиспутировать на тему места лишпов в природе.

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

Ты бы видел, ЧТО НАМ ПРИСЫЛАЛИ!!!

Да лан, я однажды пачку румынов собеседовал, просил площадь прямоугольного треугольника найти...
Ты бы видел, ЧТО НАМ ОТВЕЧАЛИ!!!

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

я говорил о лиспе к которому относятся схема и ракета.

а тред про коммон лисп, вообще-то

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

Но отсутствие этого сахарка не позволяет использовать прокси-класс вместо ожидаемого класса

Так и в крестах нельзя пихнуть прокси вместо ожидаемого объекта. Только если делать прокси как декоратор т.е. «делать наследование от класса-реализации и переписывать все методы».

метод может появится позже в произвольном пакете, всё совсем грустно

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

В необходимости делать отдельный defclass на каждый make-instance. + постоянная вероятность коллизии имён

Зачем? Во-первых достаточно замутить макрос defarray, который будет штамповать классы, также как это в крестах делает шаблон. Во-вторых если array<bool> имеет отдельную реализацию, то она и в крестах будет отдельной. Не пойму, в чём проблема-то?

Ещё можно вспомнить перегрузку функций

А можно и не вспоминать, т.к. вообще-то print(int x) и print(int x, int y) делают только мудаки - это нарушает полиморфизм.

typecase или generic generic нельзя, так как разное число аргументов

Это ещё почему? typecase пофиг, сколько там аргументов у функции, т.к. это полностью ручное управление, дженерикам тоже без разницы, ну будет у тебя 2,3,4 и т.д. дженерика на каждый вариант количества аргументов, ну и что? Зоопарк функций в крестах при перегрузке тебя почему-то не смущает.

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

т.к. вообще-то print(int x) и print(int x, int y) делают только мудаки - это нарушает полиморфизм.

Почему?

«делать наследование от класса-реализации и переписывать все методы».

Я не знаю как в лиспе, но в плюсах, при наследовании, все методы переопределять не надо.

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

Я не знаю как в лиспе, но в плюсах, при наследовании, все методы переопределять не надо

Речь идёт о декораторе, и там, в общем случае, может возникнуть такая необходимость.

Почему?

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

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

Ну да. Он прислал полноценную программу, компилирующуюся в экзешник, но начиналась она с int main (char *String).

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

Лично тебе я бы выслал споры сибирской язвы.

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

вообще-то print(int x) и print(int x, int y) делают только мудаки - это нарушает полиморфизм

Например, error в Racket. А ещё можешь поискать по слову &optional в CLHS.

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

Так и в крестах нельзя пихнуть прокси вместо ожидаемого объекта

Да ладно!

int f(MyClass *x) { ... }

c = new Proxy<MyClass, FromFile>("data");
f(c);

замечательно работает.

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

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

То есть ты тоже считаешь, что возможность доопределять методы класса в CLOS — вредная?

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

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

Сами пропёрлись, а виноват кандидат.

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