Version française
Home     About     Download     Resources     Contact us    

This site is updated infrequently. For up-to-date information, please visit the new OCaml website at

Browse thread
What does Jane Street use/want for an IDE? What about you?
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: 2008-11-05 (14:58)
From: Kuba Ober <ober.14@o...>
Subject: Re: [Caml-list] What does Jane Street use/want for an IDE? What about you?
On Wednesday 05 November 2008, Jon Harrop wrote:
> On Tuesday 04 November 2008 23:06:00 Kuba Ober wrote:
> > On Tuesday 04 November 2008, Jon Harrop wrote:
> > > You'll just be invoking autogenerated Python code using OCaml so
> > > OCaml's class system is only relevant if you want to do some fancy
> > > statically-typed shim. I'd forget about that and just focus on making
> > > the whole of Qt4 available safely from OCaml in any form first. Even
> > > this is an unsolved problem in the OCaml world!
> >
> > Python bindings for Qt extensively use Python's API. You'd need OCaml to
> > provide said API first.
> No, you just invoke the existing Python bindings. OCaml doesn't have to
> implement anything except bindings to Python, which are already done.

Are those bindings fully functional? As in: can Python use classes/objects
declared in OCaml?

> > > Of those, only core and GUI might be relevant here but the core lacks
> > > first-class functions for events and callbacks
> >
> > Maybe they are not first-class, but the way they've done it is via
> > preprocessing using moc and things behave like they were first-class.
> >
> > In Qt, if you have a user interface dialog box (a form) called MyForm
> > with an element named say ExitButton, you'd have this:
> >
> > class MyForm : public QDialog {
> > 	Ui::MyForm ui;
> >
> > 	MyForm::MyForm(QWidget * parent) : QDialog(parent) {
> > 	  ui.setupUi(this); // calls code autogenerated by UI compiler
> >         }
> >
> > public slots:
> >         void on_ExitButton_clicked() {
> >            ui.ExitButton->hide()
> >         }
> > };
> Compare with the equivalent F#+WPF code:
>   button.Click.Add(fun _ -> window.Close())

This certainly looks better, but it's not an order of magnitude better.
You can also say in Qt:

connect(ui.ExitButton, SIGNAL(clicked()), ui.ExitButton, SLOT(hide()));

If you want lambda-like functionality, that's doable too via metaprogramming,
although the Trolls didn't venture that way yet. And for a good reason: Qt
still largely compiles (IIRC) with VC 6, and trolls kept it that way ;)

> > The code is hopefully easy to understand and as you can see you don't
> > even have to connect signals and slots manually if you don't want to. All
> > the magic happens behind the scenes. It's very easy to use.
> I prefer my F# to your C++.

That's an issue of taste. I do understand the benefits of languages with
first-class functions and other goodies that say OCaml provides, of course,
and I'd much rather use F#, but given that Camelia has to run on modest
hardware and without downloading umpteen megabytes of dependencies, C++
is the right choice for now.

> > > > WPF is just another thing, and it's not really portable in any decent
> > > > sense of the word.
> > >
> > > Sure. My point is that you're building on antique technology when you
> > > could be building modern technology instead.
> >
> > With Qt there's a real chance of machine-translating the code to say LISP
> > or OCaml or what have you.
> Even if anyone ever managed to do that, the result would be an unusable
> buggy mess.

My really limited experiments would indicate that in fact it can be done
very cleanly and without introducing bugs. If you have a relatively well
designed codebase, it's easy to port it to almost anything. If you have a big
mess then of course the result will be just as horrible.

