Автор | Сообщение |
joba
157 сообщений |
#5615 2012-01-28 06:03 GMT+3 часа(ов) |
Очень не хватает сабжа. Например, в схеме нельзя так делать:
(define bar (map foo)) (define (f x y) (+ x y)) Приходится писать так: (define (bar lst) (map foo lst)) (define (f x y) (+ x y)) И было бы хорошо, если бы каждая функция была на самом деле функцией от одного аргумента:
А приходится писать так: (define (foo x) (lambda (y) (lambda (z) (* x y z)))) Я понимаю, что можно сделать костыль, чтобы это все работало, но лучше уж тогда создать свой диалект с нуля. И еще, кстати говоря, мне не нравится, что строки реализованы не в виде списков символов. Нет чтоб сделать как в haskell. Собственно вопрос, какие есть разумные причины существования данного безобразия в лиспах? отредактировал(а) joba: 2012-01-28 06:14 GMT+3 часа(ов) |
|
joba
157 сообщений |
#5616 2012-01-28 06:22 GMT+3 часа(ов) |
И еще меня вот эта вот наркоманская фигня бесит в cl:
* (car nil)Еле сдерживаю рвотные позывы. |
|
Kergan
300 сообщений |
#5617 2012-01-28 14:24 GMT+3 часа(ов) |
> Собственно вопрос, какие есть разумные причины существования данного безобразия в лиспах?
Отсутствие статической типизации. Без нее неясно, что значит (map foo) - частичное применение или полную аппликацию. |
|
misha![]()
1275 сообщений |
#5619 2012-01-28 21:40 GMT+3 часа(ов) |
($define ($map f a) (map f a)) |
|
joba
157 сообщений |
#5620 2012-01-28 21:59 GMT+3 часа(ов) |
>Отсутствие статической типизации. Без нее неясно, что значит (map foo) - частичное применение или полную аппликацию.
Причем тут статическая типизация? Кому не ясно? Интерпретатору не ясно? Очень даже ясно. |
|
joba
157 сообщений |
#5621 2012-01-28 22:18 GMT+3 часа(ов) |
2 misha
Что это? Пример работы костыля? Как костыль написать я и сам знаю. >(define (1+ a) (+ a 1)) Лучше (define 1+ (sum2 1)), где sum2 - бинарная операция сложения. |
|
misha![]()
1275 сообщений |
#5622 2012-01-28 23:09 GMT+3 часа(ов) |
> Как костыль написать я и сам знаю.
Не сомневаюсь ![]() > Лучше (define 1+ (sum2 1)), где sum2 - бинарная операция сложения. ($define (sum2 a b) (+ a b)) |
|
joba
157 сообщений |
#5624 2012-01-28 23:50 GMT+3 часа(ов) |
Единственная причина (которую я не считаю разумной), которую я вижу, - это то, что если мы делаем в языке возможными частичные аппликации, то тогда нам придется отказаться от функций с переменным числом аргументов. Но это не создает больших проблем, потому что можно передавать список как аргумент (именно поэтому я и не считаю эту причину разумной).
Например, ;sum : (List Number) -> Numberгде под fold1 я подразумеваю левостороннюю свертку, которая принимает только один список. |
|
misha![]()
1275 сообщений |
#5625 2012-01-29 01:06 GMT+3 часа(ов) |
Можно обойтись и без свертки
($collect sum2 1 2 3 4 5) ; => 15 А нужна ли поддержка переменного числа аргументов? ($collect sum2 1 2 3 4 5) => |
|
joba
157 сообщений |
#5627 2012-01-29 02:21 GMT+3 часа(ов) |
Нет, никаких $collect быть не должно в языке. Я хочу чтоб было так:
(-> t1 t) ;контракт для лямбда-абстракции ниже (t1, t - контракты) И да, я это уже все реализовал (кроме контрактов), но суть треда не в этом. |
|
Kergan
300 сообщений |
#5628 2012-01-29 21:18 GMT+3 часа(ов) |
Цитата Ни интерпретатору, ни компилятору Цитата Хорошо, ты видишь форму (f x) скажи, что это - аппликация или частичное применение? И это не говоря уже обо всяких (+ х). Цитата Если компилятору известно, что f : (-> t1 t2 t3 t), то ЯП статически типизрован, ты в курсе? Y-комбинатор в таком лиспе, кстати, ты написать уже не сможешь. отредактировал(а) Kergan: 2012-01-29 21:26 GMT+3 часа(ов) |
|
joba
157 сообщений |
#5629 2012-01-30 02:48 GMT+3 часа(ов) |
>Хорошо, ты видишь форму (f x) скажи, что это - аппликация или частичное применение?
Смотря что из себя представляет f. |
|
Kergan
300 сообщений |
#5630 2012-01-30 11:47 GMT+3 часа(ов) |
> Смотря что из себя представляет f.
А компилятор не знает, что из себя представляет f. И узнать никак не может. (lambda (g f) (f 1)), например. Неизвестно же, что будет передано потом в эту лямбду. |
|
joba
157 сообщений |
#5631 2012-01-30 20:38 GMT+3 часа(ов) |
Ну вот когда будет передано, тогда и узнает. Нам же не надо вычислять тело лямбды до того, как будет уточнен ее аргумент. И, кстати, я говорил про интерпретатор, а не компилятор. И я уже написал этот интерпретатор, а ты мне говоришь, что это невозможно. Весело бля.
|
|
Kergan
300 сообщений |
#5632 2012-01-30 21:39 GMT+3 часа(ов) |
Цитата Но ведь в рантайме это будет медленно? Решил потестить реализацию на case-lambda в Racket - забавные результаты:
это код, соответственно:
все работает. А теперь тесты:
Короче, инлайнинг байткода в racket - это нечто! Ладно, второй вариант совпадает с первым (понятно, что компилятор просто подставил нужную форму), но во третьем случае даже лямбда при частичном применении в (g i) не создавалась! Он и ее раскрыл и заинлайнил на ходу ![]() Вырубаем инлайнинг:
Теперь уже лямбда создается. Можно обратить внимание - вторйо вариант быстрее первого, т.к. + так же определяется в виде case-lambda, но там больше кейзов (для rest аргумента). для сравнения вариант с "чистым" сложением:
Так что, однако, не так уж и плохо все - везде, где можно, компилятор-таки умудряется оптимизировать до максимальной производительности (как буд-то функция вычисляется "напрямую"), а когда оптимизировать не выходит - просадка вполне разумна. Я думал, будет гораздо хуже, а так оно даже вполне юзабельным выходит, так что беру свои слова обратно на счет невозможности. |
|
misha![]()
1275 сообщений |
#5633 2012-01-31 00:45 GMT+3 часа(ов) |
2Kergan
Какой смысл в "(let ([curried ...]) curried)", его ведь упразднит оптимизатор? > но во третьем случае даже лямбда при частичном применении в (g i) не создавалась! Он и ее раскрыл и заинлайнил на ходу Это неудивительно, если учесть, что функция объявлена в модуле, а не в рантайме. А также она ни разу не переопределялась. (time (for ([i 10000000]) (+ i i)))cpu time: 1109 real time: 1110 gc time: 0 cpu time: 1375 real time: 1375 gc time: 0 cpu time: 1922 real time: 1953 gc time: 62 ************************************************** cpu time: 1187 real time: 1234 gc time: 0 cpu time: 1547 real time: 1547 gc time: 0 cpu time: 2063 real time: 2188 gc time: 61 отредактировал(а) misha: 2012-01-31 01:00 GMT+3 часа(ов) |
|
Kergan
300 сообщений |
#5635 2012-01-31 06:56 GMT+3 часа(ов) |
Цитата у функции будет имя <curried> тогда, а не <procedure module line-number column-number>. Вообще, там по-хорошему должно быть что-то типа <curried-name module line-number column-number> (это все для отладки), но мне было лень, оставил так ![]() Хотя вообще можно inferred-name и напрямую в синтаксический объект для лямбды добавить. Цитата у тебя, видимо, инлайнинг и так вырублен. отредактировал(а) Kergan: 2012-01-31 07:20 GMT+3 часа(ов) |
|
misha![]()
1275 сообщений |
#5636 2012-01-31 15:10 GMT+3 часа(ов) |
> у тебя, видимо, инлайнинг и так вырублен.
Компилятор учитывает наличие переопределения (set! g g), поэтому не производит инлайнинг функции. Это возможно, ведь в рэкете модуль компилируется целиком, а не по частям (как в лиспе), поэтому возможен предпросмотр и продвинутые оптимизации. ($define (g x y) (+ x y)) cpu time: 1109 real time: 1109 gc time: 0 cpu time: 1125 real time: 1125 gc time: 0 cpu time: 1110 real time: 1110 gc time: 0 |
|
Kergan
300 сообщений |
#5641 2012-01-31 18:14 GMT+3 часа(ов) |
Цитата ну да, все правильно, мне просто почему-то показалось, что он не должен инлайнить только после set!. Кстати, в какой-то из последних версий добавили cross-module инлайнинг. |
|
misha![]()
1275 сообщений |
#5657 2012-02-03 13:53 GMT+3 часа(ов) |
> Кстати, в какой-то из последних версий добавили cross-module инлайнинг.
Не в курсе. |
|
joba
157 сообщений |
#5659 2012-02-03 17:01 GMT+3 часа(ов) |
Есть идея создать такой диалект лиспа (правда от лиспа там останется только синтаксис - s-выражения): смесь идей из kernel (первоклассность всего и вся), racket (контракты, модульность, pattern matching), haskell (строки в виде списков символов, частичное применение, встроенное каррирование, ленивые вычисления (я не имею в виду те костыли, что в scheme), вывод "типов" (в нашем случае контрактов), чистота (через монады или что-нибудь похожее)). Может еще что-нибудь. Потом, возможно, создам отельную тему, когда реализую это все, если, конечно, это кому-то будет интересно.
|
|
misha![]()
1275 сообщений |
#5668 2012-02-04 00:09 GMT+3 часа(ов) |
Если тебе он нужен, то можешь реализовать. А так... есть Shen
(1+) + |
|
joba
157 сообщений |
#5670 2012-02-04 02:37 GMT+3 часа(ов) |
Shen отвратителен. Во-первых, он статически типизированный. И при этом хуже haskell по всем параметрам => на фиг не нужен.
Во-вторых, pattern matching убогий, он такой не нужен из коробки. В-третьих, синтаксис довольно далек от чистого s-expressions. Т.е. грязь. Должны быть в основе либо чистые s-выражения, либо что-то типа навороченного хаскелльного синтаксиса. Что-то промежуточное, совмещающее и то и другое понемножку - бессмысленное убожество. В-четвертых, костыльное call-by-need, как в scheme. В-пятых, есть макросы - не первоклассные объекты. В-шестых, в eval нельзя передать окружение. В-седьмых, есть строки как базовый тип объектов - лишняя сущность. Короче, этот Shen вдоль и поперек сплошное говно. |
|
joba
157 сообщений |
#5671 2012-02-04 03:20 GMT+3 часа(ов) |
Кстати, если кто-то подумал, что поддержка всех фич, которые я перечислил в Сообщение #5659, предполагает статическую типизацию, то он дурак. Весь checking будет производиться в рантайме. Вывод "типов" тоже. Декларации вида (: name contract), которые должны делаться до (define name val), не обязательны. Сhecking будет опциональным, он нужен только на этапе разработки, в готовом продукте он не нужен.
|
|
Kergan
300 сообщений |
#5673 2012-02-04 08:39 GMT+3 часа(ов) |
Цитата в чем именно проявляется первоклассность kernel по сравнению с другими диалектами? |
|
joba
157 сообщений |
#5674 2012-02-04 11:39 GMT+3 часа(ов) |
misha![]()
1275 сообщений |
#5675 2012-02-04 14:11 GMT+3 часа(ов) |
> Во-первых, он статически типизированный.
Это настраиваемая в рантайме опция. Да и типизация больше похожа на контракты. Кстати, хорошо бы и тебе подобное прикрутить. > Во-вторых, pattern matching убогий, он такой не нужен из коробки. Для игрушечного языка вполне нормальный. Реализуешь лучше? > В-третьих, синтаксис довольно далек от чистого s-expressions. Обоснуй. > В-четвертых, костыльное call-by-need, как в scheme. Значит производительность тебя не волнует. > В-пятых, есть макросы - не первоклассные объекты. Разделение пространств имен - это правильный шаг. > В-шестых, в eval нельзя передать окружение. А зачем? Eval использует текущее пространство имен. > В-седьмых, есть строки как базовый тип объектов - лишняя сущность. Обоснуй. |
|
Kergan
300 сообщений |
#5676 2012-02-04 15:13 GMT+3 часа(ов) |
Цитата За тем, чтобы можно было исполнять формы в любом окружении (возможно, только что созданном в рантайме). Цитата ну например в определении факториала твоем не проставлены скобки вокруг "0 -> 1" и "N -> (* N (factorial (- N 1)))" , которые должны там быть. |
|
misha![]()
1275 сообщений |
#5677 2012-02-04 15:21 GMT+3 часа(ов) |
> За тем, чтобы можно было исполнять формы в любом окружении (возможно, только что созданном в рантайме).
Ну так в чем проблема? ![]() > ну например в определении факториала твоем не проставлены скобки define - это ридер-макрос, т.е. ридер преобразует его в s-выражение. P.S. Shen - это конструктор лего. |
|
Kergan
300 сообщений |
#5678 2012-02-04 15:24 GMT+3 часа(ов) |
Цитата а примеры есть какие-нибудь? Типа "вот так можно в кернел и нельзя в других лиспах". |
|