类似于 let in Ruby

发布于 2024-10-18 00:02:54 字数 841 浏览 4 评论 0原文

我曾经写过类似 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

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

PS:抱歉我的英语不好,你知道的。

UPD:我忘了提供用法示例:

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

输出:

2
1

I used to write let-like expressions -- with lexical scope.

So I write my own (sad, but it will fail with multiple threads):

# 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

I search in google for such constructions (maybe additional block definitions) for ruby, but can't found it. Maybe I loose something? What ruby-people use in such cases?

PS: Sorry for my bad English, you know.

UPD: I foget to provide example of usage:

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

output:

2
1

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

攒一口袋星星 2024-10-25 00:02:54

一个想法:

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

An idea:

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

Single-value scopping is more explicit because you name the variable(s) in the block arguments. This abstraction has been called as, pipe, into, scope, let, peg, ..., you name it, it's all the same:

class Object
  def as
    yield self
  end
end

sum = ["1", "2"].map(&:to_i).as { |x, y| x + y } #=> 3
晚雾 2024-10-25 00:02:54

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

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

You can't specify the value that you want to initialize, but you can declare a variable as explicitly local to that block:

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

This will result in:

external value
1
2
3
external value
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文