ОбичамREPLs. Това е страхотен инструмент за развитие. Всеки приличен език има REPL. Lisp го има. Python го има. Както и Haskell. И Ruby очевидно го има!

REPL означаваReadEvalPprintLoop. Това е интерфейс на командния ред за взаимодействие с език за програмиране. Повечето интерактивни езици за програмиране имат REPL. (Не проверих.) Тази номенклатура произлиза от имплементацията на Lisp, която в най-основната си форма може да бъде едноредова:

(loop (print (eval (read))))

Lisp REPL са много мощни. Можем да инспектираме дървото на стека, (повторно) да изпълним рамка (обикновено извикване на функция), да променим аргументите на рамката и да я изпълним повторно, да променим дефиницията на функция и да изпълним повторно рамката, която я извиква.

С толкова високи очаквания не е чудно, че IRB (REPL по подразбиране на Ruby) не изглежда толкова мощен. (Мисля, че ще се съгласите с мен за това.) Pry е доста мощна алтернатива на IRB и съдържа много нови функции. Но все пак... не може да се сравни с този на Lisp. Въпреки това има няколко функции, които (мисля) ще се харесат на новодошлите. Възнамерявам да ги разгледам в тази публикация.

Стойност на предишна оценка

Когато изучавах 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, показва стека за извикване на кадри. (По-често това отнема много време, за да се покаже нещо.)

Wiki на Pry е добре документиран и също така има връзки към други ресурси.

Командата help на Прай също е много полезна. Научих повечето от тези функции оттам. (RTFM синдром)

Това е всичко за сега. Забавлявайте се и бъдете добри! :-)

Работя в Runtime Revolution като Rails разработчик. Работим и с Python, JavaScript… и двата имат REPL! Също така помагаме на стартиращи фирми да достигнат следващото ниво.