Блокове, Lexical Closures и подлото Ruby 1.8
-
Нещо което доста ме шашна в Руби 1.8 – аргументите към блоковете не винаги са локални за тях, а се вземат от обгръщащата област на видимост на блока (lexical closure):
[~]$ irb >> x = "local variable" => "local variable" >> y = lambda do |x| puts x end => #<Proc:0xb7c23f64@(irb):2> >> y.call("local variable changed") local variable changed => nil >> x => "local variable changed" >>
Във версия 1.9 аргументите винаги са локални за блока: http://www.infoq.com/news/2008/01/new-lambda-syntax
Публикувано преди повече от 4 години -
Хватката, всъщност, е следната:
Аргументите на блоковете са локални само ако до момента Ruby не е срещнал променлива с такова име. Ако не си дефинирал x преди това, няма да остане.
>> [1, 2, 3].map { |x| x } => [1, 2, 3] >> x NameError: undefined local variable or method `x' for main:Object from (irb):2
Другата хватка е с for. Той не създава област на видимост, при което:
>> for y in [1,2]; z = y; end => [1, 2] >> y => 2 >> z => 2
И двете неща работят в различно в 1.9.
Иначе, капанът, в която най-често попадам:
photo = Photo.find_by_name(search[:name]) # Тук намерих снимка с ID 1 photo.related_photos.each { |photo| photo.deactivate } photo.deactivate # Тук е грешката
Очевидно исках да деактивирам синмка, като преди това даективирам нейните <code>related</code> снимки. Обаче като този код се изпълни, снимката с ID 1 все още е активна.
Публикувано преди повече от 4 години -
Това последното е доста коварно. Трябва да се внимава доста как се кръщават променливите в блоковете, явно.
Публикувано преди повече от 4 години
Нов отговор
Трябва да сте вътре за да отговаряте.