From: Nicolas C. <war...@fr...> - 2003-10-05 09:58:15
|
Hi people ! Right now, SF downloads are showing that there is (only) around 60 peoples that downloaded the ExtLib (no counts on how many are actually using it :-). That's not big, because it's a challenge here : everybody agree that ExtLib is a good thing and that they should eventualy switch to it but since everybody is already using their own libraries, the switching cost can sometimes be quite high . To encourage people to use ExtLib, I thing the best way is to increase the added-value (from an user point of view) that ExtLib is providing. We need more code and several releases to bring people's attention on it. Any proposals for new features are welcome. IMHO, it would be useful to add support for Xml ( XmlLight : http://tech.motion-twin.com ) into the ExtLib. Other thing : a Debian ExtLib package will be available soon. Nicolas Cannasse |
From: Brian H. <bh...@sp...> - 2003-10-05 18:00:37
|
Was I dreaming when I noticed that ExtLib was now part of the CDK? Brian |
From: Nicolas C. <war...@fr...> - 2003-10-05 18:23:57
|
> Was I dreaming when I noticed that ExtLib was now part of the CDK? > > Brian Looks like a nightmare then : the CDK is dead and no longer maintained. Was it a ghost ? :-) Nicolas Cannasse |
From: skaller <sk...@oz...> - 2003-10-06 02:45:06
|
On Sun, 2003-10-05 at 19:59, Nicolas Cannasse wrote: > Hi people ! > Any proposals for new features are welcome. > IMHO, it would be useful to add support for Xml ( XmlLight : > http://tech.motion-twin.com ) into the ExtLib. I don't. XML is a specialist facility, not a general purpose one. By all means a separate library, or twenty. |
From: skaller <sk...@oz...> - 2003-10-06 02:47:30
|
On Sun, 2003-10-05 at 19:59, Nicolas Cannasse wrote: > Hi people ! > > Right now, SF downloads are showing that there is (only) around 60 peoples > that downloaded the ExtLib (no counts on how many are actually using it :-). Well, I'm concerned still with the semantics of Enum, and since Enum-extending other data structures is a key feature .. |
From: Brian H. <bh...@sp...> - 2003-10-06 17:01:25
|
On 6 Oct 2003, skaller wrote: > On Sun, 2003-10-05 at 19:59, Nicolas Cannasse wrote: > > Hi people ! > > > > Right now, SF downloads are showing that there is (only) around 60 peoples > > that downloaded the ExtLib (no counts on how many are actually using it :-). > > Well, I'm concerned still with the semantics of Enum, > and since Enum-extending other data structures is a key > feature .. I agree. My laundry list of things I don't like about the current enum implementation: 1) Creating new enums is clumsy. 2) The next function returns 'a and throws an execption to indicate the end of elements in one place, and returns 'a option and returns None to indicate the end of elements in another. 3) Next both returns the "current" element and moves the enumeration forward to the next element. These two different operations should be seperate functions. 4) Imperitive/side effect driven. Given a choice, I prefer functional semantics. Note that you can still do enumerations of imperitive functions (like reading a file). What you do is cache the next object, making a "pseudo-functional" enumeration object. If it's already returned a next enum, you return the cached value. If it hasn't, it creates a next element, caches it, and returns it. Effectively, the enumerations become a singly linked list. I came up with a brilliant solution to all the of above, based upon objects and inheritance (IMHO an enumeration is an object). Unfortunately, I needed the following class to be typeable in Ocaml: class virtual ['a] enum = object method virtual map: ('a -> 'b) -> 'b enum end;; Unfortunately, this doesn't work (in 3.06 or 3.07). Not being able to do this, my next best solution meant every time you called step (to move the enumeration forward) on an enumeration that had been mapped n times, you needed to create n+1 new objects, and calling current (to return the current element) you needed to create n option variables. Which is why I haven't posted the code to the list :-). Brian |
From: Nicolas C. <war...@fr...> - 2003-10-06 19:40:45
|
> > > Hi people ! > > > > > > Right now, SF downloads are showing that there is (only) around 60 peoples > > > that downloaded the ExtLib (no counts on how many are actually using it :-). > > > > Well, I'm concerned still with the semantics of Enum, > > and since Enum-extending other data structures is a key > > feature .. > > I agree. My laundry list of things I don't like about the current enum > implementation: > > 1) Creating new enums is clumsy. > > 2) The next function returns 'a and throws an execption to indicate the > end of elements in one place, and returns 'a option and returns None to > indicate the end of elements in another. Your eternal battle here :) Not yet convinced that exceptions are better - faster - for internal usage, but dangerous for the programmer if raised from the API ? BTW, there is no Enum.next in the API : it's called Enum.get > 3) Next both returns the "current" element and moves the enumeration > forward to the next element. These two different operations should be > seperate functions. There is already such separates functions : Enum.peek return the current element without removing it Enum.junk remove an element from the enum > 4) Imperitive/side effect driven. Given a choice, I prefer functional > semantics. Note that you can still do enumerations of imperitive > functions (like reading a file). What you do is cache the next object, > making a "pseudo-functional" enumeration object. If it's already returned > a next enum, you return the cached value. If it hasn't, it creates a next > element, caches it, and returns it. Effectively, the enumerations become > a singly linked list. > > I came up with a brilliant solution to all the of above, based upon > objects and inheritance (IMHO an enumeration is an object). > Unfortunately, I needed the following class to be typeable in Ocaml: > > class virtual ['a] enum = > object > method virtual map: ('a -> 'b) -> 'b enum > end;; > > Unfortunately, this doesn't work (in 3.06 or 3.07). Not being able to do > this, my next best solution meant every time you called step (to move the > enumeration forward) on an enumeration that had been mapped n times, you > needed to create n+1 new objects, and calling current (to return the > current element) you needed to create n option variables. Which is why I > haven't posted the code to the list :-). Your answer here : class virtual ['a] enum = object method virtual map : 'b . ('a -> 'b) -> 'b enum end BTW, objects are certainly the worst part of OCaml. They are tricky, difficult to use, and have bad performances (compared to modules instances). If you look at Java programmers (or most of the OO programmers actually) they're using OO only for prototyping ( interfaces in Java or pure virtual classes in C++ ). In Ocaml , you can already prototype by using a module and add specialisation with some polymorphic closures. Believe me : you don't need objects. Nicolas Cannasse |
From: Richard J. <ri...@an...> - 2003-10-06 20:52:57
|
On Mon, Oct 06, 2003 at 09:42:09PM +0200, Nicolas Cannasse wrote: > BTW, objects are certainly the worst part of OCaml. They are tricky, > difficult to use, and have bad performances (compared to modules instances). > If you look at Java programmers (or most of the OO programmers actually) > they're using OO only for prototyping ( interfaces in Java or pure virtual > classes in C++ ). In Ocaml , you can already prototype by using a module and > add specialisation with some polymorphic closures. Believe me : you don't > need objects. Unfortunately objects have a certain very large mindshare over simple abstract data types. I'm not sure most commercial Java programmers would even know what an ADT was ... In OCaml objects have a major syntactic advantage, in as much as it's easier and nicer to type: hash#find "foo" vs. Hashtbl.find hash "foo" Shame that OCaml doesn't have some syntactic sugar to solve this. Rich. -- Richard Jones. http://www.annexia.org/ http://freshmeat.net/users/rwmj Merjis Ltd. http://www.merjis.com/ - all your business data are belong to you. NET::FTPSERVER is a full-featured, secure, configurable, database-backed FTP server written in Perl: http://www.annexia.org/freeware/netftpserver/ |
From: Brian H. <bh...@sp...> - 2003-10-06 22:04:02
|
On Mon, 6 Oct 2003, Nicolas Cannasse wrote: > > 2) The next function returns 'a and throws an execption to indicate the > > end of elements in one place, and returns 'a option and returns None to > > indicate the end of elements in another. > > Your eternal battle here :) > Not yet convinced that exceptions are better - faster - for internal usage, > but dangerous for the programmer if raised from the API ? > BTW, there is no Enum.next in the API : it's called Enum.get Until I can come up with something better, I'm not going to restart the debate. > Your answer here : > > class virtual ['a] enum = object > method virtual map : 'b . ('a -> 'b) -> 'b enum > end I tried that. No dice: $ ocaml Objective Caml version 3.07 # class virtual ['a] enum = object method virtual map : 'b . ('a -> 'b) -> 'b enum -------------------------- end;; This type scheme cannot quantify 'b : it escapes this scope. # > > BTW, objects are certainly the worst part of OCaml. They are tricky, > difficult to use, and have bad performances (compared to modules instances). > If you look at Java programmers (or most of the OO programmers actually) > they're using OO only for prototyping ( interfaces in Java or pure virtual > classes in C++ ). In Ocaml , you can already prototype by using a module and > add specialisation with some polymorphic closures. Believe me : you don't > need objects. While I'll agree that Java programmers use objects for a lot of things that Ocaml has better ways of doing, I think objects are the *natural* representation for enumerations. You have internal state shared among multiple functions (data hiding), multiple implementations of the same methods (inheritance), and a specified contract for the API (interfaces). This is OO all over. Brian |
From: Alan P. <ap...@re...> - 2003-10-06 23:36:40
|
In article <Pine.LNX.4.44.0310061648040.21186-100000@localhost.localdomain>, Brian Hurt wrote: > You might want to fix your Message-ID header generation, though admittedly with all that stuff in front of the @, perhaps the brokenness won't cause any actual problems. > I think objects are the *natural* representation for enumerations. > You have internal state shared among multiple functions (data > hiding), multiple implementations of the same methods (inheritance), > and a specified contract for the API (interfaces). This is OO all > over. How is the ocaml object system better for these than a struct of closures (e.g. the current implementation)? The type of the struct is the interface (Enum.t). Closures can have shared, private data. Inheritance is much more flexible with the struct-of-closures approach. |
From: Brian H. <bh...@sp...> - 2003-10-07 05:00:39
|
On Mon, 6 Oct 2003, Alan Post wrote: > In article <Pine.LNX.4.44.0310061648040.21186-100000@localhost.localdomain>, Brian Hurt wrote: > > > > You might want to fix your Message-ID header generation, though > admittedly with all that stuff in front of the @, perhaps the > brokenness won't cause any actual problems. > > > I think objects are the *natural* representation for enumerations. > > You have internal state shared among multiple functions (data > > hiding), multiple implementations of the same methods (inheritance), > > and a specified contract for the API (interfaces). This is OO all > > over. > > How is the ocaml object system better for these than a struct of > closures (e.g. the current implementation)? In the system I'm thinking about (that I'm cleaning up to post as a talking-point), the enumeration for a list would be: class ['a] list_enum lst = object (this) inherit ['a] enum (* gives us count *) val l = lst method next = match l with | [] -> this (* or throw an exception? *) | h :: t -> {< l = t >} method curr = match l with | [] -> None | h :: t -> Some h end let enum l = ((new list_enum l) : 'a list_enum :> 'a enum) And compare it to the version in CVS: let enum l = let rec make lr count = Enum.make ~next:(fun () -> match !lr with | [] -> raise Enum.No_more_elements | h :: t -> decr count; lr := t; h ) ~count:(fun () -> if !count < 0 then count := length !lr; !count ) ~clone:(fun () -> make (ref !lr) (ref !count) ) in make (ref l) (ref (-1)) OK, my code is 14 lines (not counting blank lines), vr.s 20 for the closures. But I'll give that a wash. The closures example needs *three* levels of functions- but that's mainly to deal with the need for clone. By making the enum applicative, I don't need clone. Also, I don't need a reference. Count is implemented in the super class, so I don't need to reimplement it. But for all that, I'll grant that objects aren't a *huge* advantage over closures at this point. But now, let's write the enumeration for reading lines from a file: class file_enum desc = object inherit [string] destructive_enum val dsc = desc method get_next = try Some (input_line dsc) with End_of_file -> None end let enum_file desc = ((new file_enum desc): file_enum :> string enum) Here I'm getting some serious behaviors from the class destructive_enum- which implements next and curr and gaurentees that get_next will be call precisely once for each enumeration object (and in order), and makes the enumeration pseudo-applicative by caching the data and a reference to the next object. Can you even clone a file descriptor? A quick browse of the manual doesn't turn up how. But this is a result of the classes being (pseudo-)applicative, not OO. > > The type of the struct is the interface (Enum.t). Closures can have > shared, private data. Inheritance is much more flexible with the > struct-of-closures approach. You actually have a point here, now that I've spelled things out. Consider the following code: let rec enum_of_list lst = let next () = match lst with | [] -> enum_of_list [] | h :: t -> enum_of_list t and curr () = match lst with | [] -> None | h :: t -> Some h in Enum.make ~next:next ~curr:curr (* count is an optional argument I'm using the default implementation for. *) let rec enum_of_file dsc = let get_curr () = try Some (input_line dsc) with End_of_file -> None and get_next () = enum_of_file dsc in Enum.make_destructive ~get_curr:get_curr ~get_next:get_next This is basically the same as my object examples above, but using closures instead. This is basically as simple, and if it'd allow me to move map into the object where it belongs, it'd be a serious win. Basically, applying a map to a map would "collapse" the maps, so you'd only ever have one level of mapping. Which would eliminate the whole exceptions vr.s options debate, options would always be faster (and safer). I'll have to play with this tomorrow. I'm too brainfried to write code right now. Brian |
From: skaller <sk...@oz...> - 2003-10-07 21:07:43
|
On Tue, 2003-10-07 at 08:02, Brian Hurt wrote: > On Mon, 6 Oct 2003, Nicolas Cannasse wrote: > > > > BTW, objects are certainly the worst part of OCaml. They are tricky, > > difficult to use, and have bad performances (compared to modules instances). > > If you look at Java programmers (or most of the OO programmers actually) > > they're using OO only for prototyping ( interfaces in Java or pure virtual > > classes in C++ ). In Ocaml , you can already prototype by using a module and > > add specialisation with some polymorphic closures. Believe me : you don't > > need objects. Objects provide dynamic binding. When you have a suitable application, they're useful for that. I used them well in my Vyper emulation of Python for scopes (lookup contexts) to abstract away the rather quirky lookup rules of Python. Modules don't support dynamic binding so that wasn't an option. > While I'll agree that Java programmers use objects for a lot of things > that Ocaml has better ways of doing, I think objects are the *natural* > representation for enumerations. You have internal state shared among > multiple functions (data hiding), multiple implementations of the same > methods (inheritance), and a specified contract for the API (interfaces). > This is OO all over. I don't think you mentioned the most important feature. Enumerations are mutable, and objects provide a good way to represent and control sharing. The same cannot be said for, example, references (since the default, to share, is dangerous). |
From: Yamagata Y. <yor...@mb...> - 2003-10-11 03:39:01
|
From: "Nicolas Cannasse" <war...@fr...> Subject: [Ocaml-lib-devel] Next Step Date: Sun, 5 Oct 2003 11:59:38 +0200 > To encourage people to use ExtLib, I thing the > best way is to increase the added-value (from an user point of view) that > ExtLib is providing. We need more code and several releases to bring > people's attention on it. I think we have to support installation using findlib. -- Yamagata Yoriyuki |
From: Nicolas C. <war...@fr...> - 2003-10-11 07:56:39
|
> > To encourage people to use ExtLib, I thing the > > best way is to increase the added-value (from an user point of view) that > > ExtLib is providing. We need more code and several releases to bring > > people's attention on it. > > I think we have to support installation using findlib. This is already done. a META file have been added recently on the CVS (thanks to Stephano Zacchiroli). Nicolas Cannasse |
From: Yamagata Y. <yor...@mb...> - 2003-10-11 15:37:11
|
META is great, but what I mean is to make install.ml use findlib, if findlib is present. Am I missing something? -- Yamagata Yoriyuki |
From: Nicolas C. <war...@fr...> - 2003-10-11 18:00:02
|
> META is great, but what I mean is to make install.ml use findlib, if > findlib is present. Am I missing something? I don't know about findlib, since it doesn't work under Windows. Maybe you could provide an install_findlib.ml ? Nicolas Cannasse |
From: Yamagata Y. <yor...@mb...> - 2003-10-11 22:09:52
|
From: "Nicolas Cannasse" <war...@fr...> Subject: Re: [Ocaml-lib-devel] Next Step Date: Sat, 11 Oct 2003 20:01:36 +0200 > I don't know about findlib, since it doesn't work under Windows. > Maybe you could provide an install_findlib.ml ? Here is a patch. install.ml automatically tests the presence of findlib. Also, META.txt should be META (no suffix). You can not change the name of META file. The original install.ml checks whether extlib-doc presents in the *current* directory. It looks like a bug. The patch fixes this too. Index: install.ml =================================================================== RCS file: /cvsroot/ocaml-lib/extlib-dev/install.ml,v retrieving revision 1.4 diff -u -r1.4 install.ml --- install.ml 27 Sep 2003 20:06:45 -0000 1.4 +++ install.ml 11 Oct 2003 22:00:31 -0000 @@ -77,6 +77,20 @@ with _ -> prerr_endline ("Warning : failed to delete "^file) +(** package name *) +let name = "extlib" + +(** Do we have findlib? *) +let is_findlib () = + printf "Looking for findlib...\n"; + let findlib = Sys.command "ocamlfind printconf" = 0 in + printf "Done.\n"; + if findlib then + printf "We have findlib.\n" + else + printf "We do not have findlib.\n"; + findlib + let install() = printf "ExtLib installation program v1.0\n(c)2003 Nicolas Cannasse\n"; printf "Choose one of the following :\n1- Bytecode installation only\n2- Native installation only\n3- Both Native and Bytecode installation\n> "; @@ -86,8 +100,13 @@ | "3" -> true, true | _ -> failwith "Invalid choice, exit.") in - printf "Choose installation directory :\n> "; - let dest = complete_path (read_line()) in + + let findlib = is_findlib () in + let ocamlc = if findlib then "ocamlfind ocamlc" else "ocamlc" in + let ocamlopt = if findlib then "ocamlfind ocamlopt" else "ocamlopt" in + + if not findlib then printf "Choose installation directory :\n> "; + let dest = complete_path (if findlib then "." else read_line()) in (try close_out (open_out (dest^"test.file")); Sys.remove (dest^"test.file"); @@ -99,17 +118,18 @@ | "n" | "N" -> false | _ -> failwith "Invalid choice, exit."); in - if doc && not (Sys.file_exists "extlib-doc") then run (sprintf "mkdir %sextlib-doc" dest); - run (sprintf "ocamlc -c %s" (m_list ".mli")); + if doc && not (Sys.file_exists (sprintf "%sextlib-doc" dest)) then + run (sprintf "mkdir %sextlib-doc" dest); + run (sprintf "%s -c %s" ocamlc (m_list ".mli")); if byte then begin - List.iter (fun m -> run (sprintf "ocamlc -c %s.ml" m)) modules; - run (sprintf "ocamlc -a -o extLib.cma %s extLib.ml" (m_list ".cmo")); + List.iter (fun m -> run (sprintf "%s -c %s.ml" ocamlc m)) modules; + run (sprintf "%s -a -o extLib.cma %s extLib.ml" ocamlc (m_list ".cmo")); List.iter (fun m -> remove (m^".cmo")) modules; remove "extLib.cmo"; end; if native then begin - List.iter (fun m -> run (sprintf "ocamlopt -c %s.ml" m)) modules; - run (sprintf "ocamlopt -a -o extLib.cmxa %s extLib.ml" (m_list ".cmx")); + List.iter (fun m -> run (sprintf "%s -c %s.ml" ocamlopt m)) modules; + run (sprintf "%s -a -o extLib.cmxa %s extLib.ml" ocamlopt (m_list ".cmx")); List.iter (fun m -> remove (m^".cmx"); remove (m^obj_ext)) modules; remove "extLib.cmx"; remove ("extLib"^obj_ext); @@ -120,12 +140,32 @@ | PathDos -> sprintf "%s odoc_style.css %sextlib-doc\\style.css"; | PathUnix -> sprintf "%s odoc_style.css %sextlib-doc/style.css") cp_cmd dest); end; + if findlib then + let mlis = + String.concat + " " + (List.map (fun m -> m^".mli") modules) in + let cmis = + String.concat + " " + (List.map (fun m -> m^".cmi") modules) in + let cma = if byte then "extLib.cma" else "" in + let cmxa = if native then "extLib.cmxa" else "" in + if Sys.command + (sprintf + "ocamlfind install %s %s %s %s %s META" + name mlis cmis cma cmxa) + <> 0 + then failwith "installtion fails" + else () + else begin List.iter (fun m -> copy (m^".cmi") dest) modules; copy "extLib.cmi" dest; if byte then copy "extLib.cma" dest; if native then begin copy "extLib.cmxa" dest; copy ("extLib"^lib_ext) dest; + end end ;; |