From: MikkelFJ Date: 2001-11-26T10:05:23+09:00 Subject: [ruby-talk:26479] Re: generating and serving SVG "Robert Feldt" wrote in message news:Pine.GSO.4.21.0111250943580.8364-100000@godzilla.ce.chalmers.se... > > > with uniqueness typing (you can have destructive updates etc) and a > > > compiler producing really fast code. Forgot to comment on this last time: yes this is an important contribution which Haskell people are also seeking to implement. Which in turn leads me to monads for serializing I/O - which again suggest OCaml and strict evaluation to be the preferred approach most of the time. Actually - clean lazy systems (Clean inclusive) attempts to avoid state and the goes to a lot of trouble handling state anyway. This is why the Clean I/O library is large and complex. It's a nice solution to the problem, but it also suggests that ignoring the real world for the sake of cleanliness may be crossing the river to fetch water - i.e. writing a huge statemanaging I/O library in order to keep the language clean. > Out of curiosity could you mention the other languages you considered in > the same deal? You seem to have done a pretty extensive survey. My brain has been flushed a bit lately trying to keep up with newsstreams following septemper and latest the trible election just completed in Denmark, so I can't give you a fresh write-up - but I shall try anyway. The primary languages were in no particular order OCaml (SML), Clean, Haskell, Lisp, Scheme, Dylan, Erlang as I recall. The evaluation was focused on finding an expressive garbage collected langauge that is fast and can replace C++ for coding complex code. I didn't particularly look for functional programming - but it appeared that this was the area where new languages had matured. From these criterias and my own record of dealing with compiler internals, it may be no surprise that I ended up with OCaml since SML were developed for implementing compilers and doing symbolic analysis - and OCaml is SML with added features (ignoring syntax). Ruby didn't enter the competition because it wasn't fast enough, uses too much memory and is difficult to create standalone solutions in (script only). But it is expressive - just needs an easier way to handle higher level functions. Given a fast Ruby compiler I still think I'd choose OCaml over Ruby for some problems, but Ruby would then be a serious competitor as a preferred language for most problems. I did look into a lot, but I didn't write much test code - mostly looked at technology and other peoples tests - and looking for answers to various problems like handling state, I/O, compilation, FFI, library support, etc. I was rather interested in language expressiveness - how much do I need to write - how cool is it when the problems gets complicated - is the dynamic typing of Lisp more expressive that SML/OCaml type inference. I looked closely at Dylan a second time during these considerations. Dylan is definitely worth a look - but it seems to be dumped in preference to Lisp from one of its primary implementers. Dylans seems a better Lisp so I don't get it - but then I'm no expert. Dylan holds the art of migrating from dynamically typed to statically typed compilation simple by the amount of type the user bothers to give. In the end I was convinced that OCaml is almost as powerful in any of the aspects that the other languages shines in. OCaml does not have a nice macro system as Lisp, but it does have a very powerfull preprocessor, that is just as powerful if not more, just more complicated to use. I is not dynamically typed as Lisp is. This should complicate writing easy maintainable code (note that this is where Ruby is also very strong). However the combination of automatic type inference and abstract types and functors makes this a wrong assumption. Especially if/when the experimental generics package of OCaml enters the main codeline. One interesting thing to notice is that OCaml doesn't have a lot of Windows - Cygwin vs. MSVC problems like Ruby seems to have. OCaml has large Unix I/O library that also runs on Windows. It has a few functions that are not supported in the Windows distribution such as fork. But it comes in another distribution for cygwin that does support this. Independently of the distribution, OCaml generates assembler text files and calls upon the system specific assembler to create an object file and subsequently links to other modules using the system linker. As an alternative OCaml generates bytecode but uses the same system libraries. I reckon that Ruby could learn something from how OCaml deals with the cross platform issues as it is both compiled and bytecode based. > > one beginner problem in Haskell: "These four lines executes extremely slow > > and uses all the memory. I've spend the entire weekend and don't know what > > to do." The solution is usually simple once you get it. > > > Oh yeah, thats right. The other frequent problem is dealing with monads for I/O. > > The OCaml team decided on purpose to prefer strict evaluation because it is > > the most useful evaluation most of the time. > > > Ok, but if you're used to laziness it can help you express difficult > things. Have you seen the combinator parser by Swiestra (I never get his > name right... ;-))? He builds table-driven parsers on the fly as the > combinator parser is used. The name doesn't ring a bell. But I did look at combination parsers in various flavors. Most combinators are easily written in strict languages. When there are parseconflicts, the lazy languages sometimes solve the problem automagically. But sometimes it just blows up. I saw a paper on lazy combinator parsers that argued that it could be made almost as efficient as known efficient parsing techniques. However they did so by working a lot on some parsing problem before their benchmarks became decent. To me it proved the opposite: You may easily write a parser, but when it has to run efficiently you end up spending time on trimming the concept. I have wondered why OCaml parsers itself using lex/yacc technology instead of combinator parsers, but I guess it was easy enough to write the parser and it is known to be fast so why bother. I've seen integrated circuit manipulation in Haskell (embedded Lava langauge) which can describe infinitely large circuits very easily. When applied to a real world application where some inputs and outputs are bound to the circuit, the lazy evalution automatically makes a realizable circuit. Describing such general circuits in a different way is much more difficult. Here we are not dealing with parsing performance but with descriptive power. This is very powerful. But then - for such a dedicated problem you'd either choose Haskell / Clean for that particular purpose, or you would implement it in say OCaml using Lazy streams. In the end I'm not so fond of embedded languages. I'd rather write a parser that parses the domain language into an implementing language, so whether you target OCaml, Haskell, or Clean, the underlying syntax doesn't matter much. > And you've seen that you can specify strictness in clean? Have you tried > it? I haven't had the time... I don't remember the details by I'm quite positive you can - I think you add "!" all over the place. > You've convined me; I will take a deeper look at OCaml. Some problems I've > encountered the last time I took a look at it is that there is not much > papers/docs on its internals. Have you found something? I didn't look hard at anything but the GC. I looked at the source which you can browse via Web CVS or download. As I understand the compiler isn't particularly magic. There are some lambda expression optimizations, but must is straighforward transformation from one representation to another until eventually it hits assembler or object code. I guess much of the new interesting stuff is found in a layer above the core Caml language (I left out the 'O' on purpose). The preprocessor p4 allows you to make all kinds of new concepts that are rewritten into Caml before being compiled. They wrote the precossor to help making language research easier. I'd like to know > my tools to depth. I'm still very impressed with the speed the Clean team > can get in a lazy fp lang though. Well - while OCaml has lazyness, I don't think (but I also don't know) the performance of actual use of lazy features are near the performance of Clean. But then you mostly use strict features. > Especially I'd be interested in documentation on the OCaml code > generator. Could be something to ponder for RubyVM. I think OCaml is very interesting as a base for a Ruby compiler or VM. Mostly compiler because of the machine language generation. The VM is probably rather different. I have earlier mentioned C-- as a possiblity for the core of a Ruby compiler - looking at the OCaml source it appears that C-- lives somewhere in the internals of the OCaml compiler - not sure how much though - but the idea is the same: multiple targets from internal representation. But then I think you could actually compile most of Ruby to OCaml. However, I'd rather wait until support of generics is more complete. > Since I found Clean I'm > considering using it over Haskell. Seems to be few drawbacks and quite a > few advantages. If you can live with the platform restrictions and do not need any features not currently available, Clean is definitely a good choice. Better development platform and many good examples of how to create real applications. > I'm a bit at odds with ML syntax after using Haskell for a couple of > years. I guess OCaml "feels" like ML? Yeah I guess so. I'm a newcomer to the field - but OCaml definitely isn't Haskell in the sense that left side is just another way of expressing the right side of an equation. But OCaml is different from ML in that it doesn't give a damn about storing internal state if that is appropriate. For instance, the HashTable implementation stores a lot of internal state and is definitely not have referential trasparency. And that just makes it a factor X easier to write many applications. And then it has objects - which strangely doesn't seem that important thanks to the ML and OCaml module system. > > > OCaml and Ruby have very compact code as a common denominator. Apart from > > > Yeah, but IMHO Clean would probably beat them both?! I'm not sure. If you count the signature files (.mli) of Ocaml, Clean may have an edge - but then Cleans module system is inferior to ML's (which is also the basis for OCamls module system). In Clean you have to write more type info for each function which takes up space but makes the code more readable. Clean may be more to much compact by utilizing laziness - when you really can exploit that. I think it is splitting hairs. In any case both Clean, Ruby and OCaml are very compact. I hate that OCaml forces you to write the types twice when using signatures - that is exactly one of the things a wanted to leave behind in C++, and which is one of Ruby's forces. But you can't have it all, and the ML module system is really powerful so you get something in return - not mentioning the forthcoming generics of OCaml. MikkelFJ