2014-02-05 2 views
0

Я пытаюсь научиться рубину и наткнулся на что-то странное. Этот код:Как переменная может иметь значение, а также не определять?

if defined? branch 
    puts "param: #{branch}\n" 
else 
    puts "no branch! #{branch}\n" 
end 

Выходов «нет ветви thisisateststring! \ П», где «thisisateststring» является значением, которое было назначено переменной отраслью ранее в программе. Как может быть, что переменная branch может иметь присвоенное ей значение, но не определено?

Edit:

Люди, кажется, не будет понимания на мой вопрос. Я не прошу вас выяснить, почему в этом конкретном случае выполняется else; Я прошу , как это может случиться в целом. Иными словами, какой код нужно будет вставить перед этим, чтобы вызвать мое дело?

Как я уже сказал, я новичок в рубине, поэтому я мог легко ошибиться в чем-то принципиальном. Я не пытаюсь решить конкретную проблему; Я пытаюсь улучшить свое понимание, узнав больше о том, как работает рубин. В этом случае, как ruby ​​может выводить строку, но все еще думая, что она не определена.

+2

Дайте полный код. –

+0

У меня нет полного кода. Этот фрагмент - это мой собственный код, который запускается как часть более крупной структуры, которую кто-то написал. Я просто пытаюсь выяснить, как переменная может быть определена и не определена в одно и то же время. – Benubird

+0

Из того, что я могу сказать, оператор else никогда не будет успешно работать. Если, возможно, если этот код относится к определению класса или что-то подобное, то может быть, что второй ответ ветвления будет обрабатываться через функцию method_missing. – hirolau

ответ

2

@hirolau дал вам пример, который работает. Я хотел бы использовать его идею и немного упростить для вас.Попробуйте следующее:

defined? foo 
=> nil 

foo 
NameError: undefined local variable or method 'foo' for main:Object 

def method_missing(m, *params, &block) 
    if m.to_s == "foo" 
    return "cool stuff" 
    end 
end 

# foo is still not defined 
defined? foo 
=> nil 

# but returns some value 
foo 
=> "cool stuff" 
1

Как правило, нет, но Ruby имеет множество способов обработки отсутствующих методов и неопределенных переменных. Рассмотрим, например:

class Tree 
    def initialize 
    if defined? branch 
     p "param: #{branch}\n" 
     else 
     p "no branch! #{branch}\n" 
    end 
    end 

    def method_missing(method_call) 
    return 'this text comes from method_missing' 
    end 

end 

a = Tree.new #=> "no branch! this text comes from method_missing" 

class Tree 
    def branch 
    return 'NOW I HAVE MY OWN METHOD' 
    end 
end 

a = Tree.new #=> "param: NOW I HAVE MY OWN METHOD" 

Более подробную информацию о вашей проблеме очень сложно дать без контекста заявления.

+0

Вот что, я не знаю контекста ... Я просто хотел бы знать, как это возможно. – Benubird

+0

Возможно, что-то подобное, за исключением того, что ваш второй случай все еще считается как определенный. Может ли метод_mising делать какой-то поиск? – Benubird

+0

Несомненно, пример @ Abdo показывает, что его действительно не нужно определять. Я попытался показать, что только потому, что он не определен в какой-то момент, он впоследствии может быть определен, что делает проверку действительной. – hirolau

0

Ключевое слово Ruby не проверяет, является ли цель нулевой или нет, вместо этого она проверяет, что цель «относится к чему-либо распознаваемому (объект литерала, локальная переменная, которая была инициализирована, имя метода видна из текущей области действия и т. Д.). .) «.

Посмотрите документацию, чтобы понять ее поведение. http://ruby-doc.org/docs/keywords/1.9/Object.html#method-i-defined-3F

Если вы хотите проверить, если переменная равна нулю, вы можете сделать:

if branch.nil? or branch.empty? 
    puts "no branch!\n" 
else 
    puts "param: #{branch}\n" 
end 
0

defined? в Ruby, это ключевое слово.

Он возвращает nil или описание того, что объект является строкой.

В Ruby, только две вещи, которые оценивают в фальшь false и nil

Таким образом, если «вещь», что вы пытаетесь узнать о неопределен, то defined? возвратит nil, который будет оценивать, как false в вашем коде, как показано в вашем вопросе.

Чтобы ответить на ваш вопрос: «Как переменная может иметь значение, а также не определять?»

Не может. Если он не определен как переменная, как это может быть даже переменная. Но его можно определить как переменную и иметь значение nil.

+0

Хорошо, но это имеет значение, потому что мой вызов puts производит вывод. Может ли оно иметь значение nil, но также и строковое значение? – Benubird

+0

Что определяется? вернувшись на это? Вероятно, это не переменная, так как переменная может хранить только одно значение (объект), так же как метод может возвращать только один объект. Таким образом, тогда тест должен состоять в том, чтобы 'puts defined? (Branch), чтобы вы могли видеть, что такое объект ветви. – vgoff

+0

http://stackoverflow.com/a/21576653/485864 - это именно то, что я указываю здесь. – vgoff

Смежные вопросы