【问题标题】:Ruby generate a lambda programmaticallyRuby 以编程方式生成 lambda
【发布时间】:2018-02-25 20:40:15
【问题描述】:

我正在尝试以编程方式生成lambda。这是一个例子:

这是我需要生成的矩阵:

m = [[a(t), b(t)],
     [c(t), d(t)]]

这是一个时间相关矩阵。如果abcd 函数始终相同,我将创建一个像这样的 lambda:

m = lambda{|t| [[a(t), b(t)], [c(t), d(t)]]}

并调用它:

m.call(x)

这些功能并不完全通用,但它们只能来自有限的列表。问题是我不知道在我执行一些计算之前,从这个列表中,函数将是哪些。例如,就我而言,我只有三个可能的函数,所以 lambda 可能是:

m = lambda{|t| [[f1(t), f2(t)], [f2(t), f3(t)]]}

m = lambda{|t| [[f3(t), f3(t)], [f1(t), f2(t)]]}

或这三个功能的任何其他组合。

有没有办法以编程方式定义lambdas?这是最好的方法吗?

在实际代码中,这个矩阵可能非常大,很容易有 500x10,000 (500,000) 个元素。它是在第一个循环中计算的。之后循环遍历t 值。对于每个t,功能当然不会改变。 此外,这些函数是简单的数学表达式,如幂、exp 等......

【问题讨论】:

  • 这些是f1f2、...方法还是函数(即其他lambda)?
  • 是的,完全可以,您可以使用高阶函数或 lambda:->(arg) { -> { arg } }.call(1).call == 1
  • @SebastianPalma 够公平的。我已经改写了。希望它现在更有意义。

标签: ruby lambda metaprogramming


【解决方案1】:

您可以将 lambdas 用于您的 fs 作为 m 的附加参数:

m = lambda { |t, a, b, c, d| [[a[t], b[t]], [c[t], d[t]]] }

f1 = lambda { |x| x**2 }
f2 = lambda { |x| x**3 }
f3 = lambda { |x| x**4 }

p m[2, f1, f2, f2, f3]  # [[4, 8], [8, 16]]
p m[2, f3, f3, f1, f2]  # [[16, 16], [4, 8]]

根据您的扩​​展问题,这是一种更具动态性的方法 并且可以扩展到大型矩阵。我假设你有一些算法 确定算法中哪一点需要哪些 lambda 的方法,但由于我不知道那是什么,所以我使用了表格规范。

# Dynamically create a 2-d array of lambdas, determined by an
# index set referencing the pool of lambdas, with specified row_length
m = lambda do |f_set, index, row_length|
  Array.new(index.size) { |i| f_set[index[i]] }.each_slice(row_length).to_a
end

# Function to evaluate actual outcomes yielded by applying
# the lambdas in m to argument x.
def evaluate(m, x)
  m.map { |row| row.map { |lmb| lmb[x] } }
end

# Pool of lambdas used to generate m
f_set = [
  lambda { |x| x**2 },
  lambda { |x| x**3 },
  lambda { |x| x**4 }
]

# You'll need some way to specify which lambdas will be used,
# either with table lookup (as below), or preferably via some
# algorithm if the array sizes will be large.
indices = [[0, 1, 1, 2, 0, 1], [2, 2, 0, 1, 0, 1]]

# create different sets of arrays m populated with lambdas as
# specified by indices to the f_set.
m_3x2 = indices.map { |index_set| m[f_set, index_set, 2]}
m_2x3 = indices.map { |index_set| m[f_set, index_set, 3]}

m_3x2.each { |m| p evaluate(m, 2) }
# [[4, 8], [8, 16], [4, 8]]
# [[16, 16], [4, 8], [4, 8]]
m_2x3.each { |m| p evaluate(m, 2) }
# [[4, 8, 8], [16, 4, 8]]
# [[16, 16, 4], [8, 4, 8]]


m_3x2.each { |m| p evaluate(m, 3) }
# [[9, 27], [27, 81], [9, 27]]
# [[81, 81], [9, 27], [9, 27]]
m_2x3.each { |m| p evaluate(m, 3) }
# [[9, 27, 27], [81, 9, 27]]
# [[81, 81, 9], [27, 9, 27]]

【讨论】:

  • Rojj,您问,“有没有办法以编程方式 [动态] 定义 lambda?”。显然,pjs 的 lambda m 不是动态创建的。如果您觉得a[t] 令人费解,它与a.call(t) 相同(也与a.yield(t)a===2 和[已弃用] a.(2) 相同)。见Proc。最后,如果你不需要传递它,你可以使用方法而不是 lambda。
猜你喜欢
  • 2011-04-27
  • 1970-01-01
  • 2010-09-06
  • 2018-06-23
  • 2018-08-14
  • 2023-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多