Lua DSL или умные замыкания? - PullRequest
       1

Lua DSL или умные замыкания?

3 голосов
/ 09 февраля 2012

Я режу зубы с помощью Lua и пытаюсь реализовать некоторую логику обработки списка.Я не уверен, действительно ли я понимаю силу сопрограмм и анонимных функций, но я пытаюсь.Я знаю, как это работает в других языках сценариев, таких как Ruby / Groovy / Javascript, и я хочу сделать что-то столь же умное в 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 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, потому что всегда был отличный способ сделать что-то ...)

Ответы [ 3 ]

4 голосов
/ 10 февраля 2012

Если вам не нужно повторно использовать отфильтрованный результат, рассмотрите итератор:

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
1 голос
/ 09 февраля 2012

Вы можете попробовать Underscore.lua по образцу библиотеки Underscore.js JavaScript.

Ваш пример будет выглядеть так:

_ = 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 голосов
/ 09 февраля 2012

Это невероятно усложняется и чрезмерно усложняется. Вы хотите отфильтровать один список с помощью предиката. Так сделай это; это простая петля. Просто напишите это.

Даже если вам абсолютно необходимо сделать это в функциональном стиле (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)

См? Нет необходимости в сопрограммах вообще.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...