Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion

Linq for Lua (functional collection class)
  • EricEric
    Posts: 20

    I've put together a class that gives similar functionality in Lua for what Linq let's you do in C#. Most anyone who's worked with C# fairly recently is probably somewhat familiar with Linq and the lambda notation that works with it. It pretty much comes down to being able to query and work with collections with similar constructs like you can in SQL (ie. select, where, aggregate functions).

    Here's a snippet from my example program below that hopefully gives a general idea of how my class works in Lua.

    nyEmpCities = emps:where(function(e) return e.address.state == "NY" end):
                   select(function(e) return e.address.city end):distinct()
    

    emps is a previously populated collection that is of the type of my new class: LinqArray. It holds employee info for a number of employees. That snippet shows how to pull out the employees that live in NY, then pulls out the cities each of those employees live in, and lastly returns just a distinct list of those cities in NY and stores it in another variable.

    There are a decent number of methods included with the LinqArray class: min, max, sum, avg, removeWhere, along with the core ones above and a few others.

    I know working in C# being able to query and work with collections with Linq greatly reduces the amount of code I have to write. I just figured having a similar library in Lua would be useful. In no way is that class optimized and there are probably some bugs in it.

    http://pastebin.com/gKzxTCtp is the LinqArray class. http://pastebin.com/3ig2FmVN is an example program that uses the LinqArray class. It just prints output, but the code should be fairly straight forward to understand.

  • SimeonSimeon
    Posts: 3,635

    This will be great for heavily data-driven projects. Thank you for sharing it.

    I really like the API design as well, it is a bit reminiscent of SQL.

  • HerwigHerwig
    Posts: 118

    Very nice! This will definitely come in handy someday...!

  • (Newbie question) Recently starting using Lua on a in-studio designed tool. Having used C# and LINQ before this seems like an EXCELLENT idea.

    However, the scripts immediately halts at the first line "LinqArray = class()". What is class? a function you made that returns a table? ("{}") something like that?

  • EricEric
    Posts: 20

    "class()" is a special function that's part of the Codea framework, although it could be used outside of the Codea application I believe. The code for it can be found here, about half way down the page: https://bitbucket.org/TwoLivesLeft/codea/wiki/CodeaClasses It just helps with things like inheritance.

    This Linq library is very basic and probably could be written to be more efficient. It was just something I messed around with because I also come from a C# background.

  • Thanks a lot! Wow... lot's of trickery inside there. Class is working now. This will require some deep-diving for sure to really understand it : )

  • Well, first of all, thanks a lot for this initiative. Been using this class more often than not through the last couple of years. It came the time where I needed to 'groupBy' a "hashFunction" let's say. To be able to do List().GroupBy((p) => p.Name); kind of thing for example.

    How would you go about it? Creating a separate class called something like 'linqGroup'? The reason I ask is because I tried to continue using the linqArray class, linqArray:groupBy() would basically return a linqArray of linqArrays, however it ends up being more like a 'dictionary' of KeyValue pairs (where Value is a linqArray), and most iterators inside linqArray class are using "ipairs".

    Suppose the same "person" example. local persons = {"Bob", "Bob", "Bob", "Ted", "Sarah", "Sarah"} -- Group by the same array values. local persons_grouped = linqArray(persons):groupBy(fn (e) return e end) -- Up to here everything gets grouped neatly.

    local non_repeated = linqArray(persons):where(fn(g) return g:count() == 1 end) -- returns empty linqArray. print(persons_grouped:count()) -- returns 0. Panic shows its ugly face. print (table.length(persons_grouped)) -- returns 3. This one uses pairs to count.

    Is there a specific reason why most iterations are done with ipairs? Performance reasons? Do you know if it could be safe to change to 'pairs' the iterations?

    Thanks a lot in advance.