Re[5]: [Этюд]Макрос "or"
От: Mr.Cat  
Дата: 12.05.09 14:19
Оценка:
Здравствуйте, Кодт, Вы писали:
К>Зачем тогда отказались от лисповского nil? Чтобы не путать с пустым списком?
Я так понимаю, #f было введено как универсальное "пустое" значение, которое можно возвращать как признак ошибки/неудачи. Например, при поиске первого подходящего элемента в списке — как еще различить 2 случая "критерию не удовлетворяет ни один элемент" и "первым элементом, удовлетворяющим критерию, является пустой список"?

К>И тут же стали путать списки с #t.

Почему же путать? Для того, чтобы различать объекты разных типов, есть соответствующие предикаты: boolean?, list? и т.п. А if и логические операции различают только #f и "не #f".
Re[6]: [Этюд]Макрос "or"
От: Mr.Cat  
Дата: 12.05.09 17:25
Оценка:
Здравствуйте, Mr.Cat, Вы писали:
MC>Я так понимаю, #f было введено как универсальное "пустое" значение, которое можно возвращать как признак ошибки/неудачи.
Т.е. я хотел сказать, что пустой список Сассмана/whoever в роли такого значения почему-то не устраивал — потому и ввели новое.
Re[6]: [Этюд]Макрос "or"
От: Кодт Россия  
Дата: 12.05.09 23:01
Оценка:
Здравствуйте, Mr.Cat, Вы писали:

К>>Зачем тогда отказались от лисповского nil? Чтобы не путать с пустым списком?

MC>Я так понимаю, #f было введено как универсальное "пустое" значение, которое можно возвращать как признак ошибки/неудачи. Например, при поиске первого подходящего элемента в списке — как еще различить 2 случая "критерию не удовлетворяет ни один элемент" и "первым элементом, удовлетворяющим критерию, является пустой список"?

Хе, а если первым элементом, удовлетворяющим критерию, будет элемент "f#"?
Нет уж, тут нужен Maybe или нечто подобное.

Вспомнился анекдот.
— Скажи, как переводится с английского "I don't know"?
— "Я не знаю".
— Ну вот... никто не знает...

К>>И тут же стали путать списки с #t.

MC>Почему же путать? Для того, чтобы различать объекты разных типов, есть соответствующие предикаты: boolean?, list? и т.п. А if и логические операции различают только #f и "не #f".

Вот потому и путать: переменная или функция содержит список, а его истолковали как булевское значение. (Только в лиспе и в схеме эта трактовка различается).

В этом плане, скажем, питон дружественнее: там приведение к булю основано на смысле.
Ложью считаются
— нули всех числовых типов
— атом None (нулевой указатель)
— пустые контейнеры (списки, кортежи, строки, словари)

В лиспе смысл был примерно тот же, но он оказался замаскирован дурным минимализмом. То есть непонятно стало — то ли мы приравниваем "пусто" к "ложно", то ли тупо сэкономили на одном атоме (для "истина", однако, ввели атом t).
Перекуём баги на фичи!
Re[7]: [Этюд]Макрос "or"
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 13.05.09 02:53
Оценка: :)
Кодт,

К>Хе, а если первым элементом, удовлетворяющим критерию, будет элемент "f#"?

К>Нет уж, тут нужен Maybe или нечто подобное.

