Здравствуйте, VladD2, Вы писали:
VD>Хорошо вам. А я для этой цели по старинке водку да коньяк использую. А они денег стоят.
Коньяк с водкой и с утра? Плохо Неиерле на тебя повлиял
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Programmierer AG,
PA>С твоей интерпретацией функции mark я не согласен: это всегда один шаг в
PA>пространстве решений, откатов тут нет. Тупиковые ветви дерева решений
PA>отфильтруются потом: ...
Прежде чем ответить, я тоже должен разобрать по кусочкам этот шедевр.
PA>Кстати, еще один впечатляющий пример представления данных в виде функции
PA>(это к вопросу: "Хм, интересная идея. А в чём преимущество по сравнению
PA>с представлением области с помощью АТД?").
Угу, буду смотреть.
Здравствуйте, Andrei N.Sobchuck, Вы писали:
ANS>Коньяк с водкой и с утра? Плохо Неиерле на тебя повлиял
Это старая русская привычка. Способ создать себе выходной.
Звучит она так. С утра выпил — весь день свободен.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Здравствуйте, Зверёк Харьковский, Вы писали:
ЗХ>Демонстрирует: передачу функции как параметра, ее хранение в переменной, паттерн-матчинг.
Видимо я не совсем догоняю смысл этого кода. Поясни по подробнее.
Это, кстати, был Руби?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Здравствуйте, VladD2, Вы писали:
ЗХ>>Демонстрирует: передачу функции как параметра, ее хранение в переменной, паттерн-матчинг.
VD>Это, кстати, был Руби?
Ya.
VD>Видимо я не совсем догоняю смысл этого кода. Поясни по подробнее.
В Руби блоки (лямбды) определяются вот так:
#это мы определили переменную-лямбду
l = lambda{|param1, param2, param3| code}
#а это мы определяем блок переданный в функцию myfoo
myfoo(param1, param2){|block_param1, block_param2| code}
#другой вариант того же синтаксиса:
myfoo(param1, param2) do |block_param1, block_param2| code end
#или даже так:
myfoo param1, param2 do |block_param1, block_param2| code end
#пример использования на реальной библиотечной функции:
arr = [1,2,3,4]
print arr.sort{|left, right| right <=> left} #задаем лямбду сравнивающую значения
#этот код выведет [4, 3, 2, 1]
#функция, одним из параметров которой является лямбда, может выглядеть так:
def sort #неявный параметр-блок не указывается...
...
result = yield(left, right) #...и вызывается yield'ом
...
end
#а может выглядеть так:
#параметр-блок указывается явно, на то, что он должен быть блоком, указывает &
def sort(&block)
...
some_variable = block #блок теперь обычная переменная, его можно хранить, передавать, возвращать...
block.call(a,b,c) #ну и вызывать, конечно.
...
end
Пока понятно? Теперь, на основе этого, расшифровываем мои записи:
#есть объект widget
#его функция on_key_press вызывается с параметром-блоком; у блока есть параметры key, shifts
widget.on_key_press{|key, shifts| ...}
#сама функция on_key_press может выглядеть так:
class Widget
def on_key_press(*arg, &handler)
#* перед arg - оператор свертки, функция может принять любое количество аргументов
#и все они окажутся в массиве arg
#в данной функции arg представляют собой паттерн, которому должно соответствовать событие
#чтобы оно было отдиспатчено в handler
#сохраняем обработчик в хеш:
@handlers_hash[arg] = handler
end
#а вот что происходит где-то внутри window_proc:
def window_proc(message_params)
@handlers_hash.each do |key, value|
message_params.match(key){|*match_res| value.call(*match_res) }
end
end
end
Вот эта строчка:
message_params.match(key){|*match_res| value.call(*match_res) }
выполняет паттерн-матчинг на паттерне-фильтре события; если матчинг успешен, выполяняет блок, с передачей ему результатов матчинга.
#например, если мы установили такой обработчик:
widget.on_key_press(Key::A){|shifts| ...}
#то где-то в window_proc он будет вызыван, только в случае если нажата клавиша A
#и любое сочетание Alt, Ctrl, Shift; при этом сочетание "шифтов" будет передано в блок.
Примерно понятно?