fruit = ->(str) { ['banan', 'apple', 'grape'].include? str }
vege = ->(str) { ['pomidor', 'ziemniak', 'marchewka'].include? str }
miecho = ->(str) {['ciele', 'mele', 'baran'].include? str }
['apple', 'pomidor', 'ciele', 'nic'].each do |food|
case food
when fruit then puts "#{food} to jest fruit"
when vege then puts "#{food} to jednav vege"
when miecho then puts "#{food} to jednak miecho"
else p "nie wiem co to za #{food}"
end
end
Wiem, że fruit, vege i miecho to obiekty Proc,
przy when mam fruit, miecho i vege, ale nie wiem jak ruby przekazuje argument food, tak że fruit, czy vege czy miecho “wie”, że chodzi o konkretny element z tablicy. Jak wpiszę:
(...) when fruit(food) then puts "#{food} to jest fruit" (...)
to dostaję:
proc2.rb:17:in `block in <main>': undefined method `fruit' for main:Object (NoMethodError)
from proc2.rb:15:in `each'
from proc2.rb:15:in `<main>'
Formalnie co case robi to bierze argument z when i porównuje go z tematem (tym czymś po case) przy pomocy porównania ===
Czyli:
case temat
when wariant1 then puts "1"
when wariant2 then puts "2"
end
co następuje to ruby robi wariant1 === temat i jeżeli się zgadza to wypisuje 1
Teraz jest sporo klas które definiują === co więcej można ją samemu zdefiniować. Ale są pewne wbudowane zachowania o których warto wiedzieć:
W przypadku Klas [Class] operator === zachowuje się jak is_a? czyli sprawdza czy temat jest instancją danej klasy
W przypadku przedziałów Range np. (1…10) === zachowuje się jak include?
W przypadku wyrażeń regularnych Regexp np. /foo/ zachowuje się jak match?
W przypadku lambda/proc Lambda zachowuje się jak call czyli wywołuję lambdę/proca
Ps. Jako ciekawostka operator === używany jest także w wyrażeniu begin ... rescue Exception ... end możemy stworzyć własną klasę Pokeball która będzie łapać wszystkie wyjątki poprzez zdefiniowanie ją jako
class Pokeball
def self.===(exception) true end
end
begin
raise "some noise!"
rescue Pokeball
# Gotta catch them all!
end
@swistak84 dzięki za wyjaśnienia, @paki dzięki za link to mi rozjaśniło temat, rozumiem, że obiekty Proc z jednym argumentem zadziałają przy case, ale już z dwoma lub więcej argumentami już raczej nie? Mi pojawia się błąd
is_ev = ->(n,m) { puts n, m }
is_ev === 2,3
# => SyntaxError: (irb):22: syntax error, unexpected ',', expecting end-of-input
irb(main):023:0> is_ev === 2
#=> ArgumentError: wrong number of arguments (1 for 2)
ale być może, źle tego używam w tym wypadku i powinienem użyć czegoś innego?
no tak, ale nadal proc otrzymuje tylko jeden argument, a nie kilka - ale być może na siłę szukam problemu, tam gdzie go nie ma. Dzięki za wyjaśnienia - wiem więcej teraz niż rano