Как передать локальную переменную Ruby из метода во вложенный метод? - PullRequest
3 голосов
/ 30 декабря 2010

Учитывая этот простой код Ruby:

def testMethod
  testVar = 1
  def subTestMethod
    if testVar == 1
      puts 'Yes'
    else
      puts 'No'
    end
  end
  subTestMethod
end

testMethod

Есть ли способ передать локальную переменную testVar в суб-метод без принудительного использования переменной класса?

Ответы [ 3 ]

8 голосов
/ 30 декабря 2010

Код у вас, скорее всего, не делает то, что вы хотите:

Внутренний def в вашем коде не определяет локальный метод. Вместо этого он определяет subTextMethod как глобальный метод в классе Object, как только testMethod вызывается впервые. Это означает, что после вызова testMethod вы сможете звонить subTestMethod из любого места.

Тот факт, что subTestMethod не является локальным для testMethod, конечно, также означает, что subTestMethod не может закрывать локальные переменные testMethod.

Чтобы получить желаемое поведение, вы можете использовать лямбда-код, подобный этому (или переосмыслить свой дизайн, чтобы вам не понадобились вложенные функции):

def testMethod
  testVar = 1
  subTestLambda = lambda do
    if testVar == 1
      puts 'Yes'
    else
      puts 'No'
    end
  end
  subTestLambda.call
end
5 голосов
/ 31 декабря 2010

В Ruby только блоки (и лямбда-литералы) могут быть замыканиями.Таким образом, вам придется использовать блок для определения метода:

def testMethod
  testVar = 1
  Object.send(:define_method, :subTestMethod) do
    if testVar == 1
      puts 'Yes'
    else
      puts 'No'
    end
  end
  subTestMethod
end

testMethod

Как уже указывали другие, то, делает ли это то, что, по вашему мнению, делает, зависит, конечно, от того, что именно вы думаете, что это так, но, скорее всего, это не .

Просто пара советов по стилю: методы и (непостоянные) переменные следуют за snake_case именованиемПо соглашению, вы используете пустые строки, чтобы отделить инициализацию от фактической работы и возвращаемого значения, и все это выражение.

Итак, ваши testMethod, subTestMethod и testVar должны быть скорее названы test_method, sub_test_method и test_var.До define_method и до sub_test_method должна быть пустая строка.И вы можете вытянуть puts за пределы выражения if, так как оно равно выражению и, таким образом, возвращает его значение:

def test_method
  test_var = 1

  Object.send(:define_method, :sub_test_method) do
    puts(if test_var == 1 then 'Yes' else 'No' end)
  end

  sub_test_method
end

test_method

То, что вы, вероятно, скорее всего, хотите, это лямбда:

def test_method
  test_var = 1

  sub_test_lambda = -> { puts(if test_var == 1 then 'Yes' else 'No' end) }

  sub_test_lambda.()
end

test_method
1 голос
/ 30 декабря 2010

Передача testVar в качестве параметра subTestMethod

def testMethod
  testVar = 1
  def subTestMethod(testVar)
    if testVar == 1
      puts 'Yes'
    else
      puts 'No'
    end
  end
  subTestMethod testVar
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...