Smalltalk: в чем разница между «

#smalltalk #pharo

Вопрос:

Я только начал изучать Smalltalk в университете.

Я хотел бы знать разницу между сообщениями amp; и and: (так же, как | и or: )

Ответ №1:

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

Сообщение » amp; «является» двоичным » сообщением, поэтому принимает только один аргумент. В этом случае ожидается, что аргумент будет логическим или выражением, которое вычисляется как логическое. Самое главное для наших целей в этом сравнении, что выражение всегда будет оцениваться.

Сообщение «и:» является сообщением «ключевого слова» и также принимает только один аргумент. Но в этом случае ожидается, что аргументом будет блок, который, если позже отправить сообщение «значение», вернет логическое значение. Таким образом, для наших целей в этом сравнении Блок не всегда будет оцениваться. (Разница между двоичными сообщениями и сообщениями с ключевыми словами не имеет значения для этого вопроса.)

Возможность не оценивать аргумент позволяет выполнить оценку короткого замыкания, при которой знание левой стороны часто позволяет нам избежать (возможно, дорогостоящего) вычисления правой стороны. Таким образом, если левый («приемник») является ложным, нет ничего, что можно было бы получить, оценив правую сторону.

Итак, рассмотрим следующее:

 self cheapFalse amp; self expensiveTrue. "an expensive way to get false"
self cheapFalse and: [self expensiveTrue]. "a cheap way to get false"
 

Ответ №2:

Одно очевидное отличие заключается в том, что and: это сообщение с ключевым словом, поэтому вы можете написать что-то вроде

 a > b and: [b < c]
 

в то время как с amp; вами понадобились бы круглые скобки в этом выражении:

 a > b amp; (b < c)
 

потому что все двоичные сообщения ( , - , , > , < , amp; , | ) имеют одинаковый приоритет.

Что еще более важно, and: и or: ожидайте блоков, в то время amp; как и | ожидайте значений. Это означает, что вы можете писать

 this shouldRedraw and: [ obj stateChanged ]
 

где obj stateChanged будет выполнено, только если this shouldRedraw верно. Это полезно, если вы хотите оптимизировать свой код и избежать вычислений, которые в данный момент не нужны.

Комментарии:

1. Вы должны поставить «б Кроме того, shouldCompute следует изменить на shouldRedraw .

2. Привет @JamesFoster, большое вам спасибо за просмотр моего ответа!!

3. Обратите внимание, что ничто не препятствует передаче блока в двоичное сообщение на языке (при желании вы можете создать двоичное сообщение, в котором ожидается аргумент блока). Это просто соглашение, используемое в библиотеке ядра.