Каков наилучший способ обеспечить определение определенных ценностей на аргументах сообщения в Smalltalk?

StackOverflow https://stackoverflow.com/questions/4413860

  •  08-10-2019
  •  | 
  •  

Вопрос

Я работаю над простой настольной игрой в 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 ... ]
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top