В реализации монад (гы-гы) на Схеме мне встретился даже такой изврат:
(define fail (vector 'fail))

Такое значение будет не eq? любому другому. Ну конечно до тех пор, пока кто-нибудь не переопределит eq? подходящим образом

К>Вспомнился анекдот.

К>- Скажи, как переводится с английского "I don't know"?
К>- "Я не знаю".
К>- Ну вот... никто не знает...

English variation:

(We take you now to the Oval Office.)
George: Condi! Nice to see you. What's happening?
Condi: Sir, I have the report here about the new leader of China.
George: Great. Lay it on me.
Condi: Hu is the new leader of China.
George: That's what I want to know.
Condi: That's what I'm telling you.
George: That's what I'm asking you. Who is the new leader of China?
Condi: Yes.
George: I mean the fellow's name.
Condi: Hu.
George: The guy in China.
Condi: Hu.
George: The new leader of China.
Condi: Hu.
George: The Chinaman!
Condi: Hu is leading China.
George: Now whaddya' asking me for?
Condi: I'm telling you Hu is leading China.
George: Well, I'm asking you. Who is leading China?
Condi: That's the man's name.
George: That's who's name?
Condi: Yes.
George: Will you or will you not tell me the name of the new leader of China?
Condi: Yes, sir.
George: Yassir? Yassir Arafat is in China? I thought he was in the Middle East.
Condi: That's correct.
George: Then who is in China?
Condi: Yes, sir.
George: Yassir is in China?
Condi: No, sir.
George: Then who is?
Condi: Yes, sir.
George: Yassir?
Condi: No, sir.
George: Look, Condi. I need to know the name of the new leader of China. Get me the Secretary General of the U.N. on the phone.
Condi: Kofi?
George: No, thanks.
Condi: You want Kofi?
George: No.
Condi: You don't want Kofi.
George: No. But now that you mention it, I could use a glass of milk. And then get me the U.N.
Condi: Yes, sir.
George: Not Yassir! The guy at the U.N.
Condi: Kofi?
George: Milk! Will you please make the call?
Condi: And call who?
George: Who is the guy at the U.N?
Condi: Hu is the guy in China.
George: Will you stay out of China?!
Condi: Yes, sir.
George: And stay out of the Middle East! Just get me the guy at the U.N.
Condi: Kofi.
George: All right! With cream and two sugars. Now get on the phone.
(Condi picks up the phone.)
Condi: Rice, here.
George: Rice? Good idea. And a couple of egg rolls, too. Maybe we should send some to the guy in China. And the Middle East. Can you get Chinese food in the Middle East?


К>>>И тут же стали путать списки с #t.

MC>>Почему же путать? Для того, чтобы различать объекты разных типов, есть соответствующие предикаты: boolean?, list? и т.п. А if и логические операции различают только #f и "не #f".

К>Вот потому и путать: переменная или функция содержит список, а его истолковали как булевское значение. (Только в лиспе и в схеме эта трактовка различается).


К>В этом плане, скажем, питон дружественнее: там приведение к булю основано на смысле.

К>Ложью считаются
К>- нули всех числовых типов
К>- атом None (нулевой указатель)
К>- пустые контейнеры (списки, кортежи, строки, словари)

К>В лиспе смысл был примерно тот же, но он оказался замаскирован дурным минимализмом. То есть непонятно стало — то ли мы приравниваем "пусто" к "ложно", то ли тупо сэкономили на одном атоме (для "истина", однако, ввели атом t).


Я категорически против того, чтобы считать пустой список за #f. Приведу пример: мы читаем из xml
  <UnreadMessages>
    <int>42292</int>
    <int>42298</int>
    <int>42300</int>
  </UnreadMessages>

и формируем список '(42292 42298 42300), если xml будет просто <UnreadMessages/>, то сформируется пустой список. В любом случае список на выходе — это сигнал о том, что чтение было успешно, а вот если чего-то обвалилось, то пожалуйста на этот счёт есть #f.
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[7]: [Этюд]Макрос "or"
От: Mr.Cat  
Дата: 13.05.09 06:57
Оценка:
Здравствуйте, Кодт, Вы писали:
К>Хе, а если первым элементом, удовлетворяющим критерию, будет элемент "f#"?
Ну вот почему-то Сассман (или кто там) решил, что #f можно сделать козлом отпущения.

К>Нет уж, тут нужен Maybe или нечто подобное.

Ну так пожалуйста — можно возвращать этот самый Maybe — пару "#t, значение", либо "#f, диагностика-ошибки". Но вот надо ли?

К>Вот потому и путать: переменная или функция содержит список, а его истолковали как булевское значение. (Только в лиспе и в схеме эта трактовка различается).

К>В этом плане, скажем, питон дружественнее: там приведение к булю основано на смысле.
Честно говоря, меня устраивают оба варианта.
Re[8]: [Этюд]Макрос "or"
От: Кодт Россия  
Дата: 13.05.09 12:38
Оценка:
Здравствуйте, Lazy Cjow Rhrr, Вы писали:

LCR>English variation:


Читал и хохотался!
Тупой доцент...
... << RSDN@Home 1.2.0 alpha 4 rev. 1207>>
Перекуём баги на фичи!
Re[8]: [Этюд]Макрос "or"
От: Кодт Россия  
Дата: 13.05.09 12:38
Оценка:
Здравствуйте, Lazy Cjow Rhrr, Вы писали:

К>>Нет уж, тут нужен Maybe или нечто подобное.


LCR>В реализации монад (гы-гы) на Схеме мне встретился даже такой изврат:

LCR>
LCR>(define fail (vector 'fail))
LCR>

LCR>Такое значение будет не eq? любому другому. Ну конечно до тех пор, пока кто-нибудь не переопределит eq? подходящим образом

И как его диагностировать? Типа, уж послала так послала?
Впрочем, элементарно-ватсон! Где-то недавно проскакивала тема — как проверять на равенство NaN, при том, что на нём равенство тоже сломано.
(define fail? (x) (not (eq? x x)))


LCR>Я категорически против того, чтобы считать пустой список за #f. Приведу пример: мы читаем из xml

LCR>
LCR>  <UnreadMessages>
LCR>    <int>42292</int>
LCR>    <int>42298</int>
LCR>    <int>42300</int>
LCR>  </UnreadMessages>
LCR>

LCR>и формируем список '(42292 42298 42300), если xml будет просто <UnreadMessages/>, то сформируется пустой список. В любом случае список на выходе — это сигнал о том, что чтение было успешно, а вот если чего-то обвалилось, то пожалуйста на этот счёт есть #f.

И снова Maybe. Не надо валить в одну кучу значения и сигналы.
По той же самой причине, если неаккуратно кодировать, можно нарваться на проблемы с русской буквой 'я' в Си.
char c;
while(true)
{
    c = getchar(); // прочитали символ либо признак конца/ошибки - int getchar(void)
    if(c == EOF) break; // EOF - это (int)-1
    printf("<%02X>", (unsigned char)c); // вывели в hex-формате, например
}

Правда, в Си возвращаемый тип заведомо шире и позволяет выразить и то и другое.

Что касается твоего списка, то напрашивается очень простой ответ. Нужно возвращать список списков.
<Messages><int>1</int><int>2</int></Messages>                      ---> '((1 2))
<Messages></Messages>                                              ---> '(())
<Messages><int>1</int></Messages><Messages><int>2</int></Messages> ---> '((1) (2)) - если это в принципе допустимо
пусто/облом                                                        ---> '()        - он же nil

Вполне себе maybe.
... << RSDN@Home 1.2.0 alpha 4 rev. 1207>>
Перекуём баги на фичи!
Re[9]: [Этюд]Макрос "or"
От: Mr.Cat  
Дата: 13.05.09 13:09
Оценка:
Здравствуйте, Кодт, Вы писали:
К>И как его диагностировать? Типа, уж послала так послала?
К>Впрочем, элементарно-ватсон! Где-то недавно проскакивала тема — как проверять на равенство NaN, при том, что на нём равенство тоже сломано.
К>
К>;(define fail? (x) (not (eq? x x)))
К>;


Да eq? (eqv? и equal?) по-моему, сломаны by design.

Например, в mzscheme оно вот так:
> (eq? +nan.0 +nan.0)
#t
> (= +nan.0 +nan.0)
#f


А в r6rs есть nan?.
Re[10]: [Этюд]Макрос "or"
От: Кодт Россия  
Дата: 13.05.09 13:57
Оценка:
Здравствуйте, Mr.Cat, Вы писали:

MC>Да eq? (eqv? и equal?) по-моему, сломаны by design.


Я не про nan, я про fail говорил. Если для fail не выполняется eq? сам себе, то... "если фортуна повернулась к вам задом, не расстраивайтесь, а воспользуйтесь".
... << RSDN@Home 1.2.0 alpha 4 rev. 1207>>
Перекуём баги на фичи!
Re[9]: [Этюд]Макрос "or"
От: z00n  
Дата: 13.05.09 16:19
Оценка:
Здравствуйте, Кодт, Вы писали:

К>И как его диагностировать? Типа, уж послала так послала?

К>Впрочем, элементарно-ватсон! Где-то недавно проскакивала тема — как проверять на равенство NaN, при том, что на нём равенство тоже сломано.
К>
К>;(define fail? (x) (not (eq? x x)))
К>;


А в чем проблема?
(define fail (vector 'fail))
(define (fail? x) (eq? x fail))

(fail? 'fail) ;; => #f
(fail? fail)  ;; => #t
Re[10]: [Этюд]Макрос "or"
От: z00n  
Дата: 13.05.09 16:23
Оценка:
Здравствуйте, z00n, Вы писали:

К>>И как его диагностировать? Типа, уж послала так послала?

Или диагностировать переопределенный eq? А надо?
Re[9]: [Этюд]Макрос "or"
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 14.05.09 05:18
Оценка:
Кодт,

К>Что касается твоего списка, то напрашивается очень простой ответ. Нужно возвращать список списков.

К>
К><Messages><int>1</int><int>2</int></Messages> ---> '((1 2))
К><Messages></Messages>                         ---> '(())
К><Messages><int>1</int></Messages>
К><Messages><int>2</int></Messages>             ---> '((1) (2)) - если это в принципе допустимо
К>пусто/облом                                   ---> '()        - он же nil
К>

К>Вполне себе maybe.

Ну конечно, ты решаешь проблему выше введением дополнительного слоя абстракции. Любую проблему можно так решить (за некоторым исключением). Просто получается чуть менее удобно — потом придётся выковыривать само значение:
(let ((l (parse xml))
      (if l
          (do-stuff-with l)
          (display "try again"))))

(let ((l (parse xml))
      (if l ; типа рассматривает пустой список как ложь
          (do-stuff-with (car l)) ; фи!
          (display "try again"))))

Хаскель спасает то, что такие слова как let, in, data и т.п. являются зарезервированными, и поэтому никто не может ничего изменить, и поэтому Maybe кажется таким незыблемым — Nothing — это Nothing, Just — это Just, и паттерн-матчинг работает как всегда работал. А вот в условиях "повышенной гибкости" ничего такого нет, поэтому любое предопределённое поведение можно изменить:
  (define if (lambda (x y z) 'omg))
  (display (if 1 2 3)) ; выведет omg

Следоветельно и любое определение Maybe не железобетонно. Конечно, никто специально не отстреливает себе выступающие части тела, переопределяя ради прикола стандартные формы, однако лисперам/схемерам нравится само существование возможности переопределить всё нахрен.
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[10]: [Этюд]Макрос "or"
От: Аноним  
Дата: 14.05.09 07:43
Оценка:
LCR>Хаскель спасает то, что такие слова как let, in, data и т.п. являются зарезервированными, и поэтому никто не может ничего изменить, и поэтому Maybe кажется таким незыблемым — Nothing — это Nothing, Just — это Just, и паттерн-матчинг работает как всегда работал. А вот в условиях "повышенной гибкости" ничего такого нет, поэтому любое предопределённое поведение можно изменить:
LCR>
LCR>;  (define if (lambda (x y z) 'omg))
LCR>;  (display (if 1 2 3)) ; выведет omg
LCR>;

LCR>Следоветельно и любое определение Maybe не железобетонно. Конечно, никто специально не отстреливает себе выступающие части тела, переопределяя ради прикола стандартные формы, однако лисперам/схемерам нравится само существование возможности переопределить всё нахрен.

Все несколько проще

(library (fail)
  (export fail? fail)
  (import (rnrs))
  
  (define fail '#(whatever))
  (define (fail? arg) (eq? fail arg)))

(import (rnrs) (fail))
(define newfail fail)
(list fail (fail? '#(whatever)) (fail? fail) (fail? newfail))
;=> (#(whatever) #f #t #t)

(define eq? 'got-ya)
(fail? fail)
;=> #t

; uncomment to have an exception
;(set! fail #f)

(set! newfail '#(whatever))
(fail? newfail)
;=> #f


Более того, совершенно неважно какими судьбами занесет этот fail в ваше окружение:
(library (fail)
  (export fail? fail)
  (import (rnrs))
  
  (define fail '#(whatever))
  (define (fail? arg) (eq? fail arg)))

(library (fail2)
  (export (rename (fail foo)))
  (import (only (fail) fail)))

(import (only (fail) fail?) (rename (fail2) (foo success)))
(fail? success)
;=> #t


Или даже так:
(import (fail) (rename (fail2) (foo success)))
(eq? fail success)
;=> #t
Re[11]: [Этюд]Макрос "or"
От: Mr.Cat  
Дата: 14.05.09 13:41
Оценка:
Здравствуйте, Аноним, Вы писали:
А>
А>;(library (fail)
А>;(define fail '#(whatever))
А>;


Еще можно для fail новый тип определить (раз уж пьянка с r6rs пошла):
(define-record-type (fail-type make-fail fail?))
(define fail (make-fail))

Чтобы fail на vector? не реагировал, например.
Re[12]: [Этюд]Макрос "or"
От: Аноним  
Дата: 14.05.09 18:23
Оценка:
Здравствуйте, Mr.Cat, Вы писали:

MC>Еще можно для fail новый тип определить (раз уж пьянка с r6rs пошла):

MC>
MC>;(define-record-type (fail-type make-fail fail?))
MC>;(define fail (make-fail))
MC>;

MC>Чтобы fail на vector? не реагировал, например.

Согласен, distinct-тип для "константы" fail — это гораздо правильнее. Я просто пытался писать в контексте предыдущих определений
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.