Skip to content

Instantly share code, notes, and snippets.

@ujihisa
Created April 13, 2019 12:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ujihisa/7ee86d0b987d67d9ba544ddb776809d7 to your computer and use it in GitHub Desktop.
Save ujihisa/7ee86d0b987d67d9ba544ddb776809d7 to your computer and use it in GitHub Desktop.
def put_in_f(hash, keys, value)
if keys.empty?
value
else
car, cdr = [keys[0], keys[1..]]
hash.merge(car => put_in_f(hash[car], cdr, value))
end
end
def extract(binding, ast)
case ast.type
when :SCOPE
extract(binding, ast.children[2])
when :CALL
selv, methot, args = ast.children
if methot == :[]
keys, varname = extract(binding, selv)
[[*keys, args.children[0].children[0]], varname]
else
raise NotImplementedError
end
when :DVAR
[[], binding.local_variable_get(ast.children[0])]
when :GVAR
[[], eval(ast.children[0].to_s)]
when :IVAR
[[], binding.receiver.instance_variable_get(ast.children[0])]
when :FCALL, :VCALL
[[], binding.eval(ast.children[0].to_s)]
else
raise NotImplementedError, "ast.type #{ast.type} is not supported yet"
end
end
def put_in(b, value)
ast = RubyVM::AbstractSyntaxTree.of(b)
keys, hash = extract(b.binding, ast)
put_in_f(hash, keys, 150)
end
users = {
ujihisa: {
email: 'a@a.a',
wallet: {
money: 120,
},
},
}
users2 = put_in(-> { users[:ujihisa][:wallet][:money] }, 150)
# this put_in behaves like
# users.merge(ujihisa: users[:ujihisa].merge(wallet: users[:ujihisa][:wallet].merge(money: 150)))
# to create an updated version of the given hash
p users
p users2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment