2016-07-15 2 views
2

Этот код:Visibilily в #inject: в: блок

((1 to: 10) 
    inject: (WriteStream on: String new) 
    into: [ :strm :each | 
     ((each rem: 3) = 0) 
      ifTrue: [ 
       strm 
        nextPutAll: each printString; 
        space; 
        yourself ]]) contents 

терпит неудачу, потому что strm не определено, где он используется в ifTrue: блоке. Почему там не видно?

Редактировать: Я попробовал это в VASt и Pharo.

+1

Какой диалект вы используете? Дельфин, VW, VA, Pharo, Squeak, GNU ... –

ответ

4

Проблема в том, что подразумеваемая ветка ifFalse: возвращает nil. Чтобы исправить это, попробуйте следующее:

((1 to: 10) 
    inject: (WriteStream on: String new) 
    into: [ :strm :each | 
     ((each rem: 3) = 0) 
      ifFalse: [strm] "This is needed to avoid nil being returned" 
      ifTrue: [ 
       strm 
        nextPutAll: each printString; 
        space; 
        yourself ]]) contents 
+0

Это работает, но я до сих пор не совсем понимаю. Нужно ли возвращать 'strm' в первом цикле (в блоке' ifFalse: ') для его« инициализации »? –

+0

Забудьте комментарий выше, я это понимаю. Я принял ваш ответ. –

4

В зависимости от диалекта (доступные методы), вы можете взять более короткий подход

((1 to: 10) select: [ :each | (each rem: 3) = 0 ]) joinUsing: ' ' 

Как правило thumb¹ любой collection do: [ :each | something ifTrue: [] ] может быть превращен в гораздо более прямолинейный и читаемый collection select: [] или collection reject: []

Выполнение этой задачи позволит разложить сложность по нескольким независимым шагам (1. фильтрация, 2. добавление в поток), вместо того, чтобы соединить все это вместе.

Или, если вы хотите, чтобы придерживаться оригинального

(((1 to: 10) select: [ :each | (each rem: 3) = 0 ]) 
    inject: (WriteStream on: String new) 
    into: [ :stream :each | 
     stream 
      nextPutAll: each printString; 
      space; 
      yourself ]) contents 

или

String streamContents: [ :stream | 
    (1 to: 10) 
     select: [ :each | (each rem: 3) = 0 ] 
     thenDo: [ :each | 
      stream 
       nextPutAll: each printString; 
       space 
     ] 
] 

¹So не всегда, но всегда хорошо иметь в виду, когда вы столкнулись с такой ситуацией.

+0

Вы совершенно верны. Этот образец был частью части реализации fizzbuzz. Я показывал коллегу, который нельзя свести к 'select:' или 'reject:'. –

Смежные вопросы