Блокове, Lexical Closures и подлото Ruby 1.8

  1. Нещо което доста ме шашна в Руби 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 години
  2. Хватката, всъщност, е следната:

    Аргументите на блоковете са локални само ако до момента 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 години
  3. Това последното е доста коварно. Трябва да се внимава доста как се кръщават променливите в блоковете, явно.

    Публикувано преди повече от 4 години

Нов отговор

Трябва да сте вътре за да отговаряте.