2012-02-09 79 views
3

我割我的牙齿和Lua,并试图执行一些列表的处理逻辑。我不确定我是否真的掌握了协程和匿名函数的功能,但我正在尝试。我知道这些东西在Ruby/Groovy/Javascript等其他脚本语言中是如何工作的,我想要在Lua中做一些同样聪明的事情。下面是我想出为例:Lua DSL还是聪明的关闭?

model = { { player = "Cliff", age = 35, gender = "male" }, { player = "Ally", age = 36, gender = "female" }, { player = "Jasmine", age = 13, gender = "female" }, { player = "Lauren", age = 6.5, gender = "female" } } 

function allplayers() 
    return coroutine.create(function() 
     for idx, each in ipairs(model) do 
      coroutine.yield(idx, each) 
     end 
    end) 
end 

function handlePlayers(source) 
    local status, idx, each = coroutine.resume(source) 
    while each do 
     print(idx, each.player) 
     status, idx, each = coroutine.resume(source) 
    end 
end 

function having(source, predicate) 
    return coroutine.create(function() 
     local status, idx, each = coroutine.resume(source) 
     while each do 
      if predicate(each) then 
       coroutine.yield(idx, each) 
      end 
      status, idx, each = coroutine.resume(source) 
     end 
    end) 
end 

handlePlayers(having(allplayers(), function(each) return each.age < 30 end)) 

理想我想能写这样的代码:

allplayers(having(function(each) return each.age < 30 end)) 

甚至更​​好:

allplayers(having({each.age < 30 })) 

以产生相同的输出,但我无法完全理解如何或者甚至是否可以做到这一点。上面的东西对于所有的迭代和循环以及所有的东西来说似乎太冗余了。有没有更好的方法来做到这一点? (男孩,我想念编码在Groovy,因为总有做的东西更巧妙的方式...)

+2

“男孩,我怀念在Groovy编码,因为总有做的东西更巧妙的办法......”如果你在打算在Lua编程,再编程* *的Lua。不要希望语言是别的东西,并学会用Lua的方式做事。 – 2012-02-09 18:42:11

+2

放松!我喜欢Lua,这就是为什么我花时间学习它。 :)我只是做了常规的参考,因为这是浮现在脑海,当我贴出第一件事,“有一定有做这一个更巧妙的办法......” – Cliff 2012-02-09 21:39:55

回答

4

如果您不需要重复使用过滤结果,考虑一个迭代器:

model = { 
    { player = "Cliff", age = 35, gender = "male" }, 
    { player = "Ally", age = 36, gender = "female" }, 
    { player = "Jasmine", age = 13, gender = "female" }, 
    { player = "Lauren", age = 6.5, gender = "female" } 
} 

function model:having(predicate) 
    local index = 0 
    return function() 
     while true do 
      index = index + 1 
      if index > #self then break end 
      if predicate(self[index]) then return self[index] end 
     end 
    end 
end 

for item in model:having(function(m) return m.age < 30 end) do 
    print(item.player) 
end 
+0

哦,我喜欢这种方法!比我所做的更干净,非常接近我所需的语法! :)让我在选择最终答案之前查看其他答案。 – Cliff 2012-02-09 21:41:43

0

这是令人难以置信的过于复杂和过度设计。你想通过谓词过滤一个列表。那样做;这是一个简单的循环。只是写它。

即使你绝对必须以多功能风格做到这一点(Lua是不是功能性语言,它可以工作的方式,但它不是功能),协同程序是不恰当的。

观察:

model = { 
    { player = "Cliff", age = 35, gender = "male" }, 
    { player = "Ally", age = 36, gender = "female" }, 
    { player = "Jasmine", age = 13, gender = "female" }, 
    { player = "Lauren", age = 6.5, gender = "female" } 
} 

function for_each_array(list, operation) 
    for key, value in ipairs(list) do 
    operation(value) 
    end 
end 

function filter_if(list, predicate) 
    return function(value) 
    if(predicate(value)) then 
     list[#list + 1] = value 
    end 
    end 
end 

local list = {} 
for_each_array(model, filter_if(list, function(each) return each.age < 30 end)) 

for_each_array(list, function(each) print(each.player) end) 

看到了吗?根本不需要协程。

+0

你能否详细说明的Lua如何不是一个功能性的语言?除了一流的功能,这通常是足以在俱乐部被允许,它也有适当的尾调用(它的JavaScript,Python和甚至一些的Lisp缺乏)。 – ponzao 2012-02-09 21:07:20

+0

我想你错误地理解了我想要达到的目标。我上面的例子是故意微不足道的,旨在作为学习练习以及推动/发现语言限制的方式。我正在寻找一种可以用于更多涉及代码的语法弯曲方法。这样的方法将会优雅地阅读而不会过于冗长。我将避免关于功能性与非功能性的争论。 – Cliff 2012-02-09 21:50:43

1

您可能希望尝试Underscore.js JavaScript库后Underscore.lua建模。

你的榜样应该是这样的:

_ = require 'underscore' 
model = { 
    { player = "Cliff", age = 35, gender = "male" }, 
    { player = "Ally", age = 36, gender = "female" }, 
    { player = "Jasmine", age = 13, gender = "female" }, 
    { player = "Lauren", age = 6.5, gender = "female" } 
} 
result1 = _.select(model, function(p) return p.age < 30 end) -- traditional way 
result2 = _(model):select(function(p) return p.age < 30 end) -- object-oriented style, calls can be chained 
assert(_.is_equal(result1, result2)) 

注意,Lua中不会给你任何其他语法糖(除了:运营商)。如果你真的想更短的语法,你应该看看Metalua,它允许您更改语言,和出的现成提供以下功能的短语法:

result = _.select(model, |p| p.age < 30) 
+0

非常有趣的方法,但我试图保持我的依赖最小。我肯定会更深入地考察下划线和metaLua的未来需求。 – Cliff 2012-02-09 21:45:02

+1

单参数调用的可选括号(如在这个答案中的require调用)也是Lua提供的一种遗忘的语法糖。容易被滥用,但对DSL有用。 – kikito 2012-02-10 17:29:11