2016-07-16 9 views
0

Вот что я делаю прямо сейчас, что в настоящее время работает, но я чувствую это немного не хватает в синтаксическое ...Можно ли отдельно объявить параметры блока элемента массива, который передается в блок для метода впрыска?

f = RGeo::Geos.factory 
coords = [ [1,1], [2,2], [1,3] ] 
points = coords.inject([]) {|points, coord| points << f.point(coord[0], coord[1]); points } 
#=> [#<RGeo::Geos::CAPIPointImpl:0x3fff0950a508 "POINT (1.0 1.0)">, #<RGeo::Geos::CAPIPointImpl:0x3fff0950a47c "POINT (2.0 2.0)">, #<RGeo::Geos::CAPIPointImpl:0x3fff0950a454 "POINT (1.0 3.0)">] 

Вот что я хотел бы сделать:

points = coords.inject([]) {|points, x, y| points << f.point(x,y); points } 
#=> [nil, nil, nil] 

Прямо сейчас, когда возвращается массив из трех значений nil. Можно ли объявлять значения массива элемента, передаваемого в блок инъекции, отдельно, как это возможно с каждым методом?

Боковое примечание: Можно использовать одно и то же имя переменной для первого параметра блока впрыска (переменная «результат») и переменная с левой стороны знака равенства, правильно? Я думаю, да, потому что это будет типичный случай рекурсии. Прокомментируйте, если вы чувствуете или знаете иначе.

+0

почему 'inject', это выглядит как «карта»? –

+0

Я полагаю, вы правы. Я наверняка задумался над этим. –

ответ

1

Это будет делать трюк:

points = coords.inject([]) {|points, (x, y)| points << f.point(x,y); points } 

Это работает, как правило, в любом блоке; если один из параметров блока представляет собой массив из n элементов, вы можете захватить эти элементы, используя n имен переменных в скобках. Если вы используете больше, чем имена параметров п в скобках, массовка будет ноль:

[[1,2,3],[4,5]].map {|(a,b,c)| "#{a}+#{b}+#{c.inspect}" } #=> ["1+2+3", "4+5+nil"] 

Если вы используете слишком мало, имена параметров, остальные будут отброшены:

[[1,2,3],[4,5]].map {|(a,b)| "#{a}+#{b}" } #=> ["1+2", "4+5"] 

Вы можете использовать оператор восклицательный знак, чтобы захватить, остаток вместо этого, так же, как с обычными аргументами:

[[1,2,3],[4,5]].map {|(a,*b)| "#{a}+#{b}" } #=> ["1+[2, 3]", "4+[5]"] 

Вы можете даже гнездо:

[[1,2,[3,4]],[5,6,[7,8]]].map {|(a,b,(c,d))| a+b+c+d } #=> [10, 26] 

Ум, вложенный в него, может быть довольно запутанным, поэтому используйте его экономно.

Также обратите внимание, что те, внешняя скобка не являются, строго говоря, необходимо в приведенных выше примерах, но они меняют поведение, когда только один аргумент берутся из массива:

# Makes no difference 
[[1,2,3],[4,5,6]].map {| a,b,c | "#{a}+#{b}+#{c}" } #=> ["1+2+3", "4+5+6"] 
[[1,2,3],[4,5,6]].map {|(a,b,c)| "#{a}+#{b}+#{c}" } #=> ["1+2+3", "4+5+6"] 

# Makes a big difference 
[[1,2,3],[4,5,6]].map {| a | a } #=> [[1, 2, 3], [4, 5, 6]] 
[[1,2,3],[4,5,6]].map {|(a)| a } #=> [1, 4] 
+0

Вау! Мне нравится, как я продолжаю больше узнавать о синтаксических возможностях Ruby даже после 4 лет работы с ним –