Я люблю REPL. Это отличный инструмент для разработки. В любом приличном языке есть REPL. В Лиспе это есть. Python есть. Как и Haskell. И у Ruby, очевидно, он есть!
REPL означает R ead E val P rint L oop. Это интерфейс командной строки для взаимодействия с языком программирования. В большинстве интерактивных языков программирования есть REPL. (Я не проверял.) Эта номенклатура является производной от реализации Лиспа, которая в своей основной форме может быть однострочным:
(loop (print (eval (read))))
Lisp REPL очень мощные. Мы можем проверить дерево стека, (повторно) выполнить кадр (обычно вызов функции), изменить аргументы кадра и повторно выполнить его, изменить определение функции и повторно выполнить вызывающий его кадр.
С такими высокими ожиданиями неудивительно, что IRB (REPL Ruby по умолчанию) не выглядит таким мощным. (Думаю, вы со мной согласитесь.) Pry - довольно мощная альтернатива IRB и содержит много новых функций. Но все же ... его нельзя сравнивать с Лиспом. Тем не менее, есть несколько функций, которые (я думаю) понравятся новичкам. Я намерен пройтись по ним в этом посте.
Предыдущее оценочное значение
При изучении Ruby мне постоянно приходилось использовать значение предыдущей оценки. Допустим, я рассчитал налоговую стоимость продукта и теперь хочу узнать окончательную цену:
pry(main)> price, tax_rate = 34, 0.08 => [34, 0.08] pry(main)> price * tax_rate => 2.72 pry(main)> final_price = price + # damn! -_-
Мне потребовалось время, чтобы понять, что мы можем получить доступ к предыдущему значению с помощью _
(подчеркивание). С двумя символами подчеркивания __
мы получаем доступ ко второму с последнего значения.
pry(main)> price, tax_rate = 34, 0.08 => [34, 0.08] pry(main)> price * tax_rate => 2.72 pry(main)> final_price = price + _ => 36.72 pry(main)> __ => 2.72
Где я?
Одна из методологий отладки - это установка точек останова в наш код. В Pry мы делаем это с помощью выражения binding.pry
. Это приводит к остановке выполнения на этой строке. Когда это произойдет, на консоли Ruby отобразится что-то вроде этого:
pry(main)> Grid.generate(6, 6) From: /Users/bjacquet/Projects/gol/gol.rb @ line 27 Grid.generate: 25: def self.generate(width, height) 26: self.new(Array.new(height).collect do => 27: binding.pry 28: Array.new(width).collect { rand(2) } 29: end [1] pry(Grid)>
Он показывает строку кода, в которой остановлено выполнение, обозначенную =>
. (Это 27-я строка.) Также некоторый контекст кода с окружающими строками. Мы также можем сделать вывод, что он остановился внутри метода Grid.generate
и определен в файле gol.rb.
Эта информация также доступна в любое время, набрав команду whereami
.
Если бы размер этого метода был вдвое больше, мы все равно могли бы видеть его полное содержимое, используя команду show-source
как таковую:
pry(main)> show-source Grid.generate From: gol.rb @ line 25: Owner: #<Class:Grid> Visibility: public Number of lines: 7 def self.generate(width, height) self.new(Array.new(height).collect do binding.pry Array.new(width).collect { rand(2) } end ) end pry(Grid)>
Воспроизведение истории
Команда Прая hist
- это действительно что-то. Помимо прочего, он позволяет просматривать, искать и воспроизводить историю. При вызове без параметров он отображает всю историю Pry, то есть все введенные данные.
pry(main)> hist 1: price, tax_rate = 34, 0.08 2: price * tax_rate 3: price, tax_rate = 34, 0.08 4: price * tax_rate 5: final_price = price + _ 6: __ 7: Grid.generate(6, 6) 8: show-command Grid.generate pry(main)>
С опцией --replay
мы можем переоценить выражение (я):
pry(main)> hist --replay 3..4 => [34, 0.08] => 2.72
Я считаю, что использовать эту команду быстрее, чем вращать предыдущие входные данные с помощью стрелки вверх.
Позвольте мне исправить это прямо сейчас
Довольно часто мы вводим многострочные выражения в Pry. Чаще, чем хотелось бы, мы печатаем строку с ошибкой. Чтобы исправить это, мы используем команду amend-line
. В качестве аргументов он принимает номер строки и код замены.
pry(main)> def hello pry(main)* puts “hello #{name}” pry(main)* amend-line 1 def hello(name) 1: def hello(name) 2: puts “hello #{name}” pry(main)* end => :hello
В этом примере я понял, что забыл указать name
в качестве аргумента метода. Таким образом, я исправляю это, вызывая команду amend-line
в строке 1 с новым кодом. Затем Pry показывает все введенные строки и ждет новых. Я набираю end
, и метод определяется.
Идти дальше
Вылет из-за одной ошибки, извините за это! Это стоит того.
Pry также дает нам возможность изменять методы на лету. Для этого нам нужно использовать две команды. Сначала мы меняем метод с помощью команды edit
.
pry(main)> edit Grid.generate
Это откроет редактор с курсором на первой строке определения метода. Когда мы закончим, сохраняем изменения и выходим из редактора.
Далее нам нужно оценить новое определение. Команда reload-method
делает именно это.
pry(main)> reload-method Grid.generate
Отныне он будет использовать новую версию Grid.generate
.
дальнейшее чтение
У Pry есть еще много возможностей, которые стоит открыть. Готовя этот пост, я обнаружил команду amend-line
. Он настолько полезен, что мне пришлось его включить. Другие команды, о которых вам следует знать, включают:
show-model
, перечисляет атрибуты модели и ассоциации классов.show-stack
, показывает стек вызовов фреймов. (Чаще всего для отображения чего-либо требуется много времени.)
Pry's wiki хорошо документирована, а также содержит ссылки на другие ресурсы.
Команда Прая help
также очень полезна. Я изучил большинство этих функций именно там. (Синдром RTFM)
На этом пока все. Веселитесь и будьте милы! :-)
Я работаю в Runtime Revolution разработчиком на Rails. Мы также работаем с Python, JavaScript… у обоих есть REPL! Мы также помогаем стартапам выйти на новый уровень.