For those of you not in the know, Ruby is a relatively new general purpose scripting language that is surprisingly expressive, allowing developers to prototype and develop powerful applications in a short time. Now with QtRuby and Korundrum, that power and expressivity has increased: You can sketch out pretty interfaces with Qt Designer and automatically create Ruby code with the rbuic tool. Or do amazing things with DCOP without needing preprocessors, makefiles etc -- just type in your Ruby script and be in control of your desktop. In fact, you can find a fairly complete description of all the features supported by QtRuby and Korundrum over at the Ruby bindings section of the KDE Developer's Corner.
I've also translated a couple of tutorials into Ruby. There is a Ruby version of
Qt Tutorial #1, and the corresponding Ruby code is in
qtruby/rubylib/tutorial/. That's the one where you build a game to fire a cannon at a target; it explains the basics of Qt widgets such as using layout managers, and how signals and slots work.
For KDE, there is a Ruby translation of a KDE 3.0 tutorial
originally written for C++ by Antonio Larrosa Jiménez.
The sources are in korundum/rubylib/tutorials/. In nine steps it takes you from simple Hello Worlds in Qt and KDE, right up to building a customized browser using the KDE::HTMLPart component which communicates with a bookmarks app over DCOP.
The QtRuby and Korundum bindings have been backported to Qt 3.1.x and KDE 3.1.x, and so now it should be possible to build them on any KDE installation from the last year or two, right up to the current KDE 3.3. You can obtain recent CVS snapshots on the Rubyforge
one killer application using them. Right now, I have a feeling that people use the bindings more for prototyping and quick apps for themselves and convert to C++ later on.. that's one thing that makes bindings great, but hurts them in the long run.
Just my 2 cents on this, anyone agree?
My hope is that apps will spring up like mushrooms all over. Developing KDE applications with Korundum is so easy it feels like cheating.
There are certainly several good apps using PyQt/PyKDE out there. For instance, the TreeLine outliner, Eric IDE and an interesting sounding app called One Finger are all written in PyQt. I hope now that PyKDE is in the kdebindings cvs and part of every release along with ruby, it will help start to change people's perception of KDE being a C++ centric development environment.
I believe C# and java are systems programming languages, which are more of a tidied up version of C++ than RAD languages. There isn't anything wrong with them, but they just aren't the same thing as python or ruby. That's why java has been successful on the server and a complete flop on the client, simply because server side programming needs systems programming languages and the client needs more dynamic RAD languages. Objective-C is a very dynamic language, which is why Apple's Cocoa development environment works so well. It couldn't be implemented using java, and although there are java bindings they don't get used much.
> Developing KDE applications with Korundum is so easy it feels like cheating.
That's exactly what I feel when using PyQt. You write the code and you are wondering why it is so simple. Then you just run it and it works. The absence of a compile cycle is a real pleasure because the code works quicker. And languages like python or ruby are easier to manipulate than C++. No ';', no need for parenthesis inside every if/while, no variable type declaration, very few type errors, uniform API. It really feels easier.
I have converted none of my PyQt applications to C++ and I see no reason why I would.
I love it the way the rubyists and pythonistas seem to be in violent agreement here.. :)
Python and Ruby may be nice but not enough if you're looking for pure lazyness. To achieve that we'd need Haskell bindings :D
what about basic or Delphi?
Most people here celebrate Python and Ruby because they achieve the same what visual Basic and Delphi provided for years.
You are joking right ? I don't know for Delphi, but Visual Basic has some inner limitations (limited class model and other stuff) that python and ruby do not have.
For example, I sometimes like to do a dynamic class inheritance. I have also seen python used as a functional language, which I doubt Visual Basic could ever do.
"they achieve the same what visual Basic and Delphi provided for years"
No, not at all - both python and ruby are a long, long way ahead of what Basic and Delphi provide. Basic started off as a simpified FORTRAN, pascal (ie the Delphi language) started off as a simplified Algol. Ruby and python don't share those ancestors, instead they are more branches off various AI research languages. I started programming in 1976 learning the language POP-11 on an AI course, and of all the languages I've used in the next quarter century ruby is the most similar. Even in the mid-1970s I regarded Basic (and FORTRAN) as an outdated pile of crap and I've always been puzzled as to why Basic subsequently became so popular in the 80's.
Matz the ruby designer isn't familiar with POP-11 as far as I know, and so it is only a coincidence that ruby is similar.
Python and ruby are languages for the 21st century, whereas Basic and pascal are both well past their sell by dates - I personally feel it is time to move on. Blocks, closures, continuations, list processing, pattern matching - that's ruby's realm and it used to be the exclusive preserve of AI languages like lisp (or POP-11 based on the lamda calculus like lisp, but with an Algol look).
I've always felt that Delphi was much more closely related to Modula3 (which is related to Pascal, which is related to pseudocode for programming which is arguably related to Algol).
Ruby and Python are certainly "post compiler" languages. They do things in a way that ignores any considerations to the structure of the language compiler or interpreter. Other languages are tied to certain concepts regarding the underlying architecture and mechanics of the processor and machine. There are still some legacy concepts pulled over (hopefully the good ones), but they are very distinct from languages like C or C++... or even proper BASIC.
Incidently, this somewhat supports the idea that C (and derived) languages have their place as the underlying layer - if only to keep out system level extensions that would otherwise constrain a high level language. Use C (and kin) to build up from the processor to get to a level where easy tools can be used. In that sense, KDE and (BSD|Linux|Unix) are basically device drivers for the abstracted language.
"I've always felt that Delphi was much more closely related to Modula3 (which is related to Pascal, which is related to pseudocode for programming which is arguably related to Algol)."
If you read up on James Gosling's background you'll find he didn't have any object oriented programming experience before designing java and imposing it on the rest of us. He implemented a uscd-p system pascal compiler system on dec vax to solve some problem he had in the early 80's I believe, and just used that idea in conjunction with knowing the C++ had big problems, to invent java.
I feel Anders Hejlsberg (Delphi/C# designer) has more intellectual horsepower than Gosling, and certainly would have known about Modular-3 when implementing Delphi. Even so, when I attended a Delphi introduction presentation in 1996 or so, I can only remember feeling utterly underwhelmed. I was a fulltime NeXTStep programmer used to the dynamic runtime of Objective-C, and just couldn't understand why a warmed over Object Pascal would appeal to anyone..
As opposed to a warmed over Object C? Smalltalkers on the other hand wonder what glue you've both been sniffing.
Yes, java doesn't seem to have been influenced by Smalltalk because maybe James Gosling didn't know anything much about it. Which is a shame - he wouldn't have come up with static methods instead of proper class methods with dynamic despatch. And classes would have been objects that you send a 'new' message to create an instance. That design error has been carried through to C# - I really don't like static methods.
"Resist the urge to overuse static methods.":
I have a feeling much of the reason is due to Borland's wide set of users that used TurboPascal and ilk to write real apps. Much like a C programmer moves to C derived languages easily, Delphi was easy for somebody used to Borland's Pascal offerings.
Incidently, Objective-C was specifically the reason I kept referring to "C derived languages". I'd love to use it, but haven't had a project that was appropriate. Other than a few single file programs one step beyond "Hello World", I haven't played with it. Most of my time these days is spent with PHP and enforcing proper coding practices on developers with bad habits.
Well Delphi would not achieve that, Haskell on the other hand is *Purely* functional and uses *Lazy* evaluation :) I was going for a easy harmless joke. Guess it didn't work.
I got it. :)
So, when do you start one ? An OCaml binding would be welcome too. Given that there is a binding generator for already a few languages (Java, C#, ruby and perl if I am correct), it should not be that hard to add a few more.
Ashley Winters, the guy who designed the Smoke library did start on an OCaml binding. I don't know how far he got with it.
I for one, having working for an entire year on a big commercial proyect 80% done in Python would welcome optional variable type declaration. Yes, pychecker helps a lot to catch sintantic errors that a compiler would catch in C++ (and a lot of other errors) or using not previously (auto)created vars and things like that, but it just can't catch:
var = 50
[...some hundreds locs here...]
vra = var + 1 # You'r fscked here
myReallyMustBeAList = [var1, var2, 34]
# Woop! I really mean to do "someOtherList.append(34)" but
# I've been working for 12 hours, you know...
someOtherList = 34 # Now someOtherList is an Int
myReallyMustBeAList = someOtherList
myReallyMustBeAList # Fscked up you are!
I think Python 2.4 will allow you to declare the types of accepted/returned vars of functions and methods (using new python decorators); it's a start, but I would love to have _an option_ to enforce type declarations to avoid these kind of stupid but sometimes very hard to catch errors; it would help a lot in managing big proyects like mine. ¿Do you need some auto-declared var to do some dynamic magic or a function/method to act as a template? Just don't declare it (95% of vars aren't like these anyway). Declaring the type of vars, and not allowing them to change without explicit conversion, would also allow for some agresive optimizations, too.
On the other side, I love python, it's incredibly productive, the sintax is very clear and the libs are awesome.
I agree 100%. For every big python project, the dynamic typing becomes a problem. I enforce type arguments on all my functions but that's clearly not enough.
Actually, there are very few circumstances where I would change the type of my variable dynamically. I consider that bad programming style. So a static typing system would be ok and certainly remove lot of problems.
What about at like the start of the Python script you some way declare that all variables must be declared. And then create a new 'dynamic' type so in case you want some variable to still be dynamic and all it could be. Also if in the start it isn't declared that all variables must be declared, it acts like it does now.
That way everyone wins! I think...
Well, say that go Guido ! Next time I'll interview him, I'll ask for sure :-)
(shameless plug: http://www.freehackers.org/fosdem2002/guido.html)
That's not unlike what soft-typing languages do. In those languages (Common Lisp, many Schemes, Dylan), a type declaration is an optional constraint. If you put it in, it can help the compiler optimize the code, and check for errors. If you leave t out, you can still use full dynamicity. The usual development style with such languages is you write your "prototype" in a fully-dynamic, general manner, and then gradually convert that into your production code by adding declarations, refactoring, and optimizing.
That's in my list of reasons I not really like python.
Also you can count the sloppy OO style, and even the tabbed blocks, even admitting it is nice to force people to write cleaner code).
I like more Pike, sadly it is soooo unknown and underused...
"That is to say, if a program compiles in a strong, statically typed language, it just means that it has passed some tests. It means that the syntax is guaranteed to be correct (Python checks syntax at compile time, as well. It just doesn't have as many syntax contraints). But there's no guarantee of correctness just because the compiler passes your code. If your code seems to run, that's also no guarantee of correctness.
The only guarantee of correctness, regardless of whether your language is strongly or weakly typed, is whether it passes all the tests that define the correctness of your program."
Oh, you mean what Perl solved with 'use Strict'. Sorry, I couldn't help myself.. :) One other thing that could actually help which isn't really what you're looking for is design-by-contract. I believe Python has some implementation of it, but I've only played with the Perl one. It's a little bit invasive, but can solve errors similar to type errors in the dynamic language realm. Check it out, you might like it ...
That's the commonly held view but I think it is (mostly) wrong. Scripting languages are certainly good for prototypes and quick apps, but in my experience with PyQt I can't recall anybody converting to C++ later on. They might have started a project with that intention, but soon realise that there is no point.
I see the Python/Ruby vs. C++ issue as being the same as the C vs. assembler issue 25 years ago - when you look back on it in a few years time you'll wonder how you managed to write anything useful in C++.
Richard's point is exactly right. Hopefully the increased exposure of alternative Qt language bindings will help challenge current perceptions. I'm aware of many more commercial PyQt applications than open source applications. The driver in the commercial world is programmer productivity/cost rather than any perceived architectual advantages or disadvantages.
I *know* I have read of such a project very recently. Scribus, perhaps?
It is rare, however.
Only the first versions of Scribus were written in PyQt.
But the text rendering was to slow and it was rewritten in C++.
Perhaps it would have been better to replace only certain
widgets with C++.
But now there is still a possibility for scripting Scribus with Python
If only Pyrex worked well with C++ you could write those pieces in almost-python and get almost-C++ speeds :-P
Why doesn't pyrex work well with c++? Why does it not work with PyKDE/PyQt?
Quoting the Pyrex docs:
C++ support. This could be a very big can of worms - careful thought required before going there.
And it doesn't work well with PyQt/PyKDE because there is no simple way to pass a C++ object to a Pyrex extension and use it from Pyrex.
Sure, you could use Pyrex for code that only needs to use integers and floats, but how much code like that is in your average Qt application?
Replacing certain widgets with C++ versions would have been my suggestion. This is similar to what was done with eric (the PyQt IDE). The quickest way to add a good programmer's editor was to port Scintilla to Qt, produce Python bindings for it, and write the rest of the IDE in Python.
Another common approach of commercial users when they want to revamp an existing C++ application is to isolate the core functionality in a library (if it's not already structured as such), produce Python bindings for it, and rewrite everything else (particularly the GUI) using PyQt.
Yep. It is exactly what I am doing at the moment for my job. We have a little C++ library that does some of the irreplacable system code. We wrap it with boost and use python everywhere else. It is a _very_ productive language. I also love the way I can quickly write complicated tests or the way I can make arguments expclicit:
acs = generate_acs( ACS_ALWAYS, (ACS_AUTH, KEY_1), ACS_NEVER, ACS_NEVER )
CreateFile( 300, 0x3F00, acs )
acs = generate_acs( read=ACS_ALWAYS, write=(ACS_AUTH, KEY_1),delete=ACS_NEVER )
CreateFile( size=300, id=0x3F00, access=acs )
I think there are two "hurts" for bindings. Depending on your perspective they could be major, minor or trivial hurts, but I have tripped and bashed my knee on them in the past. The first is that you limit your pool of maintainers and code contributors. I don't know Ruby, so I can't help with a project written in Ruby without first learning the language. The second is that you imposing additional software (vm's, interpreters, runtime libs, etc) on the user.
The last thing I want to do is to discourage anyone from coding in any non-C/C++ language. But these language do come at a price and we should be aware of them so that we can balance those costs with the costs of using C/C++.
The extra runtime requirements used to be a much bigger problem than it is nowadays. In the early days of PyQt you really couldn't ask ordinary users to try to install PyQt themselves. I was constantly helping prospective users of Kura, my language description software, to install Python, Qt, PyQt and everything in the right order. Nowadays, most distributions package a useful version of PyQt, and there are far fewer problems.
This is great! I recently discovered Ruby and I've been hoping to use it with KDE.. and now I can!
Ruby is an amazingly wonderful language and I urge everyone to take the time to learn it, even if you won't use it. It's really quite a fun language to use.
I agree. I tried to learn both Python and Ruby a
year ago. I found Ruby was the better language for me
but never learned more than the basics simply because
I had (and have) no real need for a scripting language :-)
But in case such a need emerges I would always choose
Ruby, probably with Korundum.
I'm not sure myself that I like Python as much as I did a few years ago. The language has grown a lot, adding cool & interesting concepts for which I, unfortunately, never had any use. Well, yes, microthreads and continuations were useful for one particular class of simulation. Now I'm mostly working in C++ and Java, and I miss Python's ease of use and expressive power, but well, it won't do for the large systems we are building at work, and doing a paint app in Python is not really possible, I found.
Boudewijn, could you take a guess as to how much of code you write for Krita is CPU-bound pixel pushing vs GUI stuff? I'm guessing that 70% - 80% of the code is GUI stuff and not speed critical. (At least that is what I noticed the last time I wrote a graphics application in the early 90s, in 680x0(!!) assembler. oh the joy of being young and having too much spare time. :-) )
What did you think of the idea of writing the canvas/image/document/pixel-pushing class in C++ and the rest of the code on top using Python? What made you not go that route? just curious.
I'm not sure of the actual ratio... Let's take a look. Krita is, according to sloccount about 50.000 lines of actual code.
The UI subdir is 5000 lines -- these are the special widgets, dialogs and so on. Stuff that would be easy to do in Python.
The tools subdir is 4079 lines. A nasty mix of ui code and event handling. The event handling is critical: we handle way more events per mouse movement than an ordinary app, in order to draw an accurate line. That wouldn't be doable in Python.
The plugins subdir is 2971 lines. A mixture of plugin admin code (which wouldn't be needed in Python, UI code, and finally code to filter pixels.
The modules subdir contains the color models, complete with code to composite pixels. This is 1918 lines, and it is too slow as it is in C++. We might need to use some mmx/sse/altivec assembly from the Gimp here.
The core is 18.577 lines. This includes a lot of code that simply ties slots to signals in the main view, but also all the data handling, which is complex and performance sensitive for an application that pretends to do more than wrap QImage. Much of it is also infrastructure definition: factories for paint operations, resources, tools -- some of it would not be needed in this form if we were using a language that has a class object. The main view class and the main document class could be done in Python, and perhaps the resource loading. But the image import/export/loading/saving, the painting is very critical.
In the end, I think that doing the interface in Python would not make much difference, because it isn't the largest part of the code in terms of work needed to get going. Coding a Qt interface is not much more work to do in C++ than in Python. It's data structures and application logic that are not performance critical where Python shines. After all, when you've used Qt Designer, most of the interface work is already done.
Not that I did have a choice: Krita is by now five years old, and I merely picked up the threads were they'd fallen to the ground. I never contemplated doing a complete redesign, especially not since that would place Krita outside KOffice.
The paint application I tried to do in Python before I discovered Krita could be worked on was completely in Python. I found that Python was too slow and memory-hungry for the pixel-pushing part, and just when I had resigned myself to doing that bit as a core C++ library, I found Krita, and never did it. Otherwise it might have been a mixture of gcj-compiled Java and interpreted Jython code all using qtjava.
Not to be trolling, but, what exactly are the benefits of this over KJSEmbed (other than say, being able to use Ruby because you like it more)? To me, I see this has the distinct disadvantage of depending on a non-kde scripting engine - while KJSEmbed uses a totally, 100% KDE/QT engine (KJS) that every KDE install already has.
Unfortunately, kjsembed is not yet part of kdelibs (it's still in kdebindings, afaik), so it's not something "everyone already has". (Hopefully, this will change.)
Eh. He was saying that every KDE install has KJS.
QtRuby/Korundum (and PyQt/PyKDE) give you very complete coverage of the Qt/KDE apis. With around a 1000 classes and 30000 methods or so, they are 'heavy duty' eXtreme RAD environments. Kjsembed gives you a much smaller subset of the Qt/KDE api, and so it is more lightweight; the library is smaller and faster to load, and there is less to learn with just a subset of the target apis. If you can master PyKDE or Korundum, then great, but in spite of the simplicity of python or ruby, they do have *very* large apis and an associated steep learning curve, although not so steep if you follow the tutorials in the KDE ruby bindings Developers Corner..
Every KDE install has ruby and python bindings from 3.3 onwards, and so the argument about ubiquity no longer applies.
And don't forget all the high quality 3'rd party library's you get access to with Python and I presume the same is true for Ruby.
IMO ruby is the simplest language I know of, some people call it executable pseudo code :-)
That was the line I always used to sell Python to management... Look! It's a design document you can run :-). I'm really happy that there's so much choice nowadays in bindings. Personally, if I have a suitable problem, I'd still go for PyQt, but I like my languages with as few punctuation marks as possible. Double colons remind me too much of the medical imagery I'm writing apps for nowadays.
Anyway, Cyrille Berger is working on a kjsembed plugin for Krita, and I'm going to get in touch with Jim Bublitz one of these days to ask him whether he can help me with a Python plugin.
Ruby may still need the occasional :: (especiall in RubyQt), but overall its fairly sparse in the punctuaction dept. No semicolons I guess being the biggest difference, as well as using begin and end to define most functions.
Note than you can use an 'include Qt' or 'include KDE' directive if you prefer to have Widget over Qt::Widget, or Application over KDE::Application in your code. Thats much like the 'using' directive for C++ namespaces:
about = AboutData.new("p2", "Hello World", "0.1")
a = Application.new
hello = PushButton.new( a.i18n("Hello World !")
a.mainWidget = hello