A few days ago I was given a programming assignment. It was pretty simple. In fact it was so simple that I still cannot decide whether the challenge is whether I could follow instructions or whether I could see deeply enough into the assignment to find all of the traps… or were those traps meant for discussions later or was the whole thing there to determine if I knew enough Perl idioms to be a viable candidate.
So now that the assignment is complete and submitted I decided to implement the assignment in GO and Lua. I might even do a python and Ruby version but not right now. Maybe tomorrow.
The assignment: Write a program that could take as input any number of files that are presorted and merge the input file(s) preserving the sort order and keeping the amount of memory usage to a minimum. And you cannot use external shell commands.
That was pretty much it. The assignment missed a number of issues:
(1) what do do when no files are provided
(2) what to do when 1 file is provided (presumably return that file; but I did not do that)
(3) what happens when one or more filenames are repeated
(4) what happens when the file is either empty or only contains comments
(5) what about comments distributed randomly in the file
That’s all I can come up with from memory. Now to my solution. Just so I’ve said it… I’m not a Lua expert and for that matter I did not sleep at a Holiday Inn Express last night so while I feel certain that there may be some optimizations here and there my contention is that Lua, while interesting, has not made the cut in spite of WOW, LR, FS etc…
(complaint #1) Given the number of ways to get the number of items in a table is troublesome. Especially if you are implementing an array with holes in the index(sparse table) list like: 1, 2, 4, 5 the typical #table will yield a result of 2 which is the wrong answer. And while everything is supposed to be a table one would think that the same length functions would apply to the string. (see my len() function)
(complaint #2) The string manipulation functions are limited to a set of primitives that can be used to implement the functions that are missing. For example: trim(), rtrim(), ltrim(). The real issue here is that there is no indication as to which standard functions would implement the function best. Part of that it implementation details and the other part is keep the source code small so that there is that much less to care and feed.
(complaint #3) use of the arg table is strictly non-standard. It looks nothing like C, Perl, Python or Ruby. The fact that it’s a table (array) is only part of the problem. In order to count the number of user parameters you have to delete 2 from the len() of the array. The problem here is that “lua” is the first parameter and therefore if this were compiled instead of interpreted code the item could be absent from the table and would therefore cause my len(arg)-2 to fail.
(complaint #4) the absence of a formatted print. Instead Lua implements a formatted string.
(complaint #5) in the various loop structures there is no next, last, continue, just a break.
(complaint #6) there is nothing special about Brazil that could possibly justify using ~= as the “not equals” operator.
(complaint #7) the file i/o is just plain clunky. The idea that once you open a file, that file is considered the “current” file and that from there on you can perform certain io operations on the current. But that they do not provide decent examples on how to switch current. Instead I had to find examples of file io that mixed a could of the functions: io: and file:.
(complaint #8) pairs() is a nice function but it would also be nice to have a keys() function too.
(complaint #9) the commenting is similar to many SQL dialects but it’s still trouble; specially when the first line of the file is the #!/usr/bin/env and therefore you are mixing comment types. Unless there is some purist manual that says that the first line of any script file that includes an external directive is not really owned by the program… MEH
(complaint #10) there are two ways to delete items from a table. If the table is indexed as an array then table.delete() is the preferred method. If the table is a hash then assigning a nil to the value is preferred. And that’s when I get really annoyed. “preferred”? Are you kidding me. There is no other way. And I had to find this nugget of information after a search on an 3rd party site.
(complaint #11) the docs. They are better than most but they still suck. In some cases the grammar is terrible but if you get past that it’s simply incomplete. Many of the functions are not described completely. Whether it’s input/output or just a simple functional description and sometimes an example. (see file:read)
I think I have a few more complaints in me but I’m done for now. I may write-up my experience with GO in comparison as it’s not without it’s warts but that is a topic for another day.