C++ code with basic use of templates (what you'll find in most sane code)
translates very well to LISP, whose generics map pretty well to any language
with static and/or explicit types.

> > With WPF, you're stuck with .Net and that's the end of it.
> That is not a reason to ignore WPF's design.

I'm just rambling here since I know nothing about WPF, but Qt is quite 
reasonable in how well can UIs designed in it look. It's relatively easy
to use widgets designed in SVG, and it's just as easy to use various
"web 2.0" widgets. A friend of mine recently had a Qt application that
called for a "snazzy" timeline widget. It turned out there was one
written in JavaScript/html by someone, and he just pasted it right into
the application. The integrated webkit took care of rendering it, and
after minor tweaks you would never tell that the control was implemented
on a sub-platform of sorts.

> > > > Camelia could be run on a 486 system with perhaps 64MB of
> > > > memory when compiled using Qt/Embedded. While one can question
> > > > whether it's useful or not, Qt has the benefit of targeting all major
> > > > computing platforms out there.
> > >
> > > That sales hype for Qt is just a reflection of the fact that Qt was
> > > built on sand using a dying technology (C++). In practice, the world
> > > moved on to garbage collected virtual machines for GUI programming
> > > years ago. Qt was left behind and is desperately trying to catch up by
> > > migrating to the JVM but the JVM is now dying...
> >
> > Qt has not migrated to JVM. Relevant Qt classes implement parent-child
> > ownership, implicit copy-on-write and reference counting, and are used
> > just like you would any random collection of things in a
> > garbage-collected language. You're also free to use a garbage collector
> > with any C++ project, this has nothing to do with Qt.
> You'd have to Greenspun managed C++ if you want a real GC for your C++
> code. You can pull in Boehm but it breaks existing code and is not reliable
> (hence the Mono project are desperately trying to remove it).
> So you are not "free to use a garbage collector with any C++ project" at
> all. Quite the contrary in fact: you're completely screwed if you choose
> C++.
> Even industry are running from C++ like rats from a sinking ship:
> Is that really the trend you want to join?

First of all, I fully appreciate that there are better things than C++ out
there. I also appreciate that you are after using more up-to-date
programming paradigms / environments. But the deal is that at the end
of the day the reality wins and either you have a platform that can do
90% of the boring stuff for you, or you'll implement it yourself.

In the "good old" high school days, I used Borland Pascal for DOS
and I had to deal with maintaining my own text rendering / UI libraries.
I'd much rather not repeat that experience.

.Net for Camelia is not a choice for me (at least not now) simply because
even if I had it run on Mono, there's just so much of Qt's functionality
absent from the libraries that Mono provides -- heck, even from what .Net
provides w/o 3rd party add-ons.

> > > > Using Qt4 in a decent language will be easy once there is a C++
> > > > parser in said decent language.
> > >
> > > You'll be Greenspunning managed C++ from the .NET world. That's a fine
> > > idea if you regard Qt as useful legacy code but I don't see the point
> > > myself. Qt will always have a stone-age API and reimplementing managed
> > > C++ is a huge undertaking.
> >
> > This is not about greenspunning anything. Most of Qt code is written in
> > such way that the C++-isms are completely abstracted out at the level of
> > core classes such as QObject and collections (QList, QVector, etc).
> The C++isms are nowhere near being abstracted out. Just look at that code
> you posted above.

While I do understand that you're passing an in-place generated function
as an argument in your example, but still for typical cases that's just
syntactic sugar and gives you nothing apart from code that's perhaps
less verbose than C++. You still need to write the guts of the function
somewhere, and doing it outside of the function invocation is not
that much of a loss. OCaml does not have what amounts to truly first-class
functions IMHO. For a function to be first class -- to be really akin to
any other data type -- there must exist a facility for runtime generation
of the same. I mean, you can create integers and strings at runtime, from
external input, so you should be able to do the same with functions?

LISP has that, OCaml doesn't, right? Porting from LISP to C++ is in
generally impossible if the LISP code generates functions at runtime --
there's no way to do that in pure C++, not even with preprocessing like
trols do with Qt's meta object system.

OCaml doesn't do runtime function generation either, and is in the
same "class" of languages as C++ when it comes to that. Heck, metaprogramming
in C++ is impossible to do in OCaml (right?), but is trivial in LISP! So I'd
even argue that C++ has some compile-time code generation built right in
that's lacking in OCaml.

> > By
> > translating the use of basic Qt primitives (really QObject and
> > collections) to whatever OCaml/Lisp/Python/blabla provides, you can very
> > cleanly port Qt codebase to another language, and it will look pretty
> > much as if it were written in said language.
> A triumph of hope over reality.

OK, whenver I get time I will post some side-by-side code taken verbatim
from Qt's sources, and how it looks hand-translated to OCaml; I'll strive
to do the hand-translation using methods that would be easy to implement.

> > > In contrast, you can implement a GUI toolkit in OCaml that far exceeds
> > > the relevant limitations of Qt4 with quite easily.
> >
> > Qt has very few language-inherent limitations that are not abstracted out
> > to the core. Whatever other limitations Qt has are design decisions that
> > have little to do with choice of the language.
> I was referring to the limitations of Qt itself. Look at this example from
> one of our products:
> That uses a 3D layer with a 2D layer overlaid. The labels are 2D widgets.
> That's trivial with WPF because it renders everything through a single
> pipeline: you just put a 2D widget over a 3D widget. That's impossible with
> Qt its OpenGL widget is completely uninteroperable.

You havent recently looked at Qt's demos, did you? Qt lets you do just that.

> Trolltech are hailing Mathematica 6 as a success story for Qt. Look at the
> Mathematica notebook interface:
> That is one giant OpenGL widget covering the whole window and everything is
> rendered using custom code precisely because Qt does not provide the
> required functionality.

What you say may well be true, but the example screenshot you provided is
trivial to implement in Qt without going anywhere near OpenGL. If what the
screenshot shows is done in  OpenGL then they surely spent a lot of time
reinventing the wheel. Do you have any links to screenshots that actually show
benefits of using OpenGL for that?

> > Qt has to cover a lot of platform-specific ground. Reimplementing it from
> > scratch implies having to fix most of the bugs that Qt folks have already
> > fixed. Qt's code base as a fine reference for a lot of platform-specific
> > borkedness that Qt's users have run into, and the trolls have fixed.
> FUD. Those are design flaws specific to Qt. OCaml+OpenGL source code is
> already portable.

Correct me if I'm wrong, but isn't core OpenGL a one-way street? As in it's
oblivious to everything but getting the scene rendered? Admittedly I've last
dealt with OpenGL sometime in late 90s, but from what I recall all notion of
user input was handled very rudimentarily by what amounted to bolt-on 
libaries. And said bolt-on libraries were completely oblivious to the rest of
the common services provided by the underlying operating system.

I can't see, for example, how OCaml+OpenGL code could inherently interoperate
with  anything when it comes to rendering the same thing on screen and
on the printer. Or passing data between applications (think clipboard). Or
embedding itself in another application (think browser plugins or ActiveX
controls, or their equivalent on OS X whatever it may be). And so on.
All of that is provided by any modern application development framework
such as Qt, or Carbon, or Cocoa.

When it comes to those "little things", I presume that the framework that you
developed simply skips over them, and that's where a lot of hard, mundane
work goes.

> > Show me a generic, reuseable OCaml-written, OpenGL-based common widgets
> > such as model-view tables, buttons, editors, tree views, ... Then we'll
> > talk.
> I've actually implemented most of that in Smoke and Presenta already. We
> never made any money out of it (selling OCaml libraries to OCaml
> programmers is almost impossible) so I am considering open sourcing it all.

Now you've perhaps got my attention, although I still dislike the idea of
using OpenGL to render it, since on many everyday platforms OpenGL is in
useless state. Perhaps if there was an abstraction layer that could
work on OpenGL and DirectX 9 and 10, then maybe it'd be worthwhile.

I still would like seeing how it works in practice - say your application
embeds itself via OLE into a typical Office application. How many concurrently
embedded OLE documents can be open before you run into limitations of
OpenGL or DirectX in number of visible "windows"? And so on...

> > > Easiest for me to answer by just posting our code. Here is the code
> > > from the current version of Smoke that typesets paragraphs of text by
> > > overflowing words onto new lines:
> > >
> > > let rec charsmap = function
> > >
> > >     | 'f' :: 'f' :: 'i' :: t -> (`CMR, 177) :: charsmap t
> > >     | 'f' :: 'f' :: 'l' :: t -> (`CMR, 178) :: charsmap t
> > >     | 'f' :: 'f' :: t -> (`CMR, 174) :: charsmap t
> > >     | 'f' :: 'i' :: t -> (`CMR, 175) :: charsmap t
> > >     | 'f' :: 'l' :: t -> (`CMR, 176) :: charsmap t
> > >     | c :: t -> charmap c :: charsmap t
> > >     | [] -> []
> > >
> > > let word string =
> > >   let string = charsmap(list_of_string string) in
> > >   let aux x (font1, c1) (font2, c2) =
> > >     let contours = Cmfont.glyph font1 c1 in
> > >     let contours = Contour.make contours in
> > >     let g = (Contour.trans (translate x 0.)) contours in
> > >     let advance =
> > >       if font1=font2 then Cmfont.advance font1 c1 c2 else
> > >         Cmfont.advance `CMR 32 32 in
> > >     x +. advance, g in
> > >   let rec aux2 x = function
> > >
> > >     | [] -> []
> > >     | h1::t ->
> > >
> > >         let h2 = match t with h2::_ -> h2 | _ -> `CMR, 32 in
> > >         let x, g = aux x h1 h2 in
> > >         g :: aux2 x t in
> > >   aux2 0. string |> List.concat |> ContourGeometry.of_contours
> > >
> > > let word = memoize (fun _ -> word)
> > >
> > > let paragraph ~skip ~justify ~width ~string =
> > >   let words = word (String.split ' ' string) in
> >
> > LOL. If you seriously think it's worth reimplementing the wheel for
> > a millionth time, go for it.
> >
> > Qt already can do rendering in OpenGL, so if one wants to do something
> > that actually really needs OpenGL, it can be done.
> >
> > But to just render a paragraph of text? There's code for it in Qt ;)
> You have completely missed the point, of course.
> You will need to use some modern GUI applications before you can begin to
> understand how they are designed. These screenshots might help:

That's what Qt is for - it's no big deal to do it in Qt, and moreover it
will still work reasonably well on a platform with no hardware 3D support
at all.

I really suggest you look at demos in Qt.

> Note how the GUI elements are arbitrary 2D and 3D graphics. They may be
> overlaid whereas Qt's native and OpenGL widgets cannot be. They have a
> uniform representation whereas Qt widgets and OpenGL content are completely
> separate and uninteroperable. And they can interact with each other whereas
> Qt is completely oblivious to whatever you do in an OpenGL widget.

Qt's OpenGL widget is just as any other widget in terms of
"interoperability". Qt fully supports rendering its own widgets into
textures that can be then used in OpenGL, and vice versa. The biggest deal
with most of what you've shown is that none of it really requires OpenGL --
it's mostly basic SVG stuff and basic transforms available in Qt.
For the few examples where there really are views that benefit from true
3D rendering, you can use OpenGL just for that. Output from OpenGL can be
sliced, diced and integrated anywhere you want within Qt's regular widget
system -- it may not be as clean as writing everything in OpenGL, but then
trolls are not really sitting idly on their hands. Almost every major Qt
release includes big chunks of new functionality that's not only non-trivial,
but has comparatively modest hardware requirements.

> They would not have impressed me a decade ago, let alone today. Many of
> them don't even work on either of my Debian machines.

Interesting that they don't work -- I wonder why. As for the demos, they show
mostly the same stuff that you show in the included screenshots.

Please don't understand me wrong: I do understand the benefits of using
higher-level concepts for description of stuff to be shown to the user.
3D scene descriptions are just a logical step above display postscript,
which is alive and well in OS X. I would just as well use them.

Qt is going that way: they have painter paths, which are a concept straight
from display postscript, and I doubt they are just ignorant as to what
everyone else is doing.

But the big deal is that a lot of that has still to work on quite
low-common-denominator systems. One thing is designing say a $10k-priced
CAD system, or something else for a vertical market where you can either ship
an Nvidia card bundled in the box, or give them coupons for discounts on new
laptops that have relevant chip in them. Or just bundle the darn machine
in the box. But something that will work well on 5 year old hardware has to do
much better than simply use OpenGL "sticking to the book". I'm sure you've
heard of various OpenGL implementation bugs -- Qt folks had to work around
them, and any OCaml-or-otherwise OpenGL -based toolkit you'll use has to work
around them too.

So it's not like OpenGL suddenly gets rid of all platform quirks: that'd be
ideal, but it just ain't so, and the same goes for a more "classic" toolkit
like Qt.

As Qt is actively pursing more advanced display models, bashing
them for being continously outdated is like bashing M$ -- it lets you vent,
but is unproductive. I doubt they won't go in that general direction, but
the benefit you get from using their platform is that it quite simply
works -- even on ancient Windows 95 hardware that they claim they don't
support anymore.

Things like this
and that
actually work on very modest hardware, which cannot really be said about

I of course agree that if both Qt and OpenGL folks did their homeworks
properly, both methods of rendering 3D content (or what pretends to be 3D)
have same asymptotic complexity. After all, if you're say rendering
a transformed bitmap, no matter what the underlying toolkit, the mathematics
are the same. Where Qt wins is that the darned constant factor, conveniently
ignored even in "mid-level" CS courses, is pretty important. Mesa software
renderer works, but good luck persuading anyone to use it ;)

Commonalizing 3D scene descriptions and bringing them into use as a common
way of doing things requires some serious manpower -- if any "small player"
could pull that off, it'll be either trolls or some well-funded startup that
better had a few key customers in line. Qt is getting to be quite entrenched
in some fields, and the big win with Qt is that it interoperates with a lot
of legacy code (Motif or WINAPI). A company with a million-line C/C++ codebase
won't just suddenly abandon it all and decide to port it to OCaml. Not unless
there are tools that for the most case can recompile said code into 
maintainable OCaml (perhaps C++-resembling OCaml, but still OCaml).

Imagine you have a huge C++ codebase that currently uses Qt, and someone tries
to persuade you to port it to MPF in C# or say OCaml/OpenGL based framework.
They will be much more likely to attempt that if they can, with minimal
effort, translate their current codebase to the new platform. They can then
test it, hone out bugs and release, and then work on refactoring it to take
advantage of what the language provides.

The example that comes to mind is how Alibre folks have went. They have a nice
CAD system originally developed for M$ Java. They recently released a port
to .Net J#, and now can work on porting it bit-by-bit to say C# (though
I wish they used F#!). J# & friends took care of "translating" the code
to make it work in the new environment.

Doing it with managed C++ is somewhat harder methinks, even though
managed C++ does exist. The big deal with managed C++ is that C++ never
had a "standard" framework for doing UI stuff. Java code uses Swing
or whatnot, so J# folks reimplemented parts of that (IIRC). Most C/C++
code will use MFC and/or WINAPI and/or GTK and/or Qt. That's a pretty
big target for M$ so they couldn't be as helpful in porting C/C++
code to .Net: it's not really so much plug-and-play anymore.

Cheers, Kuba