From: Brian H. <bri...@ql...> - 2003-02-28 22:36:08
|
On Fri, 28 Feb 2003, Nicolas Cannasse wrote: (attribution lost) > > (* like perl's chomp function, remove trailing newline characters *) > > - val String.chomp : string -> string > > Uhm, why not, but this need some discuss on implementation since newline is > "\r\n" under windows and "\n" under *nix.... I'd recognize either: let chomp s = let leAn = String.length s in if ((len > 0) && (s.[len - 1] == '\n')) then if ((len > 1) && (s.[len - 2] == '\r')) then String.sub s 0 (len - 2) else String.sub s 0 (len - 1) else s ;; Just IMHO. Brian |
From: Manos R. <er...@cs...> - 2003-03-01 00:47:52
|
On Fri, Feb 28, 2003 at 12:38:12PM +0900, Nicolas Cannasse wrote: > > (* fold left on file lines (without trailing newline), I don't know in > > which module this functions should go, maybe Sys? *) > > - val fold_file : ('a -> string -> 'a) -> 'a -> string -> 'a > > (* iter on file lines *) > > - val iter_file : (string -> unit) -> string -> unit > > perhaps : > > val iter_in : (string -> unit) -> in_channel -> unit > val map_in : (string -> 'a) -> in_channel -> 'a list > val fold_in : ('a -> string -> 'a) -> 'a -> in_channel -> 'a > > are better so it can work on many kind of descriptors and does not have to > handle the "file not found" problems > > I propose also : > > val read_lines : in_channel -> string list > val read_all : in_channel -> string > > that returns all the contents ( up to End_of_file ) I think that all of those can be done much better with Streams (the streams that are in the Stream standard module). Something like Stream.of_lines (ic:in_channel) : string Stream.t Of course, that means that we need the equivalent iter, map, and fold in Stream, like val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b Stream.t -> 'a val map : ('a -> 'b) -> 'a Stream.t -> 'b Stream.t -- Manos |
From: Stefano Z. <za...@bo...> - 2003-03-02 09:41:21
|
On Fri, Feb 28, 2003 at 07:47:34PM -0500, Manos Renieris wrote: > Of course, that means that we need the equivalent iter, map, and fold > in Stream, like > val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b Stream.t -> 'a > val map : ('a -> 'b) -> 'a Stream.t -> 'b Stream.t Those functions could be useful also by themselves and IMO should be added to the Stream module. BTW the Stream.map function simplest implementation is: let map f s = Stream.from (fun _ -> Some (f (next s))) anyway using such an implementation you will get a stream that couldn't be mixed with "normal" streams (i.e. streams not built using Stream.from), this can be ok, but should be definitely mentioned. Cheers. -- Stefano Zacchiroli - Undergraduate Student of CS @ Uni. Bologna, Italy zack@{cs.unibo.it,debian.org,bononia.it} - http://www.bononia.it/zack/ " I know you believe you understood what you think I said, but I am not sure you realize that what you heard is not what I meant! " -- G.Romney |
From: Stefano Z. <za...@bo...> - 2003-03-02 09:51:06
|
I've dug a bit more in some old ocaml sources and I've found some additional functions that IMO are worth while to be inserted in the standard library: (* find functions on arrays, similar to List's *) val Array.exists: ('a -> bool) -> 'a array -> bool val Array.for_all: ('a -> bool) -> 'a array -> bool val Array.find: ('a -> bool) -> 'a array -> 'a (* rotations on lists and arrays, step defaults to 1 *) val Array.lrotate: ?step:int -> 'a array -> 'a array val Array.rrotate: ?step:int -> 'a array -> 'a array val List.lrotate: ?step:int -> 'a list -> 'a list val List.rrotate: ?step:int -> 'a list -> 'a list Hope this helps. Cheers. -- Stefano Zacchiroli - Undergraduate Student of CS @ Uni. Bologna, Italy zack@{cs.unibo.it,debian.org,bononia.it} - http://www.bononia.it/zack/ " I know you believe you understood what you think I said, but I am not sure you realize that what you heard is not what I meant! " -- G.Romney |
From: Stefano Z. <za...@bo...> - 2003-03-02 10:03:39
|
On Thu, Feb 27, 2003 at 02:51:58PM +0100, Stefano Zacchiroli wrote: > > That would help. Thanks. I've dug a bit more on some old ocaml sources and I've found some additional functions that IMO should be included in the standard library: (* find functions on arrays *) - val Array.exists: ('a -> bool) -> 'a array -> bool - val Array.for_all: ('a -> bool) -> 'a array -> bool - val Array.find: ('a -> bool) -> 'a array -> 'a (* rotations on arrays and lists, step defaults to 1 *) - val Array.lrotate: ?step:int -> 'a array -> unit - val Array.rrotate: ?step:int -> 'a array -> unit - val List.lrotate: ?step:int -> 'a list -> 'a list - val List.rrotate: ?step:int -> 'a list -> 'a list Probably all functions added to the Array module should also be added to the Bigarray one, but I've never used it ... Cheers. -- Stefano Zacchiroli - Undergraduate Student of CS @ Uni. Bologna, Italy zack@{cs.unibo.it,debian.org,bononia.it} - http://www.bononia.it/zack/ " I know you believe you understood what you think I said, but I am not sure you realize that what you heard is not what I meant! " -- G.Romney |
From: Brian H. <bri...@ql...> - 2003-02-25 21:54:25
|
On Wed, 26 Feb 2003, John Max Skaller wrote: > I personally DESPISE make and friends, I think they're > total garbage. While they automate some tasks nicely, > trying to fool make into doing all the build/test/install > tasks correctly requires considerably expertise and hackery. I have to agree with you there. Plain make is nigh unto unusable, even for a small project (dozens of files). Requiring gnu make helps, but doesn't solve the problem- for example, how do you write a rule that deals with yacc outputting both a foo.c and a foo.h, such that if either file needs to be rebuilt yacc is run, but if both files need to be rebuilt yacc is only run once? I still haven't solved that one. And I'm not sure it's solvable. For the record, I also dislike ant. If I was willing to forego partial recompilation and dependency checking, I'd write a fargin shell script. Brian |
From: Nicolas C. <war...@fr...> - 2003-02-26 01:30:23
|
> >> For that, we already have a decomposition to follow, that of the > >> standard library itself. We need a name, a license, a compilation > >> strategy, and an installation strategy. > > I think we should be careful here. In my opinion Boost went entirely > off the rails by chosing a special make tool, and then modifying > that so that to actually build boost became a total nightmare. > > They failed to follow my recommendation:-) > > I recommended Python script as the build tool, and they > thought it was 'too heavy' which of course turned out > to be a joke compared to having to download and build > a custom tool -- which needed constant modification. <snip> > Well, we should probably use ocaml script instead :-) That's Ocamake, Thanks for your support John :) Nicolas Cannasse |
From: Brian H. <bri...@ql...> - 2003-02-25 16:15:27
|
More comments comming soon. I have 2.5 libraries I've written I'd like to see included. They (and their status) are: - Psqueue, implementing a Priority Search Queue ala: http://www.informatik.uni-bonn.de/~ralf/talks/ICFP01.pdf This data structure has the best features of both a priority queue (O(1) find the highest priority element, O(log n) remove the highest priority element) and search trees (O(log n) to add, find, modify the priority of, or remove any element). It is purely applicative. It is commented, cleaned up, and forgotten at home at the moment. - Bitset, implementing an unordered set of unique small integers as a bitfield. Adding or removing and element and checking to see if an element is contained in the set are all O(1). It is imperitive in style. I need to add a couple of functions (just remembered I forgot union and intersection) and commenting and it'll be ready to go. - Regex, a regular expressions library. This is the .5- it's about half written at this point. Brian |
From: fva <fv...@ts...> - 2003-02-25 09:03:50
|
Maxence Guesdon wrote: >>Make some incredibly minimum directory layout suggestions and minimal >>project documentation (something like text file called "description.txt" in >>the root of each module). Then get a ton of code up there. Deal with the >>consequences later. The number of community projects with intricate and >>beautiful submission specifications and no useful code or users far >>outweighs the number of useful projects bogged down by bad indentation and >>planning. >> >> > >I don't think uploading a ton of code and deal with consequences *later* is the easy way : someone will have to sort the functions, and try to give some consistency for the functions of a module. This can be very difficult when it means finding the good functions among hundreds. > >What about this other way : let's find some topics for modules (strings, lists, ...), then for each topic ask everyone what functions are missing and useful, then upload them or code them. Otherwise, I'm afraid the mess in the libraries will result in mess in programs using them. > >Building stable libraries will make them more usable : I don't think anyone would use a library whose interface is always changing. > How about scribbling specs for libraries in module signatures then producing structures that implement the signatures? In this way: - the question of the consistency for the functions of a module is somewhat ameliorated because structures would claim to implement this or that signature only (I know: the problem would somehow be moved to designing the module's signature. Still, we'd be doing one problem at a time: what goes in, first, then how to build it...) - the community could proffer several implementations for different signatures... This could mean competition between implementations (hopefully) for the benefit of everybody... (Also, some stabilisation of the (winning) modules in the library). - signatures *to some extent* can be extended (as structure implementations can)... The library could well be extended bit by bit, but always having a "usable" form. I once extended the OCaml string library using some primitives that I lacked from CAML and it was pretty usable (I've been using it ever since although I see better string libraries nowadays only because it's my own and I remember coding it (and the names of the addons)). - it could be demanded that people contributing to a *particular structure* follow the indentation mode of *that* structure... Besides If someone produced code and submitted it without the proper indentation, just indenting *one* structure in a coherent way is pretty easy for anybody to do. (We could see other people's practice and improve our "indenting" habits that way too!) In a word, let's profit by the capability of the language for developing code piecewise and with "local" flavours but in a public "milieu" where everybody knows what they should do even if their guts remain (hopefully, neatly) hidden. So what I propose is: - let's make a big library, the Extended Library, EL - made of a thousand smaller (smallish) modules and let people contribute to it. - implementing public (voted, agreed upon) signatures - that a) extend signatures and modules of the standard library SL b) provide different implementations to those of the SL (and test them, that's my dream) c) provides *other* signatures and modules that hugely add functionality to the SL d) make open "call-for-implementation"'s in the form of signatures interesting to the community. e)... When we have a high population of signatures and implementations, we'll start thinking about good retrieval mechanisms with them (something that rubs off when you're doing experimentation: first you need a BIG corpus of real data, then you try to extract structure from it). There's a number of them hovering already... Regards, Fran Valverde |
From: Maxence G. <max...@in...> - 2003-02-25 09:17:26
|
> How about scribbling specs for libraries in module signatures then > producing structures that implement the signatures? In this way: > ... > libraries nowadays only because it's my own and I remember coding it > (and the names of the addons)). Sound good to me. To verify the signatures are the ones needed, each person could look at his code and see if it would be what he wanted. What a pity when the type of a function (for example the order of arguments) is *almost* what we need and we have to create a dummy function, for example to change the order of the arguments... BTW, what about labels ? with or without ? I vote for only optional labels, except for functions with plenty of arguments of the same type. > - it could be demanded that people contributing to a *particular > structure* follow the indentation mode of *that* structure... Besides If > someone produced code and submitted it without the proper indentation, > just indenting *one* structure in a coherent way is pretty easy for > anybody to do. (We could see other people's practice and improve our > "indenting" habits that way too!) Agreed. -- Maxence Guesdon |
From: Nicolas C. <war...@fr...> - 2003-02-25 09:43:33
|
> > How about scribbling specs for libraries in module signatures then > > producing structures that implement the signatures? In this way: > > ... > > libraries nowadays only because it's my own and I remember coding it > > (and the names of the addons)). > > Sound good to me. To verify the signatures are the ones needed, each person > could look at his code and see if it would be what he wanted. What a pity when > the type of a function (for example the order of arguments) is *almost* what we > need and we have to create a dummy function, for example to change the order of > the arguments... ... or update your whole code using the ExtLib :) Do it once, and sleep better after. > BTW, what about labels ? with or without ? I vote for only optional labels, > except for functions with plenty of arguments of the same type. Labels should be used for what they have been made for : tipping an ambigous argument. Of course optionals options are also welcome, but only if they're meeting a massive need ( I wouldn't like to see ten optionals options for some -can-do-everything- function ) Nicolas Cannasse |
From: Brian H. <bri...@ql...> - 2003-02-25 21:04:50
|
On Tue, 25 Feb 2003, Maxence Guesdon wrote: > What a pity when the type of a function (for example the order of > arguments) is *almost* what we need and we have to create a dummy > function, for example to change the order of the arguments... How much of a problem is this? I mean, to do: let foo x y = bar y x ;; strikes me as being seriously trivial. A bigger problem for me is to make the arguments in a standard order. One thing that *always* annoys me in C is: fprintf(stream, "string"); fputs("string", stream); I'd much perfer to have a standard order for arguments, to make them easier to remember. For example, in data-structure oriented APIs, the data structure to act upon/use should always be the first argument. Etc. Having to look up the order of arguments every time you use the function encourages programmers to not use the function. Speaking of which- I came upon an issue writting my psqueue library. For data structures that have uniqueness constraints (hashes, trees, etc) what happens when you add an element that is already there, or modify/remove an element that isn't there? There are two sets of ideology on this that I know of: - The "loose" philosophy- quietly do "the right thing". Adding an element (or key) that already exists simply replaces the previous element(key). Removing or modifying a key that doesn't exist does nothing. The belief here is that what the programmer meant, or what is likely to do the least damage, is obvious, and you shouldn't blow up the entire program when there is an obvious way to continue. - The "strict" philosophy- throw an exception on these cases. The programmer asked to do something "nonsensical" and should fix his program, rather than take the chance that the library will guess wrong what the correct behavior is. And the sooner the library helps the programmer catch his mistake, the easier it is to fix. My "solution" is to provide both and let the programmer pick which he wants. IIRC, I used add/remove for the loose versions, and insert/delete for the strict versions. > > BTW, what about labels ? with or without ? I vote for only optional labels, > except for functions with plenty of arguments of the same type. My general philosophy on labels is that they should only be used when there is a real good reason to use them. What a 'real good reason' is I'm still working on. Brian |
From: Maxence G. <max...@in...> - 2003-02-25 22:38:01
|
> > What a pity when the type of a function (for example the order of > > arguments) is *almost* what we need and we have to create a dummy > > function, for example to change the order of the arguments... > > How much of a problem is this? I mean, to do: > let foo x y = bar y x ;; > strikes me as being seriously trivial. Yes, but it really bothers me to define such functions in my code, because I must find a not conflicting and still meaningful name for these, or use a function defined "on the fly". Example : I have a set module MySet (result of the Set.Make functor), containing the function add : elt -> t -> t Now if I want to build a MySet.t from a list, I use fold_left like this : List.fold_left (fun set e -> MySet.add e set) MySet.empty my_list I could have used List.fold_right MySet.add my_list MySet.empty but fold_right is not tail-recursive, so I think MySet.add should have the type add : t -> elt -> t In this case, I would not have to pollute my code with (fun set e -> MySet.add e set) You can say the workaround is trivial, but it happens quite often. > A bigger problem for me is to make the arguments in a standard order. One > thing that *always* annoys me in C is: > fprintf(stream, "string"); > fputs("string", stream); > > I'd much perfer to have a standard order for arguments, to make them > easier to remember. For example, in data-structure oriented APIs, the > data structure to act upon/use should always be the first argument. Etc. I agree. > Having to look up the order of arguments every time you use the function > encourages programmers to not use the function. I agree again. -- Maxence Guesdon |
From: John M. S. <sk...@oz...> - 2003-02-26 05:15:12
|
> My general philosophy on labels is that they should only be used when > there is a real good reason to use them. What a 'real good reason' is I'm > still working on. Good reason (1) is obvious: there are a LOT of arguments. Good reason (2) might be: there are several arguments of the same type and no natural order the programmer might guess at, or, the chosen order differs from the C function it is wrapping. An example might be: Array.make count value can be confused with Array.make value count without a type error if the array type is int array. Good reason (3) is related to both: there are many arguments and some are optional (so labels are necessary to invoke the defaults). Another less good reason is: there are enough arguments and lack of natural ordering, and the client is likely to want to curry the function with subsets of the arguments, perhaps multiple times. -- John Max Skaller, mailto:sk...@oz... snail:10/1 Toxteth Rd, Glebe, NSW 2037, Australia. voice:61-2-9660-0850 |
From: fva <fv...@ts...> - 2003-02-26 09:58:23
|
John Max Skaller wrote: > >> My general philosophy on labels is that they should only be used when >> there is a real good reason to use them. What a 'real good reason' >> is I'm still working on. > > > > Good reason (1) is obvious: there are a LOT of arguments. > > Good reason (2) might be: there are several arguments of the same > > type and no natural order the programmer might guess at, or, > the chosen order differs from the C function it is wrapping. > > Good reason (3) is related to both: there are many arguments > and some are optional (so labels are necessary to invoke > the defaults). > > Another less good reason is: there are enough arguments > and lack of natural ordering, and the client is > likely to want to curry the function with subsets > of the arguments, perhaps multiple times. All seem to me good enough reasons. Shall we push it as a recommendation for contributions? But remember that some Standardlib functions come in two guises now: labelled and unlabelled. Regards. Fran Valverde |
From: Nicolas C. <war...@fr...> - 2003-02-25 09:36:04
|
> - the question of the consistency for the functions of a module is > somewhat ameliorated because structures would claim to implement this or > that signature only (I know: the problem would somehow be moved to > designing the module's signature. Still, we'd be doing one problem at a > time: what goes in, first, then how to build it...) Agreed, Talking first about the signatures is meaningful > - the community could proffer several implementations for different > signatures... This could mean competition between implementations > (hopefully) for the benefit of everybody... (Also, some stabilisation of > the (winning) modules in the library). Yes, somehow Several implementations should be discussed before committing, that's part of the approval process. An implementation can be changed latter if a better one is found or a bug fixed, but the specification won't change > - it could be demanded that people contributing to a *particular > structure* follow the indentation mode of *that* structure... Besides If > someone produced code and submitted it without the proper indentation, > just indenting *one* structure in a coherent way is pretty easy for > anybody to do. (We could see other people's practice and improve our > "indenting" habits that way too!) I don't think we should talk about indentation right now but well... Let's do it. There IS indentation rules in OCaml , they're used in the OCaml Sources and specified somewhere ( in the Manual ? or any pointer ? ) > So what I propose is: > - let's make a big library, the Extended Library, EL > - made of a thousand smaller (smallish) modules and let people > contribute to it. > - implementing public (voted, agreed upon) signatures > - that > a) extend signatures and modules of the standard library SL > b) provide different implementations to those of the SL (and > test them, that's my dream) > c) provides *other* signatures and modules that hugely add > functionality to the SL > d) make open "call-for-implementation"'s in the form of > signatures interesting to the community. > e)... That make sense But I don't agree with the "thousand". The current goal is not to put every existing (although very used) ocaml library into the ExtLib. For example PXP, which is a very good XML parser - and everybody is using XML in today applications - should remain a separate library. The ExtLib should remain somehow small :) Nicolas Cannasse |
From: Brian H. <bri...@ql...> - 2003-02-25 21:38:57
|
On Tue, 25 Feb 2003, Nicolas Cannasse wrote: > The current goal is not to put every existing (although very used) ocaml > library into the ExtLib. For example PXP, which is a very good XML parser - > and everybody is using XML in today applications - should remain a separate > library. The ExtLib should remain somehow small :) > I agree that having six different tree implementations- or even just six different map implementations- isn't usefull. But one of the things I like about Java is it's (bloated, huge) libraries. Yes, it makes Java have a footprint that would shock a brontosaurus, but it also makes Java programmers more likely to use the libraries that exist. Why write your own (badly implemented and non-conformant) XML parser when you can just use the (well implemented and conformant) standard XML parser? Why write your own configuration file parser when you can use XML? Etc. Huge libraries- like GUI interface or 3D libraries- should be on their own. But unless we're talking megabytes of library here, I'd perfer to download and install *one* library, not thirty. And, IMHO, XML parsing is small enough and there are enough possible uses for it that I'd like it in the library. Note that the definition for inclusion shouldn't just be *current* uses, but also *potiential* uses were it everywhere. Take XML for example- it probably isn't a bad format for configuration files, should an XML parser be handy. It's almost certainly not worth it to write an XML file parser just to parse your configuration file, but if it was there, people would use it for that. Brian |
From: Nicolas C. <war...@fr...> - 2003-02-26 01:39:41
|
> > The current goal is not to put every existing (although very used) ocaml > > library into the ExtLib. For example PXP, which is a very good XML parser - > > and everybody is using XML in today applications - should remain a separate > > library. The ExtLib should remain somehow small :) > > Huge libraries- like GUI interface or 3D libraries- should be on their > own. But unless we're talking megabytes of library here, I'd perfer to > download and install *one* library, not thirty. And, IMHO, XML parsing is > small enough and there are enough possible uses for it that I'd like it in > the library. Yes I agree, It would be good to add ( later ) a very small Xml parser into the ExtLib. But let's delay such choices a little bit more... Nicolas Cannasse |