gpt4 book ai didi

ruby - 在 block 中拦截 def

转载 作者:数据小太阳 更新时间:2023-10-29 08:12:49 26 4
gpt4 key购买 nike

我有一个方法需要在附加 block 上做一些巫术。这种 block 的样本可能是

myMethod do 

somemethod x
someother y
def name(a,b)
a+b
end
end

前两个方法调用(somemethod xsometother y)应该正常执行。但是我想在不实际定义新方法的情况下拦截方法定义(作为 S 表达式)。如果我将整个 block 转换为 S 表达式然后搜索 AST,我就可以做到这一点。但是,我需要弄清楚如何调用这些方法。任何一个的解决方案都可以。也就是

  • 截取定义,转换为S-expression(Ruby2Ruby可以理解的)
  • 将 block 转换为 S 表达式并找到方法调用并执行它们

编辑我正在寻找的 AST 类似于

[:defn,
:name,
[:args,:a,:b],
[:call,
[lvar,:a],
:+
[lvar,:b]]]

最佳答案

如果我理解正确,您希望能够在传递给另一个方法的代码块中定义一个方法,但拦截该内部方法定义,以便它实际上不会被定义,而是被转换为 S 表达式?因此,您希望它的行为几乎就像它被注释掉并且一些外部进程已经通过源代码并将实现解析为 S 表达式一样?

类似于:

myMethod do 

somemethod x
someother y
# def name(a,b)
# a+b
# end
end

somemethodsomeother 仍然执行的地方,定义了 name 的实现,但是被 Ruby 解释器忽略了。然后你想以某种方式将此实现捕获为 S 表达式。通过注释掉它显然不会像这样完成,但它是我描绘行为的好方法。

好吧,RubyParser gem 可能会做你想做的事。它利用了将“此处文档”作为字符串传递给方法的能力,如本例所示:

def x (str)
str
end

x( <<-EOF )
this is
a here
document
EOF

# => "this is\n a here\ndocument\n"

使用 RubyParser,您可以执行以下操作:

require 'ruby_parser'
require 'pp'

pp RubyParser.new.parse( <<-EOF )
def plus(x,y)
x+y
end
EOF
# => s(:defn, :name, s(:args, :a, :b), s(:call, s(:lvar, :a), :+, s(:lvar, :b)))

然后,将它与您想要的代码合并将是一件微不足道的事情,如下所示:

require 'ruby_parser'

def myMethod
x = yield
end

def somemethod( x )
puts x
end

def someother( y )
puts y
end

x = 'magic'
y = 'output'

sexp = myMethod do
somemethod x
someother y
RubyParser.new.parse( <<-EOF )
def name(a,b)
a+b
end
EOF
end

pp sexp
name(1,2)
# magic
# output
# s(:defn, :name, s(:args, :a, :b), s(:call, s(:lvar, :a), :+, s(:lvar, :b)))
# NoMethodError: undefined local variable or method 'name' for main:Object

如您所见,方法定义本质上只是一个字符串,可以这样操作。

关于ruby - 在 block 中拦截 def,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16054876/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com