/ / Разбиране `array.map (&: метод)` [дубликат] - рубин, символ

Разбиране на `array.map (&: метод)` [дубликат] - рубин, символ

Защо:

[1,2,3,4,5].map(&:to_s) #=> ["1", "2", "3", "4", "5"]

работа, но:

[1,2,3,4,5].map(&:*(2))

хвърля неочаквана синтактична грешка?

Отговори:

3 за отговор № 1

& се нарича to_proc оператор. Той нарича to_proc метод на израза, който го следва и след това предава получения Proc на метода като блок.

В случай че &:to_s, :to_s е символ, така че операторът призовава Symbol#to_proc, Документите са малко объркани, но е достатъчно да се каже, че тези два израза са повече или по-малко еквивалентни:

my_proc = :to_s.to_proc
my_proc = Proc.new {|obj| obj.to_s }

Така че отговорът на въпроса "Защо не &:*(2) работа "? е, че изразът, който следва & оператор, :*(2), не е валиден израз на Ruby.Това прави толкова смисъл за Ruby parser като "hello"(2).

Между другото, има начин да направите това, което се опитвате да направите:

[1,2,3,4,5].map(&2.method(:*))
# => [2, 4, 6, 8, 10]

В горния код, 2.method(:*) се връща препратка към * метод на обекта 2 като метод обект. Предметите на метода се държат много като Proc обекти и отговарят на тях to_proc, Въпреки това, горното не е точно еквивалентно - това е така 2 * n отколкото n * 2 (разлика, че няма значение дали n също е числено) и не е по-кратко и разбираемо от това {|n| n * 2 }, и рядко си струва неприятностите.


-1 за отговор № 2

Ampersand и обект (&: метод)

Операторът & също може да се използва за пренасяне на обект като блок на метод, както е показано в следния пример:

arr = [ 1, 2, 3, 4, 5 ]

arr.map { |n| n.to_s }
arr.map &:to_s

И двата примера имат същия резултат. И в двата метода на картата се използва масив arr и блок, след което той изпълнява блока на всеки елемент от масива. Кодът вътре в блока върви към_s на всеки елемент, превръщайки го от цели числа в низове. След това, методът на картата връща нов масив, съдържащ конвертираните елементи.

Първият пример е общ и широко използван. Вторият пример може на пръв поглед да изглежда малко загадъчен. Нека да видим какво се случва:

В Ruby елементите, настроени с двоеточие (:) са символи. Ако не сте запознати с класа / типа на символите, ви предлагам да го намерите в Google и да прочетете няколко статии, преди да продължите. Всички имена на методите в Ruby са вътрешно съхранени като символи. Чрез префиксиране на име на метода с двоеточие, ние не превръщаме метода в символ, нито наричаме метода, ние просто предаваме името на метода наоколо (позовавайки се на метода). В горния пример минаваме: to_s, който е препратка към метода to_s, към оператора ampersand (&), който ще създаде proc (като се обади на to_proc под капака). Процесът приема стойност като аргумент, извиква към него и връща стойността, превърната в низ.

Въпреки че :to_s символът е винаги еднакъв, когато изпълнявате схемата на картата, тя ще се отнася до метода to_s на класа, съответстващ на всеки елемент от масива. Ако преминем към масив като [21, 4.453,: foobar], методът to_s на класа Fixnum ще бъде приложен (наречен) на първия елемент, методът to_s на класа Float ще бъде приложен към вторият елемент и методът to_s на класа Символ ще бъдат приложени към третия елемент. Това има смисъл, защото не предаваме действителния метод to_s на оператора ampersand, само името му.

По-долу е даден пример за създаване на прок, който взема аргумент, извиква метод върху него и връща резултата от метода.

p = :upcase.to_proc
p.call("foo bar")
Output:
=> "FOO BAR"

Нека да прегледаме какво се случва в arr.map &: to_s

  1. При всяка итерация на карта един елемент от масива (цяло число) се предава на &: to_s
  2. В:to_s символ (който е препратка към метода to_s) се предава на оператора &, който създава proc, който ще вземе аргумент (елемент от масив), извика to_s върху аргумента и връща стойността, превърната в низ;
  3. Методът на картата връща нов масив, съдържащ низовете "1", "2", "3", "4" и "5".