Каков наилучший способ обеспечить определение определенных ценностей на аргументах сообщения в Smalltalk?
Вопрос
Я работаю над простой настольной игрой в Pharo, и у меня есть метод на моей доске, который добавляет объекты в клетку. Клетки - это просто словарь точек на объектах.
В рамках метода я хотел обеспечить применение того, что точка должна быть больше нуля, но меньше, чем ширина и высота доски, другими словами, на самом деле она должна быть на доске. Какой лучший способ сделать это?
Моя текущая попытка выглядит так:
at: aPoint put: aCell
((((aPoint x > self numberOfRows)
or: [aPoint x <= 0])
or: [aPoint y > self numberOfColumns ])
or: [aPoint y <= 0])
ifTrue: [ self error:'The point must be inside the grid.' ].
self cells at: aPoint put: aCell .
Вид Лисс-у со всеми этими парнами! Но я не могу использовать короткие замыкания or:
не закрывая каждое выражение, чтобы он оценивает как логический, а не блок (или как or:or:or:or:
сообщение). Я мог бы использовать двоичный оператор |
Вместо этого и для короткого замыкания, но это не кажется правильным.
Итак, какой правильно SmallTalk-ISH способ справиться с этим?
Решение
Как правило, or:
вложены так:
(aPoint x > self numberOfRows
or: [ aPoint x <= 0
or: [ aPoint y > self numberOfColumns
or: [ aPoint y <= 0 ] ] ])
ifTrue: [ self error: 'The point must be inside the grid.' ].
Ваше гнездование является краткосмысленным, но менее эффективным из-за повторных испытаний первого аргумента (проверьте байт-код, чтобы увидеть разницу).
Альтернатива вы можете использовать assert:
или assert:description:
это определено на Object
:
self
assert: (aPoint x > self numberOfRows
or: [ aPoint x <= 0
or: [ aPoint y > self numberOfColumns
or: [ aPoint y <= 0 ] ] ])
description: 'The point must be inside the grid.'
Другие советы
В любое время все время вложено, пришло время вызвать другой метод.
isValidPoint: aPoint
aPoint x > self numberOfRows ifTrue: [^ false].
aPoint x <= 0 ifTrue: [^ false].
aPoint y > self numberOfColumns ifTrue: [^ false].
aPoint y <= 0 ifTrue: [^ false].
^ true.
В общем, ваши методы должны быть относительно плоскими. Если нет, время рефактору.
Вы можете просто префилировать словарь «ячейки» со всеми точками, которые действительны в пределах диапазона, то есть где-то в инициализации вы поставили:
1 to: numberOfRows do: [:y |
1 to: numberOfCols do: [:x |
cells at: x@y put: dummy "or nil " ] ]
Тогда ваш способ добавления ячейки в данной точке будет выглядеть так просто, как:
at: aPoint put: aCell
self cells at: aPoint ifAbsent: [ self error: 'The point must be inside the grid.' ].
self cells at: aPoint put: aCell .
Есть также помощник метода #between: и:, который вы можете использовать для минимизации беспорядка кода:
((aPoint x between: 1 and: self numCols) and: [
aPoint y between: 1 and: self numRows ]) ifFalse: [ ... bummer ... ]