Короткий базар
От: Кодт Россия  
Дата: 14.11.09 22:49
Оценка: 23 (2) :)))
SmallTalk — скуп на слова как де Ниро, с ним спорит только больной...
Взглянем, например, на методы класса Boolean
and: alternativeBlock 
    self subclassResponsibility

and: block1 and: block2
    self ifFalse: [^ false].
    block1 value ifFalse: [^ false].
    block2 value ifFalse: [^ false].
    ^ true

and: block1 and: block2 and: block3
    self ifFalse: [^ false].
    block1 value ifFalse: [^ false].
    block2 value ifFalse: [^ false].
    block3 value ifFalse: [^ false].
    ^ true

and: block1 and: block2 and: block3 and: block4
    self ifFalse: [^ false].
    block1 value ifFalse: [^ false].
    block2 value ifFalse: [^ false].
    block3 value ifFalse: [^ false].
    block4 value ifFalse: [^ false].
    ^ true

На 4-арном and (и то же самое для or!) действие наркотика контрол-вэ у авторов иссякло, и они всосали следующую дорожку
ifTrue: alternativeBlock 
    self subclassResponsibility

ifFalse: alternativeBlock 
    self subclassResponsibility

fTrue: trueAlternativeBlock ifFalse: falseAlternativeBlock
    self subclassResponsibility

ifFalse: falseAlternativeBlock ifTrue: trueAlternativeBlock 
    "Same as ifTrue:ifFalse:."
    self subclassResponsibility

Не забываем, что булевы константы True и False — это субклассы, конкретизирующие поведение вышеупомянутых методов... Поэтому авторы сбегали к цыганам (точнее, к их суперклассу — к индусам) за новой порцией.

Вот такой лаокооничный синтаксис

(Если что — тырил эту прекрасность из реализации Pharo, которая является ответвлением Squeak. Возможно, у IBM Visualage сделано изящнее).

P.S. Возопиил в связи с тем, что "Язык Objective-C позволяет снабжать метками каждый аргумент, что заметно повышает читаемость кода и снижает вероятность передачи неправильного параметра."
Перекуём баги на фичи!
Re: Короткий базар
От: Буравчик Россия  
Дата: 14.11.09 23:48
Оценка:
Здравствуйте, Кодт, Вы писали:

К>SmallTalk — скуп на слова как де Ниро, с ним спорит только больной...

К>Взглянем, например, на методы класса Boolean
К>
К>and: alternativeBlock 
К>    self subclassResponsibility

К>and: block1 and: block2 and: block3 and: block4
К>    self ifFalse: [^ false].
К>    block1 value ifFalse: [^ false].
К>    block2 value ifFalse: [^ false].
К>    block3 value ifFalse: [^ false].
К>    block4 value ifFalse: [^ false].
К>    ^ true
К>

К>На 4-арном and (и то же самое для or!) действие наркотика контрол-вэ у авторов иссякло, и они всосали следующую дорожку

Это всего лишь сахар, дабы не плодить лишних скобок. Основная операция and:
"это равносильно and: and: and:
(((aBoolean and: [...]) and: [...]) and: [...])


