首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >binding.pry和Pry.start有什么区别?

binding.pry和Pry.start有什么区别?
EN

Stack Overflow用户
提问于 2019-09-26 22:48:05
回答 1查看 1.1K关注 0票数 2
代码语言:javascript
复制
require 'pry'

var = "variable"

class Gnar
    def self.gar
        @var = "lar!"
        # binding.pry
        # Pry.start(binding)
        # Pry.start
    end
end

Gnar.gar

当我取消对binding.pry的评论时,我发现自己正处于self == Gnar的REPL中。当我取消评论Pry.start(binding)时,Pry从未启动过。当我取消对Pry.start的评论时,我发现自己正处于self == main的REPL中。

我不明白这种行为,我想真正掌握这个重要的Ruby调试工具的本质。我想集中讨论binding.pryPry.start(binding)的行为。

在一种情况下,我们在binding对象上调用binding方法,而在另一种情况下,我们用binding作为参数调用Pry类上的.start方法。

让我们从binding.pry开始。根据医生们#pry的定义如下:

代码语言:javascript
复制
def pry(object=nil, hash={})
  if object.nil? || Hash === object
    Pry.start(self, object || {})
  else
    Pry.start(object, hash)
  end
end

基于该方法定义,当我们在没有参数的对象上调用#pry时,我们调用Pry.start(self, {}),其中selfbinding上下文中的self

那么,在Pry.start中发生了什么呢?文档中的定义是相当长的,但我注意到的是,self作为target of Pry.start传入,然后在这一行中使用:

代码语言:javascript
复制
options[:target] = Pry.binding_for(target || toplevel_binding) #line 152

在此之前

代码语言:javascript
复制
# Enter the matrix
  driver.start(options) #line 169

考虑到所有这些,我的理解是,binding.pry通过driver.start(options)options[:target] = Pry.binding_for(binding)生成REPL。如果Pry.start(binding) target == binding 在这两种情况下都没有表现出相同的行为(即没有启动REPL),为什么没有表现出相同的行为呢?我做了什么不正确的假设?,我有点理解,Pry.start会以self == main作为默认的target == toplevel_binding来启动REPL。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-09-27 04:53:42

从控制台中调用Pry.start(binding)应该与调用binding.pry具有类似的效果

代码语言:javascript
复制
rails c
Loading development environment (Rails 5.1.6.2)
[1] pry(main)> class Gnar
[1] pry(main)*   def self.gar    
[1] pry(main)*     @var = "lar!"        
[1] pry(main)*     Pry.start(binding)
[1] pry(main)*   end  
[1] pry(main)* end  
=> :gar
[2] pry(main)> Gnar.gar

From: /Users/redacted/.gem/gems/pry-0.12.2/lib/pry/pry_instance.rb @ line 388 Pry#evaluate_ruby:

    383: def evaluate_ruby(code)
    384:   inject_sticky_locals!
    385:   exec_hook :before_eval, code, self
    386: 
    387:   result = current_binding.eval(code, Pry.eval_path, Pry.current_line)
 => 388:   set_last_result(result, code)
    389: ensure
    390:   update_input_history(code)
    391:   exec_hook :after_eval, result, self
    392: end

[1] pry(#<Pry>)> 

绑定对象封装代码在特定位置的执行上下文。Binding#pry在绑定对象上启动一个撬REPL。

Pry.start只是启动了一个撬的REPL。如果您不传递它一个绑定,那么它只是一个没有任何执行上下文的Pry;如果传递给它的绑定的执行上下文是一个撬实例,控制台将通过从pry(main) (无上下文)更改为pry(#<Pry>)>来告诉您它是否具有上下文:

代码语言:javascript
复制
$ rails c
Loading development environment (Rails 5.1.6.2)
[1] pry(main)> Pry.start(binding)

From: /Users/redacted/.gem/gems/pry-0.12.2/lib/pry/pry_instance.rb @ line 388 Pry#evaluate_ruby:

    383: def evaluate_ruby(code)
    384:   inject_sticky_locals!
    385:   exec_hook :before_eval, code, self
    386: 
    387:   result = current_binding.eval(code, Pry.eval_path, Pry.current_line)
 => 388:   set_last_result(result, code)
    389: ensure
    390:   update_input_history(code)
    391:   exec_hook :after_eval, result, self
    392: end

[1] pry(#<Pry>)> exit
=> nil
[2] pry(main)> binding.pry

From: /Users/redacted/.gem/gems/pry-0.12.2/lib/pry/pry_instance.rb @ line 388 Pry#evaluate_ruby:

    383: def evaluate_ruby(code)
    384:   inject_sticky_locals!
    385:   exec_hook :before_eval, code, self
    386: 
    387:   result = current_binding.eval(code, Pry.eval_path, Pry.current_line)
 => 388:   set_last_result(result, code)
    389: ensure
    390:   update_input_history(code)
    391:   exec_hook :after_eval, result, self
    392: end

[1] pry(#<Pry>)> exit
=> nil
[3] pry(main)> exit

类似地,从类方法中调用binding.pry会在该类的执行上下文(pry(ClassName))中打开一个撬REPL。从实例方法中调用binding.pry将在该实例(pry(#<ClassName>)的执行上下文中打开一个撬REPL。

代码语言:javascript
复制
rails c
Loading development environment (Rails 5.1.6.2)
[1] pry(main)> class A
[1] pry(main)*   def self.b
[1] pry(main)*     binding.pry
[1] pry(main)*   end  
[1] pry(main)*   
[1] pry(main)*   def c
[1] pry(main)*     binding.pry
[1] pry(main)*   end  
[1] pry(main)* end  
=> :c
[2] pry(main)> A.b

From: (pry) @ line 4 A.b:

    2: def self.b
    3:   binding.pry
 => 4: end

[1] pry(A)> exit
=> nil
[3] pry(main)> A.new.c

From: (pry) @ line 8 A#c:

    6: def c
    7:   binding.pry
 => 8: end

[1] pry(#<A>)> exit
=> nil

希望这能有所帮助。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58125631

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档