#ruby #object #undefined
#ruby #объект #не определено
Вопрос:
Я работал над определенной проблемой, когда заметил, что все сбило с толку то, что я объявил переменную вне циклов while. Рассматриваемая переменная имеет значение sub_string = 1 . Похоже, что я должен объявить его после первого цикла while, прямо перед тем, как он фактически вступит в игру во втором цикле while. Объявляя ее раньше, цикл каким-то образом может распознавать только палиндромы, которые начинаются со строки [0] и, тем не менее, могут быть любой длины. На всю жизнь я не уверен, почему он ведет себя таким образом, поскольку я объявляю длину фрагмента (а не начальную позицию).
Простите меня, если я здесь упускаю что-то невероятно простое, поскольку я довольно новичок в программировании в целом.
Вот код, о котором идет речь (опущено определение палиндрома? метод проверки).
def longest_palindrome(string)
idx = 0
longest = nil
#substring_string = 1 ; declaring it early seems to cause weird issues to show up
while idx < string.length
substring_length = 1 #I have to declare the substring_length here
while (idx substring_length) <= string.length
substring = string.slice(idx, substring_length)
if palindrome?(substring) amp;amp; (longest == nil || substring.length > longest.length)
longest = substring
print substring_length
end
substring_length = 1
end
idx = 1
end
return longest
end
Ответ №1:
Сценарий 1: substring_length определен внутри цикла while
def longest_palindrome(string)
idx = 0
longest = nil
while idx < string.length
substring_length = 1
while (idx substring_length) <= string.length
# palindrome
substring_length = 1
end
idx = 1
end
longest
end
- Когда этот метод вызывается для объекта, поток управления выполнением переходит к первому
while
циклу.while idx < string.length
- Внутри этого цикла вы инициализируете
substring_length
1
- Затем код переходит во вложенный цикл
while (idx substring_length) <= string.length
- Внутри вложенного цикла вызывается метод palindrome, который затем
substring_length
увеличивается на 1. Этот код выполняется до тех пор, пока его условие не вернет false(idx substring_length) < string.length
. Следствием этого является то, что после завершения этого внутреннего циклаsubstring_length
ВСЕГДА будет значение больше 1 - Как только этот внутренний цикл заканчивается, управление возвращается к внешнему
while
циклу. Теперь первая строка кода переназначаетсяsubstring_length
на1
. По сути, независимо от значенияsubstring_length
в конце внутреннего цикла, как только поток управления возвращается во внешний цикл, это значение отбрасывается, поскольку вы устанавливаетеsubstring_length
значение 1
Сценарий 2: substring_length определяется вне цикла while
def longest_palindrome(string)
idx = 0
longest = nil
substring_length = 1
while idx < string.length
while (idx substring_length) <= string.length
# palindrome
substring_length = 1
end
idx = 1
end
longest
end
- Когда этот метод вызывается для объекта, он
substring_length
инициализируется значением 1, а затем поток управления выполнением переходит к первомуwhile
циклу.while idx < string.length
- Если условие истинно, поток управления переходит ко второму циклу,
inner
циклу - Внутри внутреннего цикла вызывается метод palindrome, который затем
substring_length
увеличивается на 1. Этот код выполняется до тех пор, пока его условие не вернет false(idx substring_length) < string.length
. Как и в сценарии 1, из этого следует, что после завершения этого внутреннего циклаsubstring_length
ВСЕГДА будет значение больше 1 - Как только этот внутренний цикл заканчивается, управление возвращается к внешнему
while
циклу. На этот раз нет инструкции инициализации, поэтому значениеsubstring_length
в конце внутреннего цикла — это то же самое значение, которое используется, когда управление возвращается во внешний цикл.
Давайте попробуем использовать пример
Сценарий 1
longest_palindrome('him')
idx = 0; substring_length = 1; string.length = 3
while (0 < 3) # the outer loop condition is true,
substring_length = 1
# while (idx substring_length) < string.length
while (0 1) < 3 # inner loop condition is true
# run code block, increment substring_length by 1, substring_length is NOW 2
while (0 2) < 3 # inner loop condition is still true
# run code block, increment substring_length by 1, substring_length is NOW 3
while (0 3) < 3 # inner loop condition fails, substring_length = 3
# Go to line after end of inner loop
increase idx by 1 # idx = 1
# Go back to outer loop
set substring_length to 1 # substring_length is NO MORE 3
# while (idx substring_length) < string.length
while (1 1) < 3 # run code block, increment substring_length by 1, substring_length is NOW 2
while (1 2) < 3 # condition fails
..... and so on
Сценарий 2
longest_palindrome('him')
idx = 0; substring_length = 1; string.length = 3
while (0 < 3) # the outer loop condition is true,
# while (idx substring_length) < string.length
while (0 1) < 3 # inner loop condition is true
# run code block, increment substring_length by 1, substring_length is NOW 2
while (0 2) < 3 # inner loop condition is still true
# run code block, increment substring_length by 1, substring_length is NOW 3
while (0 3) < 3 # inner loop condition fails, substring_length = 3
# Go to line after end of inner loop
increase idx by 1 # idx = 1
# Go back to outer loop. Remember substring_length =3
# while (idx substring_length) < string.length
while (1 3) < 3 # condition is false. Inner loop is NOT EXECUTED
# Go to line after end of inner loop
increase idx by 1 # idx = 1
# Go back to outer loop while (idx < string.length)
while (1 < 3) # outer loop condition is true
# Go to inner loop while (idx substring_length) < string.length
while (1 3) < 3 # Once again condition is false and inner loop is NOT EXECUTED
# Go to line after end of inner loop
increase idx by 1 # idx = 1
Как вы можете видеть в этом сценарии, внутренний цикл перестает выполняться, потому substring_length
что ему не присваивается значение 1, и условие постоянно выполняется с ошибкой.
Комментарии:
1. Ага. Я думаю, мне придется несколько раз перечитать ваше объяснение, чтобы разобраться, но большое спасибо за ответ!
2. Эй, @Tony, я отредактировал свой ответ. Надеюсь, это даст вам лучшее понимание.
3. Ваше объяснение было замечательным с самого начала. Ваше форматирование сделало его очень удобным, чтобы увидеть, в чем ключевое различие между двумя рассматриваемыми сценариями. Мой комментарий оборвался, и я почему-то не уловил этого (и не похоже, что я могу редактировать комментарии). Спасибо за ваше время. Мне нужно будет поискать в Google, как вы смогли показать вывод каждого цикла таким образом (поскольку я все время использовал print как часть своего цикла для получения информации о том, что делал код).