Помещение переменной имя = значение формата в Ruby - PullRequest
3 голосов
/ 24 марта 2010

Я хотел бы добавить несколько отладок для моих простых функций 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

Я понимаю, что Эвал - это зло. Итак, у меня есть два вопроса.

  1. Есть ли способ написать этот метод отладки без использования eval? Если НЕТ, есть ли предпочтительный способ сделать это?
  2. Есть ли способ передать список аргументов этому методу? Я бы предпочел отладку {: x,: y. : anynumOfvariables}. Я не мог понять, как включить это в метод отладки (т. Е. Взять список аргументов)

Ответы [ 2 ]

11 голосов
/ 24 марта 2010

Просто используйте массивы. Вы можете использовать метод 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"

Кстати: передача блока, поскольку привязка больше не работает в Ruby 1.9. (Несмотря на то, что в документации сказано, что работает .) Вы должны явно вызвать Proc#binding, чтобы получить объект Binding для этого Proc:

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

К счастью, этот уже работает в Ruby 1.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"

Это обеспечивает дополнительную гибкость, позволяющую им фактически передавать другую привязку, чем привязка на месте вызова, например если они хотят отладить фрагмент кода в другом фрагменте приложения.


Кстати: вот немного веселья с самоанализом параметров Ruby 1.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"
0 голосов
/ 01 апреля 2014

И как я должен использовать эти методы для получения имен и значений переменных из каждого цикла , чтобы разместить их в качестве ключей и значений вложенного хэша?

Массив * атрибутов передается как параметр метода. Я хочу перебрать его, и имя каждой переменной использовать в качестве ключа для вложенного хэша, а значение переменной в качестве значения.

Я получил это:

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

Ошибка при запуске this create_instance_hash :

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

Как я могу исправить эту ошибку и достичь своей цели?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...