From: Reuben T. <rr...@sc...> - 2004-01-31 20:35:45
|
> 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. I pretty much don't modify arguments unless the function is obviously intended to do that. I've never had performance problems, but I haven't run big or long-running programs. I've tried to encourage a functional style in general. > 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). And I consider arrays to be fixed length and monomorphic. Also, most of my list functions are indeed intended to be used on lists as lists (that functional style again). I'm not really sure which is better, but it's certainly better to be consistent. > I didn't see the need for a Set object. Mainly metamethods. Another tension I have sensed in building the libraries this far is between using Lua's freedom to do anything with tables for easy dynamic polymorphism on the one hand, against the propensity to get hard-to-find bugs this way, and the difficulty of actually knowing you have a function that does what you want (e.g. transpose = zip = unzip). Also type "safety". Also object orientation. Of course, with the Set code I give, you can use constructed sets directly if you want, and indeed pass ordinary tables to the methods. > 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. ...and given that Lua doesn't have any real type system, maybe that's the best thing to do, rather than giving an illusion of it. > bind: I think this name better describes what the function does. Agreed. > join: Does what you've called list.concat(). I chose join() to avoid confusion > with table.concat(), since that also acts on lists. table.concat is evilly named IMO. You either want string.join or fold(table, concat_function) when you use it. > 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. Can't you just use trim in the latter case? If there are two many functions half the users will never find the one they need and the others will just spend their time learning them all rather than getting work done. > map: My version is extended to allow multiple lists in parallel to be mapped > over (i.e. the transpose of your mapWith()). Or just zipWith, but with the lists as arguments rather than as a list of lists. > 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. In general I'm against recoding in C, except for a very few primitives. It's error prone, and the average programmer can't inspect it. > tail: You call this behead(). I was thinking of in-place modifications for argument list processing when I wrote it (originally I called it shift). I tend to agree with you about the rest. > My version is missing the extra numerical argument though. Easily fixed. > shallow_copy: You've called it clone(). I used the more explicit name to > distinguish it clearly from deep_copy(). It's a pity, because I prefer the shorter name. > deep_copy: I don't think you have this. No, I've never needed it. > 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? I think I've never needed anything more than table.empty. > 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... I like that. > dump: Dumps the contents of a table for debugging purposes. I'd like to have a pretty printer on my extended tostring for that. Anything I haven't commented on I agree with. Now I'm feeling rather daunted, however, mainly over all the table/list/set/array operations. I suggest the best way to proceed is to try to construct roughly the intersection of what we have between us (in terms of the size of the API), but with the union of functionality and, where possible, efficiency. How does that sound? Partly I'm worried about alienating programmers without experience of functional languages by making the interface as aggressively functional as it is at the moment; partly I feel this is a great opportunity to educate, and I am also encouraged by reading the book "A Small Matter of Programming" about "programming" by users (e.g. in spreadsheets (formulae, not macros) and CAD systems (templates)) which mentions that the greatest sticking point that most users have when trying to learn anything like a general-purpose programming language (e.g. spreadsheet macro language) is with the control-flow stuff. The great thing about map, zip & friends is that you avoid control-flow (other than if-then-else, which was found easier to grasp). Encouraging Lua programmers to give their users functional primitives that they can use to write typically one-to-three line programs without needing to understand while or for might be a big win, albeit a rather visionary one. Perhaps the terminology might need to be refined: map is a rather mathematical word. But the idea that if you have a list of things and a function that works on one then you can say map (f, list) is much more obvious than trying to explain for x in list f (x) end -- http://www.mupsych.org/~rrt/ | certain, a. insufficiently analysed |