Няколко полезни линка:
"You can convert a different class to a proc (if it supports it) by calling the to_proc method. If you use & on an object that is not a proc, Ruby will try to coerce that object into a block by calling the to_proc method."
"proc is a function that creates a new Proc object"
"If you put & in front of a Proc instance in the argument position, that will be interpreted as a block. If you combine something other than a Proc instance with &, then implicit class casting will try to convert that to a Proc instance using to_proc method defined on that object if there is any."
Подобни обяснения има и в Programming Ruby, която силно препоръчвам. :)
Иначе за да примера ти - ти подаваш на map-а символ :Kon, и руби "търси" такъв метод Kon, но няма такъв - ти имаш клас Кон -> следователно излиза и грешката "undefined method 'Kon' for 1:Fixnum". И ако искаш все пак да заработи, to_proc трябва да се извика на класа Kon -> [1,2,3].map(&Kon), следователно самият ти клас Kon трябва да има метод to_proc:
class Kon
def self.to_proc
Proc.new { |x| puts "obicham kone #{x}" }
end
end
Така на Kon се извиква to_proc, а не на инстация от Kon.
Резултатът е:
[1,2,3].map(&Kon)
obicham kone 1
obicham kone 2
obicham kone 3
# => [nil, nil, nil]
защото в крайна сметка блока за map-a принтира някакви неща и стойността на крайния израз е nil.
И за край - аз най-просто го разбирам така - to_proc кара нещо да се превърне/ да върне блок, за да може този блок да се използва от друг метод. Блокът, който връща to_proc, е логично да приема някакви стойности, да прави нещо с тях и да връща резултат - и отделно този блок пък го подаваме на пример на map. При Symbol така е имплементирано, че когато напишем:
&:метод, to_proc връща Proc, който приема обект obj, аргументи **args и на този обект му "изпраща" :метод - obj.send(:метод, **args)
ПП. чак сега видях, че си направил инстанция на Kon - moq_kon, тогава за да работи map-ът трябва само да напишеш:
[1,2,3].map(&moq_kon) и да не променяш to_proc в класа.