Не забываем, что булевы константы True и False — это субклассы, конкретизирующие поведение вышеупомянутых методов... Поэтому авторы сбегали к цыганам (точнее, к их суперклассу — к индусам) за новой порцией.
Вот такой лаокооничный синтаксис
(Если что — тырил эту прекрасность из реализации Pharo, которая является ответвлением Squeak. Возможно, у IBM Visualage сделано изящнее).
P.S. Возопиил в связи с тем, что "Язык Objective-C позволяет снабжать метками каждый аргумент, что заметно повышает читаемость кода и снижает вероятность передачи неправильного параметра."
Здравствуйте, Кодт, Вы писали:
К>SmallTalk — скуп на слова как де Ниро, с ним спорит только больной... К>Взглянем, например, на методы класса Boolean К>
Можно оставить только 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 пришлось бы делать то же самое. Хотя, могу ошибаться.
Здравствуйте, Буравчик, Вы писали:
Б>Это всего лишь сахар, дабы не плодить лишних скобок. Основная операция 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)
Здравствуйте, Кодт, Вы писали:
К>Но тут фигня в том, что авторы накопипастили кучу сигнатур, вместо того, чтобы позволить пользователю выражать всё через одну. К>Вот у чисел есть единственное 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: — это удобно, поэтому и добавили.
Здравствуйте, Буравчик, Вы писали:
Б>У 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. Просто из-за подмены именованных параметров многословными сообщениями возникает повод делать эту лишнюю функцию.
Здравствуйте, Кодт, Вы писали:
К>Житие-мое паки херувимы. То есть, без вариантов, придётся писать К>((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.
Здравствуйте, Буравчик, Вы писали:
Б>Более того, т.к. ^ равносильно return, то вариант с ^ может привести к ошибкам: Б>(true and: [^true]) and: [^false] выдаст true вместо желаемого false. Б>Это происходит из-за того, что при выполнении блока [^true] происходит return true. Б>Вычисление выражения прерывается и не доходит до and: [^false]
То есть, ^ действует на уровне метода, а не на уровне блока?
Здравствуйте, Кодт, Вы писали:
К>То есть, ^ действует на уровне метода, а не на уровне блока?
Да. Если встречается возврат из блока, то он выходит не только из блока, но и из метода в котором определен блок.
Возврат из блока обычно встречается при использовании управляющих конструкций и обычно проблем не вызывает:
, из-за необходимости lazy вычесления аргументов в "Boolean AND".
При этом, в "stock squeak" используется много "&" и "|". А #and: и #or: — редко. Вполне возможно, что из-за синтаксической сложности. А если учесть, что большая часть Squeak написана не профессиональными программистами, то синтаксический сложность и непонимание разницы lazy-eager вычисления параметров вполне может быть причиной. Случаи, когда используется "&" или "|" последовательно или когда используется многоарный #and: можно пересчитать по пальцах (но они есть).
Есть и еще один момент. Например, #ifTrue:ifFalse: используется всего 8 раз. Из них 2 — для имплементации методов #ifEmpty:ifNotEmptyDo: и #ifEmpty:ifNotEmpty:
То есть, зачастую принято добавлять свои методы контроля потока управления. Среди них, например:
#ifNil: который заменяет "anObject isNil ifTrue:" и т.д.