From: Jamie W. <j...@jm...> - 2004-01-31 19:15:33
|
On Friday 30 January 2004 20:22, Reuben Thomas wrote: > > Attached is the standard library I've been gathering. It's rather smaller > > than yours and duplicates some of the contents, but it also has some new > > functions which you might want to consider for inclusion. > > Thanks very much for this. It does look as though there are some handy > additions to stdlib here. > > Hi. I've had a look, and there's a lot of overlap, but also differences of > approach. It would be very helpful if you could tell me which functions > are new (i.e. not in stdlib) and which you think are better (either in > functionality, documentation, or implementation) in your version, as I'm > bound to miss things otherwise. Ok, here goes: Firstly, functions in my library do not modify their arguments unless you use the *_inplace versions which exist for some functions. I think this avoids confusion and having both versions could reduce unnecessary copy operations. Also, I use the notation 'array' to refer to the tables you call 'lists' because it seems to me that they have access semantics more like arrays, whereas lists I consider to mean sequential structures such as functional-style recursive lists (or more generally linked lists). I didn't see the need for a Set object. I just defined a set as a table with all values true. Given Lua lists/arrays, this seems more in keeping. I see you've made it an object because you want to, e.g. set 'table' as the __index table for tables, and that doesn't work for sets. I decided against that approach because you can't rely in it, e.g. it doesn't hold for 'arg', which is otherwise a list/array, and other modules might not use the convention. succ: mainly convenient as an argument to generate() curry: The function that you call curry() does what I have called bind(), i.e. partially applies a function. My curry() function converts the function into a curried version. Certainly much less useful than bind(), but notable as something distinct. Probably needs rewriting in C eventually for speed. bind: I think this name better describes what the function does. bind_method: Just a convenience to avoid passing the table name twice when binding a table method. conjunction: Mainly useful to build parameters to filter() join: Does what you've called list.concat(). I chose join() to avoid confusion with table.concat(), since that also acts on lists. split: I think my implementation is probably more efficient (although admittedly I haven't tested it very thoroughly). split_words: I distinguished this from split(), because usually when you split on, e.g. commas, you want to preserve leading and trailing blank fields, whereas usually when you split on whitespace, you don't. ltrim, rtrim, trim: Remove edge whitespace. I don't think these are present in your library. map: My version is extended to allow multiple lists in parallel to be mapped over (i.e. the transpose of your mapWith()). There's a performance hit though for the typical case. That could be virtually eliminated by coding in C (better vararg handling), and this a very commonly useful function, so I think that would be the best option in the long run. In the meantime, maybe this should be added but under a different name. map_tbl, filter_tbl: Like map and filter, but for general tables. tail: You call this behead(). My version returns a new table (and there is no tail_inplace() version since the difference in efficiency is minimal and I was too lazy). tail() is the more common name for this function, esp. in functional programming circles. My version is missing the extra numerical argument though. cons: Adds a single value to the start of an array. Just a common special case of join(). Again, it's a functional thing. shallow_copy: You've called it clone(). I used the more explicit name to distinguish it clearly from deep_copy(). deep_copy: I don't think you have this. I've just noticed some bugs in my implementation though. Corrected and better tested implementation below. getter: Useful to build arguments to map() and filter(), e.g. std.map(std.getter("x"), t) returns { t[1].x, t[2].x, ... }. method: Useful to build arguments to map() and filter(), e.g. std.map(std.method("x", y), t) returns { t[1]:x(y), t[2]:x(y), ... }. I use this one all the time. generate: Builds sequences, i.e. generate(f, s, n) returns the n-element table { s, f(s), f(f(s)), f(f(f(s))), ... }. override: Serves as your Set.union() and table.merge(). intersect, difference: Again, work on sets and tables. size: Returns the size of a table or set (not list/array). I'm surpised I didn't see this one in your libary. Have I missed something? op[*]: Function forms of the operators, extended to many arguments where appropriate. I used the symbols rather than naming them to avoid confusion (subtract or minus?). Not entirely sure if that was worth it though. Useful in parameters to map, filter, generate... dump: Dumps the contents of a table for debugging purposes. -- Jamie Webb function std.deep_copy(t) local r = {} local d = { [t] = r } local function h(o,x) for k,v in pairs(x) do if type(v) == "table" then if not d[v] then d[v] = {} local q = h(d[v], v) o[k] = q else o[k] = d[v] end else o[k] = v end end return o end return h(r, t) end |