Something like let in Ruby

眉间皱痕 提交于 2019-12-04 04:44:20

问题


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

回答1:


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



回答2:


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


来源:https://stackoverflow.com/questions/5010828/something-like-let-in-ruby

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!