代码之家  ›  专栏  ›  技术社区  ›  Kannan Ekanath

在ruby中放入变量name=value格式

  •  3
  • Kannan Ekanath  · 技术社区  · 15 年前

    我想为我的简单ruby函数添加一些调试,我编写了一个函数,如下所示,

    def debug(&block)
      varname = block.call.to_s
      puts "#{varname} = #{eval(varname,block)}"
    end
    
    debug {:x} #prints x = 5
    debug {:y} #prints y = 5
    

    我知道eval是邪恶的。所以我有两个问题。

    1. 有没有办法不用eval来编写调试方法?如果没有,有没有更好的方法?
    2. 有没有办法把参数列表传递给这个方法?理想情况下,我更喜欢调试{:x,:y.:anynumofvariables}。我不太明白如何在调试方法中考虑这一点(即,获取参数列表)
    2 回复  |  直到 11 年前
        1
  •  11
  •   Jörg W Mittag    15 年前

    使用数组就行了。你可以使用 Array 方法以确保始终具有数组,即使有人只传入一个值:

    def debug(&block)
      Array(block[]).each do |var| puts "#{var} = #{eval var.to_s, block}" end
    end
    
    x, y = 3, 5
    
    debug {:x} # => "x = 3"
    debug {[:x, :y]} # => "x = 3" "y = 5"
    

    顺便说一下:在Ruby1.9中,作为绑定传递一个块不再有效。(尽管文件上说 工作。)必须显式调用 Proc#binding 得到一个 Binding 反对这个 Proc :

    def debug(&block)
      Array(block.()).flatten.each do |var|
        puts "#{var} = #{eval var.to_s, block.binding}"
      end
    end
    

    幸运的是 已经 在Ruby1.8中工作,因此您可以通过包含它来验证您的代码。

    另一种选择是完全放弃这个街区。我是说,你 已经 强制用户 debug 使用不熟悉的习惯用法,即在块中传递参数而不是在括号中。为什么不强迫他们通过绑定呢?

    def debug(*vars, bnd)
      vars.each do |var|
        puts "#{var} = #{eval var.to_s, bnd}"
      end
    end
    
    x, y = 3, 5
    
    debug :x, binding # => "x = 3"
    debug :x, :y, binding # => "x = 3" "y = 5"
    

    这增加了灵活性,他们实际上可以通过 不同的 绑定而不是调用站点上的绑定,例如,如果他们想实际调试应用程序中不同部分的代码。


    顺便说一下:这里有一些关于Ruby1.9.2参数内省的乐趣( Proc#parameters ):

    def debug(&block)
      block.parameters.map(&:last).each do |var|
        puts "#{var} = #{eval var.to_s, block.binding}"
      end
    end
    
    x, y = 3, 5
    
    debug {|x|} # => "x = 3"
    debug {|x, y|} # => "x = 3" "y = 5"
    
        2
  •  0
  •   spaffy    11 年前

    以及如何使用这些方法从 每个 循环,将它们作为嵌套哈希的键和值放置?

    *attributes数组作为方法的参数传递。 我想遍历它,每个变量的名称用作嵌套散列的键,变量的值用作值。

    我得到这个:

    def get_varname(&block)
        varname = block.call.to_s
        return varname
    end
    
    def create_instance_hash(env_attrs_obj, *attributes)
        if not env_attrs_obj.has_key?("instances")
            env_attrs_obj["instances"] = ""
        end
        attributes.each do |attr|
            attr_name = get_varname{:attr}
            env_attrs_obj["instances"][attr_name] = attr
        end
    end
    
    instance_nat_ip_pub = "ip_pub_addr"
    instance_nat_ip_prv = "ip_addr"
    instance_nat_ami = "AMI_NAME"
    instance_nat_aws_ssh_key_id = "AWS_SSH_KEY_ID"
    instance_nat_id = "instance_id"
    
    env_hash = {}
    
    create_instance_hash(env_hash, *[instance_nat_ip_pub, instance_nat_ip_prv, instance_nat_ami, instance_nat_aws_ssh_key_id, instance_nat_id])
    

    但是:

    def attrs_each_test(*attributes)
        attributes.each do |attr|
            puts get_varname{:attr}
        end
    end
    

    它输出:

    attr
    attr
    attr
    attr
    attr
    

    误差 when I run 创建实例哈希 :

    Line 12:in `[]=': string not matched (IndexError)
        from t.rb:12:in `create_instance_hash'
        from t.rb:10:in `each'
        from t.rb:10:in `create_instance_hash'
        from t.rb:24
    

    我怎样才能纠正这个错误并达到我的目标?