我有一个存储为字符串的“公式”数据库。为简单起见,我们假设每个公式包含 2 个变量,分别用 a 和 b 表示,并且这些公式都是格式正确的,并且确保它只包含集合 ()ab+-*
中的字符。
在运行时,从该数据库中获取公式,并从另一个来源获取 a 和 b 的数值,并对公式求值。评估可以像这样编程:
# This is how it works right now
formula = fetch_formula(....)
a = fetch_left_arg(....)
b = fetch_right_arg(....)
result = eval(formula)
这个设计可行,但我并不完全满意。它要求我的程序命名自由变量与它们在公式中的命名完全相同,这很丑陋。
如果我的“公式”不是字符串,而是接受两个参数的 Proc 对象或 Lambda,我可以做类似的事情
# No explicitly named variables
result = fetch_proc(...).call(fetch_left_arg(....),fetch_right_arg(....))
但不幸的是,公式必须是字符串。
我尝试以下列方式进行实验:如果从数据库中获取公式的方法将字符串包装成某种东西,其行为类似于 block ,并且我可以将参数传递给它,那会怎么样?
# This does not work of course, but maybe you get the idea:
block_string = "|a,b| #{fetch_formula(....)}"
当然我不能评估这样一个block_string,但是有没有类似的东西我可以使用?我知道 instance_eval
可以传递参数,但我应该将它应用于什么对象?所以这也许也不是一个选择....
最佳答案
这是非常讨厌的方法,但对于您提到的简单公式,它应该有效:
▶ formula = 'a + b'
▶ vars = formula.scan(/[a-z]+/).uniq.join(',') # getting vars names
#⇒ "a,b"
▶ pr = eval("proc { |#{vars}| #{formula} }") # preparing proc
▶ pr.call 3, 5
#⇒ 8
这里我们依赖于这样一个事实,即参数以相同的顺序传递给 proc
,因为它们出现在公式中。
关于Ruby:使用变量的动态绑定(bind)评估字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35274367/