вторник, 26 января 2010 г.

[comp.prog] Новая конструкция across в языке Eiffel

Бертранд Мейер рассказал в своем блоге о новой конструкции across в языке Eiffel, которая выполняет роль цикла foreach, но не только.

Вот так теперь может записываться обход всех элементов контейнера:

across s as c loop print (c.item) end

А вот так подсчет суммы всех элементов контейнера:

across s as c from sum := 0 loop sum := sum + c.index * c.item end

Раньше нужно было писать так:

from
   sum := 0 ; s.start
until
   s.after
loop
   sum := sum + s.index * s.item
   s.forth
end

В качестве s может использоваться объект любого класса наследника ITERABLE. В качестве c будет использоваться объект того типа, который возвращает метод new_cursor объекта s. По умолчанию это тип ITERATION_CURSOR, но конкретный контейнер может использовать и наследников от этого класса.

Вот так можно обойти контейнер в обратном порядке:

across s.new_cursor.reversed as c loop print (c.item) end

Мейер говорит, что в Eiffel встраивается некоторая защита от модификации контейнера, по которому идет итерация посредством across. В этой защите каким-то образом задействовано постусловие и новое свойство контейнеров is_valid. Вроде бы, когда контейнер модифицируется, его свойство is_valid возвращает false вместо true и это останавливает цикл. Но как это реально работает я не понял, а сама новая версия библиотеки EiffelBase с поддержкой is_valid еще не готова.

Однако, самое интересное в across то, что эта конструкция может использоваться не только в качестве цикла, но и в качестве предиката. Например, выражение:

across s as c all c.item > 0 end

будет истинным только если все элементы контейнера s больше нуля. А выражение:

across s as c some c.item > 0 end

будет истинным если хотя бы один элемент контейнера s больше нуля.

Забавный все-таки язык Eiffel. И развивается забавно.

Отправить комментарий