import simplejson
class PrettyFloat(float):
def __repr__(self):
return '%.15g' % self
def pretty_floats(obj):
if isinstance(obj, float):
return PrettyFloat(obj)
elif isinstance(obj, dict):
return dict((k, pretty_floats(v)) for k, v in obj.items())
elif isinstance(obj, (list, tuple)):
return map(pretty_floats, obj)
return obj
print simplejson.dumps(pretty_floats([23.67, 23.97, 23.87]))
испускает
[23.67, 23.97, 23.87]
Не требуется привязка к monkey.
В первую очередь, block.call()
покончили yield
, и Вам не нужно &block
параметр тот путь.
Вы не можете обычно делать то, что Вы хотите, блоки связываются, когда они создаются, и в блоке Вы видите локальные переменные, определенные в тот момент; самый легкий способ сделать, что Вы хотите, который не является, как Вы будете обычно использовать блоки, является этим:
def test()
foo = yield if block_given?
puts "in test, foo is #{foo}"
end
test() {
foo="this is foo"
}
Но это - только побочный эффект потому что foo
"возвращается" блоком. Если Вы вместо этого делаете это:
def test()
foo = yield if block_given?
puts "in test, foo is #{foo}"
end
test() {
foo="this is foo"
"ha ha, no foo for you"
}
Вы заметите, что это делает что-то другое.
Вот больше волшебства:
def test(&block)
foo = eval "foo", block.binding
puts foo
block.call
foo = eval "foo", block.binding
puts foo
end
foo = "before test"
test() {
foo = "after test"
"ha ha, no foo for you"
}
Это было бы вид работы, но это повреждается, если Вы удаляете foo = "before test"
потому что foo
становится локальной переменной в блоке и не существует в привязке.
Сводка: Вы не можете получить доступ к локальным переменным от блока, просто местные жители, где блок был определен и возвращаемое значение блока.
Даже это не будет работать:
def test(&block)
eval "foo = 'go fish'", block.binding
block.call
bar = eval "foo", block.binding
puts bar
end
потому что foo
в привязке отличается от локального в блоке (я не знал это, спасибо).
Нет, блок не может влиять на локальные переменные в месте, где это называют.
Блоки в Ruby являются закрытиями, что означает, что они получают объем вокруг них, когда они создаются. Переменные, которые видимы при создании блока, являются теми, он видит. Если были a foo
и bar
наверху Вашего кода, вне любого метода, тот блок изменил бы их, когда это назвали.
Можно сделать то, что Вы хотите, будучи немного более подробными:
class Test
def foo(t)
@foo = t
end
def bar(t)
@bar = t
end
def test(&block)
self.instance_eval &block if block_given?
puts "in test, foo is #{@foo}"
puts "in test, bar is #{@bar}"
end
end
Test.new.test() {
foo "this is foo"
bar "this is bar"
}
Можно создать методы как attr_accessor
это генерирует соответствующий метод set ( foo
и bar
методы).
def test(&block)
foo = yield
puts "in test, foo is #{foo}"
end
test { "this is foo" }
печать in test, foo is this is foo
Значение урожая является значением блока.
Можно также передать параметры для получения, к которому затем может получить доступ блок с помощью |param, другой | в начале блока.
Кроме того, выезд procs.
foo = "this is foo"
p = Proc.new { "foo is #{foo}" }
p.call
Печать "foo is this is foo"
def test(p)
p.call
end
test p
Печать "foo is this is foo"
def test2(p)
foo = "monkey"
p.call
end
test2 p
Печать "foo is this is foo"