Когда становится доступной локальная переменная? - PullRequest
1 голос
/ 09 марта 2019

Это из примера, приведенного в разделе 4.3 ruby-doc, по следующей ссылке:

рубин Doc

Объяснение выглядит так:

Ruby ищет операторы присваивания. Если в какой-то момент в источнике до использования a'' it sees it being assigned to, it decides to parse a '' в качестве переменной, в противном случае он обрабатывает его как метод.

пример ниже

def a
  print "Function 'a' called\n"
  99
end

for i in 1..2
  if i == 2
    print "a=", a, "\n"
  else
    a = 1
    print "a=", a, "\n"
  end
end

Вывод дан как

a=1
Function 'a' called
a=99

Но, как видно из кода, когда i равен 1, a присваивается 1, а 1 печатается как значение a. Тогда для i = 2 вызывается метод «a».

Теперь, что произойдет, если я напечатаю 'a' вне цикла for? Я получил значение 1, но я понятия не имею, как это возможно. Если переназначение a на 1 от предыдущего значения метода приведет к его повсеместному изменению, то при i = 2 вывод также должен был быть 1. Исправьте меня, если я ошибаюсь.

Ответы [ 3 ]

1 голос
/ 09 марта 2019

Когда вы назначаете a = 1, вы «переопределяете» функцию a. Я надеюсь, что этот маленький кусочек кода может помочь:

def a
  'function a'
end

p a.class #=> String returned by the function
a = 1
p a.class #=> Integer "overridden" by a=1
p a().class #=> String the function is not lost, needs to be called with round brackets.
0 голосов
/ 11 марта 2019

Операторы присваивания в недоступных ветвях кода действительно влияют на локальные переменные.

class Foo
  def method_missing(meth, *args)
    "returned from method_missing #{meth}"
  end
end

Foo.new.instance_exec do
  puts abc.inspect # abc is considered a method

  if true == false
    abc = 1 # <-- this should never be reached
  end

  puts abc.inspect # abc is considered a local variable
end

Это выводит:

"returned from method_missing abc" # <- the return value from method_missing
nil # <- suddenly abc is nil, even though abc wasn't touched.

Итак, Ruby видит код, который присваивается локальной переменной abc и решает, что с этого момента abc является переменной, а не вызовом метода.

Я считаю, что это сделано для того, чтобы разрешить что-то подобное без NoMethodError:

if something
  a = true
end

if a
  puts "ah yes, a."
end

Это редко встречается, если вы сначала не делаете глупостей.

0 голосов
/ 10 марта 2019

В вашем примере нет ничего "локального".В ruby ​​большинство вещей доступно, если они не определены внутри определения класса или модуля, где они могут быть «локализованы».Вот как вы можете написать простой класс

class Foo
  def self.a
    'a'
  end
end

Здесь мы просто определяем один метод класса, который всегда будет возвращать строку a, которая не может быть изменена.Если вы хотите инкапсуляцию, рекомендуется не писать вещи без нее.В противном случае вы можете в значительной степени изменить что угодно в Ruby, поэтому это хороший язык для метапрограммирования.Для других идей возможно посмотрите здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...