如果我想将一个值传递给 foo()、将其返回值传递给 bar()、将其返回值传递给 baz() 等,在 lua 中该怎么办?
附件 A(伪代码):
backwards(code(reading(like(not(do(I))))))
图表 B(伪代码):
local all = foo(...)
local this = bar(all)
local variables = baz(this)
local obscure_a_simple_idea = quux(variables)
在 F# 中此代码(源)
let numbers = [0..100]
let evenNumbers = List.filter isEven numbers
let doubledNumbers = List.map double evenNumbers
List.iter printNumber doubledNumbers
可以这样重写:
[0..100]
|> List.filter isEven
|> List.map double
|> List.iter printNumber
在 clojure 中这段代码(source)
(defn calculate []
(reduce + (map #(* % %) (filter odd? (range 10)))))
可以这样写
(defn calculate* []
(->> (range 10)
(filter odd? ,,,)
(map #(* % %) ,,,)
(reduce + ,,,)))
我知道茴香有线程宏。我想知道:我能用lua做什么?我错过了语言功能吗?有什么我不知道的众所周知的成语吗?我是否被迫在证据 A、证据 B 或迁移到茴香之间进行选择?
好消息:Lua 具有一流的功能,因此几乎所有这些都可以在普通 Lua 中实现! (不过,它可能更冗长和/或效率低下。)
让我们从函数组合开始:
function compose(f, g)
return function(...)
return f(g(...))
end
end
这仍然是“错误”的顺序:
f(g(x))
相当于compose(f, g)(x)
。
让我们在可变参数上写一个左折叠:
function foldl(f, acc, ...)
if select("#", ...) == 0 then
return acc
end
local l = ...
return foldl(f, f(acc, l, select(2, ...))
end
我们还定义恒等函数:
function id(...) return ... end
现在让我们来处理附件 A:
function compose_multiple(...) return foldl(compose, id, ...) end
compose_multiple(backwards, code, reading, like, dont)(I)
这仍然是倒着读。如果您不想这样做,只需定义一个相反的组合即可:
function compose_flipped(inner, outer)
return function(...)
return outer(inner(...))
end
end
(您也可以将其定义为
compose_flipped = compose(compose, function(x, y) return y, x end
;))
现在:
function chain(...) return foldl(compose_flipped, id, ...) end
chain(dont, like, reading, code, backwards)(I)
由于链接只是与另一个顺序的组合,它返回一个函数,因此参数仍然在右侧。如果您对此不满意,您可以自己编写一个接受参数并执行调用的函数,类似于 F# / Clojure 必须提供的线程:
function chaincall(arg, ...) return chain(...)(arg) end
现在您的附件 A 变为
chaincall(I, dont, like, reading, code, backwards)
。