From: Richard J. <ri...@an...> - 2005-02-17 23:47:28
|
A common pattern, one which I use frequently anyway, is to write a pair of functions like this: let add_elem, get_elems = let elems = ref [] in let add_elem r = elems := r :: !elems in let get_elems () = List.rev !elems in add_elem, get_elems;; followed by imperative-style code to add elements to the list, and finally return the list with get_elems (). Could ExtList contain such a "list building" function? ie. It would be a function which returned a pair of functions as above, something like: let add, get = ExtList.List.build () where build would be defined as: let build () = let xs = ref [] in let add x = xs := x :: !xs in let get () = List.rev !xs in add, get Thoughts? Rich. -- Richard Jones, CTO Merjis Ltd. Merjis - web marketing and technology - http://merjis.com Team Notepad - intranets and extranets for business - http://team-notepad.com |
From: skaller <sk...@us...> - 2005-02-18 00:53:24
|
On Fri, 2005-02-18 at 10:47, Richard Jones wrote: > A common pattern, one which I use frequently anyway, is to write a > pair of functions like this: > > let add_elem, get_elems = > let elems = ref [] in > let add_elem r = elems := r :: !elems in > let get_elems () = List.rev !elems in > add_elem, get_elems;; > > followed by imperative-style code to add elements to the list, and > finally return the list with get_elems (). I do this often, but I don't really think it warrants inclusion in the library, I doubt I'd remember the name of the function, also, often I prefer to get the list reversed. In addition, it fixes the list to start empty, sometimes I need a starting list, and it also hides the list during construction, whereas I sometimes need to pattern match on it or other things. OTOH the actual idiom let elems = ref [] in .. elems := .. :: !elems .. is fairly simple and only requires one name to be invented, instead of two. The library code does provide some abstraction, but not enough I think. Of more interest to me, and also probably not worth having in the library is: let direction_t = [`f | `r] let 'a d_list_t = private { d: direction_t; l: 'a list } mkfwd l mkrev l getfwd l getrev l getlst l isfwd l which keeps track of the direction of a list: at present I use lots of multi-pass algorithms and find it so hard to track the direction of a list, I've adopted the convention they're always forward, sometimes writing l .. (* in reverse order *) let l = rev l in (* enforce convention *) .. let l = rev (x:: (rev l)) to append an element .. when the list was naturally in reverse order anyhow. The wrapper I suggest uses 'getfwd' and 'getrev' to get the list in a particular order, but now I can write routines that pass d_list_t about, and note that any order independent processing can be done efficiently, and order dependent processing is self-optimising. But I doubt this is generally useful enough to put in a library .. and the encoding is quite simple. Note your suggestion and mine are related messily, I sometimes build lists imperatively and sometimes functionally, and it is a mess. I also sometimes destroy list with a tail recursion, sometimes with an imperative structure and a loop and sometimes using an HOF... I think it is probably better to leave this mess exposed, and NOT to abstract it, so it is easier to refactor. This is also why I use lots of algebraic data types instead of abstractions, even when the latter seems appropriate -- abstractions break with design changes and refactorings. -- John Skaller, mailto:sk...@us... voice: 061-2-9660-0850, snail: PO BOX 401 Glebe NSW 2037 Australia Checkout the Felix programming language http://felix.sf.net |