【问题标题】:Something like let in Ruby类似于 let in Ruby
【发布时间】:2011-02-15 23:41:27
【问题描述】:

我曾经写过类似 let 的表达式——带有词法范围。

所以我自己写了(难过,但它会因多线程而失败):

# Useful thing for replacing a value of
# variable only for one block of code.
# Maybe such thing already exist, I just not found it.
def with(dict, &block)
  old_values = {}

  # replace by new
  dict.each_pair do |key, value|
    key = "@#{key}"
    old_values[key] = instance_variable_get key
    instance_variable_set key, value
  end

  block.call

  # replace by old
  old_values.each_pair do |key, value|
    instance_variable_set key, value
  end
end

我在 google 中搜索 ruby​​ 的此类结构(可能是其他块定义),但找不到。也许我失去了一些东西?在这种情况下,红宝石人使用什么?

PS:对不起,我的英语不好,你知道的。

UPD:我想提供使用示例:

@inst_var = 1
with :inst_var => 2 do
  puts @inst_var
end
puts @inst_var

输出:

2
1

【问题讨论】:

标签: ruby lexical-scope


【解决方案1】:

一个想法:

class Object
  def let(namespace, &block)
    namespace_struct = Struct.new(*namespace.keys).new(*namespace.values)
    namespace_struct.instance_eval(&block)
  end
end

message = let(language: "Lisp", year: "1958", creator: "John McCarthy") do
  "#{language} was created by #{creator} in #{year}"
end

单值范围更明确,因为您在块参数中命名变量。这个抽象被称为aspipeintoscopeletpeg,......,你的名字,都是一样的:

class Object
  def as
    yield self
  end
end

sum = ["1", "2"].map(&:to_i).as { |x, y| x + y } #=> 3

【讨论】:

  • 两个很好的建议,它们都可以通过简洁的方式来扩展语言以满足您的需求。
【解决方案2】:

您无法指定要初始化的值,但可以将变量声明为该块的显式本地变量:

x = 'external value'
puts x
[1,2,3].each do |i; x|
  x = i
  puts x
end
puts x

这将导致:

external value
1
2
3
external value

【讨论】:

  • 值得注意的是,i 在本例中也是块的本地。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-09
  • 2011-02-24
  • 1970-01-01
相关资源
最近更新 更多