Селектор timesRepeat:
хочет блок в качестве аргумента. Вы вызываете это с выражением в скобках:
10 timesRepeat: (a even ifTrue: b ifFalse: c).
Однако так получилось, что c
определен как блок [a := a - 2. b]
, который возвращает значение b
, и это оказывается блоком. Таким образом, timesRepeat:
счастлив, и он выполняет блок b
на каждой итерации, в которой a
нечетно. Если вы напишите это правильно, как:
10 timesRepeat: [a even ifTrue: b ifFalse: c].
Тогда в конце a
будет -19, как и ожидалось.
Относительно вашего утверждения: если мое понимание блоков правильное, последний элемент блока возвращается вместо оцененного , на самом деле это не так. Для последнего оператора в блоке нет специальной обработки, кроме того, что его результат действительно возвращается как значение блока при выполнении этого блока. Ваш последний оператор в блоке - это просто имя переменной. Значение переменной просто является блоком, но независимо от того, что это, просто наличие имени переменной в качестве оператора в Smalltalk просто возвращает значение переменной. Если переменная окажется блоком, вы получите блок. Блок не выполнен.
Рассмотрим следующие блоки:
[a := 1. b := 2. c := a+b]
Когда этот блок выполняется, тогда a
будет иметь значение 1, b
значение 2, а c
значение 3. Значение, которое будет возвращать блок, равно значению c
, которое 3.
[a := 1. b := 2. a]
Если вы выполните этот блок, результатом будет значение a
, которое равно 1.
[a := 1. b := 2. c := [a+b]. c]
Если вы выполните этот блок, результатом будет блок, который представляет переменная c
. Он не выполняет блок c
. Это согласуется с предыдущим примером.
Итак, когда вы выполняете блок, [Transcript show: 'I am called!'. jkl].
, jkl
в конце не выполняется. Это значение только что вернулось. Если вы хотите выполнить его, вы можете написать asdf := [Transcript show: 'I am called!'. jkl value].
Блок будет выполняться при отправке сообщения value
. Результат выполнения блока [Transcript show: 'I am called!'. jkl value].
будет результатом выполнения блока jkl
.