К тому же, при необходимости, можно легко добавить недостающие методы (and: and: and: and: and.

К>
К>ifTrue: alternativeBlock 
К>    self subclassResponsibility

К>ifFalse: alternativeBlock 
К>    self subclassResponsibility

К>fTrue: trueAlternativeBlock ifFalse: falseAlternativeBlock
К>    self subclassResponsibility

К>ifFalse: falseAlternativeBlock ifTrue: trueAlternativeBlock 
К>    "Same as ifTrue:ifFalse:."
К>    self subclassResponsibility
К>


Можно оставить только ifTrue: (аналог if) и ifTrue:ifFalse: (аналог if else).
ifFalse и ifFalse:ifTrue — сахар.

К>Не забываем, что булевы константы True и False — это субклассы, конкретизирующие поведение вышеупомянутых методов... Поэтому авторы сбегали к цыганам (точнее, к их суперклассу — к индусам) за новой порцией.


Ну так. Чистый-чистый ООП. Идеология языка, однако.

К>Вот такой лаокооничный синтаксис


К>(Если что — тырил эту прекрасность из реализации Pharo, которая является ответвлением Squeak. Возможно, у IBM Visualage сделано изящнее).


В VisualWorks есть только and: . В целом, согласен. Есть у Smalltalk проблемы с переменным количеством аргументов. Но если хочется поругать этот красивый язык, то ругать его надо все же не за это. Да и наезд на ifTrue ifFalse — не понятен.

К>P.S. Возопиил в связи с тем, что "Язык Objective-C позволяет снабжать метками каждый аргумент, что заметно повышает читаемость кода и снижает вероятность передачи неправильного параметра."


Вывод-то какой? По-моему, в Objective-C пришлось бы делать то же самое. Хотя, могу ошибаться.
Best regards, Буравчик
Re[2]: Короткий базар
От: Кодт Россия  
Дата: 15.11.09 09:17
Оценка:
Здравствуйте, Буравчик, Вы писали:

Б>Это всего лишь сахар, дабы не плодить лишних скобок. Основная операция and:

По-моему, они пересластили.
Конечно, основная операция — унарный receiver and:block1.
Но тут фигня в том, что авторы накопипастили кучу сигнатур, вместо того, чтобы позволить пользователю выражать всё через одну.
Вот у чисел есть единственное x *y, а не x *y *z *t
Возможно, это была битва против правой ассоциативности, т.к.
a and: b or: c and: d разбивается на (a and: (b or: (c and: d)))
И, соответственно, без мега-сигнатур с одними and было бы
(a and: (b and: (c and: d (and: (e and: f)))))
а с мега-сигнатурами — вот тут нужно уточнить, жадный ли компилятор
(a and: b and: c and: d and: (e and: f))
или ленивый
(a and: (b and: c and: d and: e and: f))
Вроде бы жадный...

Б>К тому же, при необходимости, можно легко добавить недостающие методы (and: and: and: and: and.

Куда легко добавить? В стандартную библиотеку?!
Ну я понимаю, что смолток-среда является песочницей, и у себя в песочнице можно творить всё, что хочешь.
Например, пропатчить стандартные классы.
Можно даже на боярский язык перевести, ибо:, вотще:, еслиЧо:, еслиНичо: — но непоймут-с!

Б>Можно оставить только ifTrue: (аналог if) и ifTrue:ifFalse: (аналог if else).

Б>ifFalse и ifFalse:ifTrue — сахар.

Конечно, можно. Я, вообще, удивился, почему они сделали всё на откуп в субклассы. Может, ради производительности?

Б>В VisualWorks есть только and: . В целом, согласен. Есть у Smalltalk проблемы с переменным количеством аргументов. Но если хочется поругать этот красивый язык, то ругать его надо все же не за это. Да и наезд на ifTrue ifFalse — не понятен.


У смолтока проблемы не с переменным, а с множеством аргументов. Из-за того, что пользователь может захотеть послать сообщение, начиная с произвольного ярлыка, приходится рожать кучу сигнатур. Ну там setWidth:height: и setHeight:width: и т.п. То есть, выбрав вот такой синтаксис, обрекли себя на многословие (и вошли в диссонанс с самоназванием).
Хотя есть языки, поддерживающие именованные параметры. Даже лисп.

А с учётом того, что все методы виртуальные, придётся договариваться — что подлежит переопределению в субклассе, а что является шаблонным методом (в случае с Boolean — and:and:and: — шаблон, and: переопределяется).

К>>P.S. Возопиил в связи с тем, что "Язык Objective-C позволяет снабжать метками каждый аргумент, что заметно повышает читаемость кода и снижает вероятность передачи неправильного параметра."


Б>Вывод-то какой? По-моему, в Objective-C пришлось бы делать то же самое. Хотя, могу ошибаться.

Именно этот вывод. Тяжёлое наследие.

Я бы в С++ офигел вводить методы setWidthHeight(w,h) и setHeightWidth(h,w)
Перекуём баги на фичи!
Re[3]: Короткий базар
От: Буравчик Россия  
Дата: 15.11.09 10:55
Оценка:
Здравствуйте, Кодт, Вы писали:

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

К>Вот у чисел есть единственное x *y, а не x *y *z *t

У Boolean есть еще один незамеченный тобой селектор, а именно &. Он ведет себя так же как *.
aBool1 & aBool2 & aBool3 ...


К>Возможно, это была битва против правой ассоциативности, т.к.

К>a and: b or: c and: d разбивается на (a and: (b or: (c and: d)))
К>И, соответственно, без мега-сигнатур с одними and было бы
К>(a and: (b and: (c and: d (and: (e and: f)))))

Нет. Оно разбивается не так. В выражении (a and: b or: c and: d) объекту a посылается сообщение (and: or: and: ). Т.е. все эти имена с двоеточиями считаются частью одного и того же сообщения.

К>а с мега-сигнатурами — вот тут нужно уточнить, жадный ли компилятор

К>(a and: b and: c and: d and: (e and: f))
К>или ленивый
К>(a and: (b and: c and: d and: e and: f))
К>Вроде бы жадный...

Компилятор жадный. Основная операция для логического И является "&". Там вычисляются все выражения.
А вот для ленивости добавили and: и пр. Значения вычисляются при необходимости.

Именно поэтому в & передается параметр Boolean, а в and: передается Block.

К>Куда легко добавить? В стандартную библиотеку?!

К>Ну я понимаю, что смолток-среда является песочницей, и у себя в песочнице можно творить всё, что хочешь.
К>Например, пропатчить стандартные классы.

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

К>Можно даже на боярский язык перевести, ибо:, вотще:, еслиЧо:, еслиНичо: — но непоймут-с!


Согласен, не поймут. Но and: and: and: and: and: and: поймут.

Б>>Можно оставить только ifTrue: (аналог if) и ifTrue:ifFalse: (аналог if else).

Б>>ifFalse и ifFalse:ifTrue — сахар.

К>Конечно, можно. Я, вообще, удивился, почему они сделали всё на откуп в субклассы. Может, ради производительности?


Скорее, ради чистоты языка. Нет ключевых слов boolean, true, false. Есть лишь классы (Boolean, True, False) и объекты (true, false).

К>У смолтока проблемы не с переменным, а с множеством аргументов. Из-за того, что пользователь может захотеть послать сообщение, начиная с произвольного ярлыка, приходится рожать кучу сигнатур. Ну там setWidth:height: и setHeight:width: и т.п. То есть, выбрав вот такой синтаксис, обрекли себя на многословие (и вошли в диссонанс с самоназванием).


Да, я имел виду множество аргументов. Ну нет именованных параметров в smalltalk, ну и что — это обходится, не усложняя язык.

К>Хотя есть языки, поддерживающие именованные параметры. Даже лисп.


И куча языков их не поддерживающих. Тот же haskell.

К>А с учётом того, что все методы виртуальные, придётся договариваться — что подлежит переопределению в субклассе, а что является шаблонным методом (в случае с Boolean — and:and:and: — шаблон, and: переопределяется).


Кому договариваться? Создатели библиотеки и сами все знают. А если мы сами чего-нибудь не переопределим то получим ошибку #errSubclassResponsibility ('My subclass should have overridden one of my messages.'). Ошибка генерируется в методе subclassResponsibility. Т.е. если мы переопределим метод and: то будет вызван метод субкласса. Если нет, то будет вызван subclassResponsibility, который уведомит об ошибке.

К>Я бы в С++ офигел вводить методы setWidthHeight(w,h) и setHeightWidth(h,w)

Я не понимаю...

// C++
a.setWidthHeight(w,h);

"smalltalk"
a.setWidth: height.


// C++
a.setWidth(w);
a.setHeight(h);

"smalltalk"
a setWidth: w.
a setHeight: h.

"smalltalk - посылка нескольких сообщений одному объекту" 
a setWidth: w;
  setHeight: h.


А вообще, методы типа ifFalse: ifTrue: — это удобно, поэтому и добавили.
// C++
if(!wrongMessage)
  ...
else
  ...

"smalltalk" 
wrongMessage ifFalse: [...]
             ifTrue: [...]


То же и с whileTrue и whileFalse.
Best regards, Буравчик
Re[4]: Короткий базар
От: Кодт Россия  
Дата: 15.11.09 20:35
Оценка:
Здравствуйте, Буравчик, Вы писали:

Б>У Boolean есть еще один незамеченный тобой селектор, а именно &. Он ведет себя так же как *.

Не то чтоб незамеченный... просто удивило, что есть and:and:and:and:

Б>Нет. Оно разбивается не так. В выражении (a and: b or: c and: d) объекту a посылается сообщение (and: or: and: ). Т.е. все эти имена с двоеточиями считаются частью одного и того же сообщения.


Житие-мое паки херувимы. То есть, без вариантов, придётся писать
((a and: [^b] and: [^c] and: [^d]) and: [^e] and: [^f] and: [^g] and: [^h])
и расставлять скобки.

Б>Компилятор жадный. Основная операция для логического И является "&". Там вычисляются все выражения.

Б>А вот для ленивости добавили and: и пр. Значения вычисляются при необходимости.
Б>Именно поэтому в & передается параметр Boolean, а в and: передается Block.

Да, вот эту тонкость не просёк...

Б>>>Можно оставить только ifTrue: (аналог if) и ifTrue:ifFalse: (аналог if else).

Б>>>ifFalse и ifFalse:ifTrue — сахар.

К>>Конечно, можно. Я, вообще, удивился, почему они сделали всё на откуп в субклассы. Может, ради производительности?


Б>Скорее, ради чистоты языка. Нет ключевых слов boolean, true, false. Есть лишь классы (Boolean, True, False) и объекты (true, false).


Чистота языка — это понятно. Я имел в виду, что они отдали на откуп не только базис (определив все производные в суперклассе, по паттерну "шаблонный метод"), а именно всё.
Таким образом, false ifFalse:ifTrue:
— находится в словаре текущего класса False, а не где-то в суперклассе Boolean
— не требует выполнения Boolean ifFalse:ifTrue: реализованного через ifTrue:ifFalse: — которое требует опять поиска, передачи параметров, возвращения...
Для часто используемых данных может получиться выигрыш.

К>>Я бы в С++ офигел вводить методы setWidthHeight(w,h) и setHeightWidth(h,w)

Б>Я не понимаю...

Не, сделать 4 функции вместо 3 (setWidth:, setHeight:, setWidth:height: и вдруг setHeight:width) можно и на С++, и на Smalltalk. Просто из-за подмены именованных параметров многословными сообщениями возникает повод делать эту лишнюю функцию.
Перекуём баги на фичи!
Re[5]: Короткий базар
От: Буравчик Россия  
Дата: 15.11.09 23:50
Оценка: 62 (1)
Здравствуйте, Кодт, Вы писали:

К>Житие-мое паки херувимы. То есть, без вариантов, придётся писать

К>((a and: [^b] and: [^c] and: [^d]) and: [^e] and: [^f] and: [^g] and: [^h])
К>и расставлять скобки.

Да скобки иногда нужны. Иногда даже очень. Все-таки потомок Лиспа

В Smalltalk последнее значение выражения в блоке, является значением самого блока.
Поэтому правильно записать выражение нужно без ^
((a and: [b] and: [c] and: [d]) and: [e] and: [f] and: [g] and: [h])

Более того, т.к. ^ равносильно return, то вариант с ^ может привести к ошибкам:
(true and: [^true]) and: [^false] выдаст true вместо желаемого false.
Это происходит из-за того, что при выполнении блока [^true] происходит return true.
Вычисление выражения прерывается и не доходит до and: [^false]

К>Чистота языка — это понятно. Я имел в виду, что они отдали на откуп не только базис (определив все производные в суперклассе, по паттерну "шаблонный метод"), а именно всё.

К>Таким образом, false ifFalse:ifTrue:
К>- находится в словаре текущего класса False, а не где-то в суперклассе Boolean
К>- не требует выполнения Boolean ifFalse:ifTrue: реализованного через ifTrue:ifFalse: — которое требует опять поиска, передачи параметров, возвращения...
К>Для часто используемых данных может получиться выигрыш.

Похоже на правду...

Кстати, возвращаясь к теме. Я так понимаю, речь шла о том, что Smalltalk не соответсвует своему названию

Судя по некоторым источникам, язык и не задумывался как краткий. Он задумывался как простой (для детей). И этого Алан Кей добился. Вот нашел немного о причинах, почему язык назван именно так:

In the summer of '71 I refined the KiddiKomp idea into a tighter design called miniCOM. It used a bit-slice approach like the NOVA 1200, had a bit-map display, a pointing device, a choice of "secondary" (really tertiary) storages, and a language I now called "Smalltalk"--as in "programming should be a matter of ..." and "children should program in ...". The name was also a reaction against the "IndoEuropean god theory" where systems were named Zeus, Odin, and Thor, and hardly did anything. I figured that "Smalltalk" was so innocuous a label that if it ever did anything nice people would be pleasantly surprised.


The name actually appeared before the first Smalltalk design, which was done in 1971. I had mentioned to someone that the "prose" of then current programming languages was lower than a cocktail party conversation, and that great progress would have been made if we could even get to the level of making "smalltalk". It then occured to me that this word was also a great pun for a language aimed at the world of small children.


http://wiki.squeak.org/squeak/50
http://www.encyklopedia.narod.ru/bios/nauka/kay/kay.html
http://gagne.homedns.org/~tgagne/contrib/EarlyHistoryST.html
Best regards, Буравчик
Re[6]: Короткий базар
От: Кодт Россия  
Дата: 16.11.09 00:31
Оценка:
Здравствуйте, Буравчик, Вы писали:

Б>Более того, т.к. ^ равносильно return, то вариант с ^ может привести к ошибкам:

Б>(true and: [^true]) and: [^false] выдаст true вместо желаемого false.
Б>Это происходит из-за того, что при выполнении блока [^true] происходит return true.
Б>Вычисление выражения прерывается и не доходит до and: [^false]

То есть, ^ действует на уровне метода, а не на уровне блока?

А блок является полноценным замыканием, кстати?
plusXX: x
  |y|
  y := x*x.
  ^ [:z| y+z]

Открываем для себя ещё один ФЯ!
Перекуём баги на фичи!
Re[7]: Короткий базар
От: Буравчик Россия  
Дата: 16.11.09 11:49
Оценка:
Здравствуйте, Кодт, Вы писали:

К>То есть, ^ действует на уровне метода, а не на уровне блока?


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

method
  cond1 ifTrue: [^...].
  cond2 ifTrue: [^...].
  ^calculate


Но бывают случаи, когда имеются некоторые проблемы. Выше я уже приводил пример. И вот еще об этом:
http://c2.com/cgi/wiki?SmalltalkBlockReturn
http://smalltalk.gnu.org/blog/s11001001/lexical-block-return-language-crux

К>А блок является полноценным замыканием, кстати?


Да.

К>Открываем для себя ещё один ФЯ!


И это одна из причин его выразительности. А может и самая главная причина.
Best regards, Буравчик
Re: Короткий базар
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 16.11.09 15:54
Оценка:
Здравствуйте, Кодт, Вы писали:


К>(Если что — тырил эту прекрасность из реализации Pharo, которая является ответвлением Squeak. Возможно, у IBM Visualage сделано изящнее).


Имхо, изящнее сделать невозможно если оставаться в рамках концепции, что всё выражается через отправку сообщений. Как уже заметили
Автор: Буравчик
Дата: 15.11.09
, из-за необходимости lazy вычесления аргументов в "Boolean AND".

При этом, в "stock squeak" используется много "&" и "|". А #and: и #or: — редко. Вполне возможно, что из-за синтаксической сложности. А если учесть, что большая часть Squeak написана не профессиональными программистами, то синтаксический сложность и непонимание разницы lazy-eager вычисления параметров вполне может быть причиной. Случаи, когда используется "&" или "|" последовательно или когда используется многоарный #and: можно пересчитать по пальцах (но они есть).

Есть и еще один момент. Например, #ifTrue:ifFalse: используется всего 8 раз. Из них 2 — для имплементации методов #ifEmpty:ifNotEmptyDo: и #ifEmpty:ifNotEmpty:
То есть, зачастую принято добавлять свои методы контроля потока управления. Среди них, например:
#ifNil: который заменяет "anObject isNil ifTrue:" и т.д.
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
smalltalk
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.