From: Ben Giddings Date: 2003-09-17T08:32:10+09:00 Subject: Re: performance and style advice requested Alex Martelli wrote: > Or Python -- no "access control" whatsoever, just *advisory* indications > of what's meant to be "published" and what's meant to be for internal use > only. Well, that's *technically* true of Ruby as well. You can get access to a private variable at any time, if you try hard enough (using instance_eval for example). It's just that you're encouraged to use getter/setter methods, and to provide them for only the attributes you want exposed. I think the only thing it buys you is that it forces you to consider "which of these attributes is internal state, and which do I want others to have access to?" whenever you're writing something. My guess would be that that lends itself to a cleaner design. It seems to me that the way Python works lends you to "I'll make Foo with attributes bar and bat, now which ones of these are really actually private?" then adding an underscore to their names vs. "I'll make Foo with attributes bar and bat, now which ones of these are actually public?" then adding an accessor for that variable. Afterall, there's nothing stopping you from using structs instead of classes in C++. My understanding is that the only difference is that a struct is by default all public, and a class is by default all private. But people always use classes. Why? Probably that's just the way they learned, but maybe it's because it's more natural to start with everything private, then expose only what you think is necessary. > I have nothing against this line of reasoning. I'm still allowed to > make the code a BIT less ugly (in my eyes) by using $_foo instead of > base $foo, though. By the same token, literals in your code are ugly > (they should all be constants, right?) -- so do you object to Ruby > letting me write a prettier (and more readable, IMHO) 1_000_000 > rather than an uglier (harder to read, must count 0's) 1000000 ...?-) Yes, I think most literals are bad, and using constants is good, within reason. I'd certainly cringe at "if x < THE_NUMBER_ZERO" though. Do whatcha want when it comes to $_var, I just think it's ugly, but I think a lot of people's code is ugly, so don't mind me. :) > be the enthusiastic "more than one way to do it" philosophy of Perl > and Ruby, vs the principle which the C Standard phrases as "provide > only one way to do an operation", and the Python Zen phrases as > "There should be one-- and preferably only one --obvious way to do it.". Actually, my understanding of matz' design philosophy is that it's more like Python's than Perl's. My understanding was that Python's was more like "There should be one -- and preferably only one -- way to do it.", (i.e. the obviousness didn't come into it) where Ruby's was "There should be one obvious way to do it (but other ways are ok too)" So in Python there should never be two ways of doing something, unless absolutely necessary, but in Ruby there can easily be multiple ways of doing something, but one should be the obvious choice. You know Python far better than I do though, so maybe my understanding is wrong, but I can say with confidence that Ruby has many more obvious solutions than does Perl. >>Note it also works for non container objects: >> >>var ||= "new val"; > > Noted, thanks (I also notice the redundant trailing ";"""...?-) -- I > guess this means that keeping variables initially undefined may be > a sensible strategy in Ruby where it wouldn't be in C or Python. Oops! An artifact of coding all day in C, I'm afraid. And a nitpick, in Ruby variables aren't quite initially undefined, they're set to "nil", the instance of the Nil class. At least, that's my understanding. I don't think you can have a truly undefined variable in Ruby. > I fail to see where the speed penalties are inherent, given that the > semantics of integer numbers in Python and Ruby are so similar now > (e.g., fixnums, aka "int", now transparently give bignum, aka "long", > results in Python, too). Sorry, most of my python knowledge is way out of date. I used it for a while seriously in '97, but not too much since then. If I recall correctly, at that point there was a clear distinction between built-in types and classes, and there were also certain classes which couldn't be subclassed. But I have heard that changed. > Anyway, I'll grow this to definitely-NOT-simple eventually. Will > the extra complication of the problem being solved favour Ruby's > performance? Stay tuned...;-). I'd also be curious to have your impressions on things other than speed, like how long it took to write the programs, how maintainable they seem to be, how easy they are to modify, that sort of thing. It's a bit of an unfair comparison since you know Python well, but this is the sort of area that I think Ruby tends to win out in. > I'll accept your evaluation that you're not surprised if Python is > faster by a healthy margin, but I'd rather a different explanation > than the one you give. *WHAT* do you think is NOT "an object" in > the Python program, giving Python an intrinsic speed advantage...? I haven't used Python 2.3 yet, and haven't used much Python at all in a while, but I was under the impression that integers and other basic types weren't quite full-fledged objects. I seem to remember that they could act as objects, but there was still a distinction like Java's "int" type vs. "Integer" class. Or maybe it was that they didn't all seem to inherit from some base "Object" class. Maybe I'm completely wrong though. I'd like to know more though. > into a dictionary -- in Ruby, I was informed, when it LOOKS like I'm > using a tuple to index into a Hash, in fact the interpreter is working > hard under the covers at forming a string out of that tuple Actually, that was a misconception, the person who told you that was later corrected. I think what happens is that the object you're using as a hash index simply has its "hash" method called (which all objects get since it's defined in Object. Anyhow, if it isn't the object-nature of the languages that causes the speed difference, my guess is that it's the age, maturity, and interpreter differences. Python's interpreter has probably had 5x the man-hours put into it that Ruby's has had, so there's still lots of room for tweaking improvement. I also think there's a fundamental difference in the interpreter, based on the fact you can have .pyc files, and .pyo files, but there's no such thing as a .rbc or a .rbo file. But my knowledge of the internals of either interpreter is basically nonexistant. > You might be surprised. Try coding in standard C or assembly a program > that must work with integers as large as 52!, without using some finely > tuned external library for the pupose, and we'll see what performance > you do get...;-). [In practice, multiple-precision arithmetic is NOT > trivial to code with decent performance]. Sure, I could use GMP, say -- > but then I could use it for Ruby or C just as well, and the variability > becomes unbounded. I _am_ interested in comparing standard languages > as opposed to languages coupled with any one of a zillion potential > add-on libraries, after all. Ok, but by that same token, if Python's multiple-precision arithmetic support has had a lot more work than Ruby's, it's bound to be much faster. If so, it wouldn't be a big surprise if Python 2.3's arithmetic was twice as fast as that of Ruby 1.6. Maybe that's the cause of the slowdown. In any case, I wouldn't get too hung up on it. For the things I tend to use Ruby for, speed isn't an issue at all. It has easily reached the point where it is "fast enough". > I know of no tasks where "a scripting language" is NOT appropriate, > except operating systems (kernels and drivers), and _accelerators_ for > "scripting languages" Unfortunately, I do, in particular embedded systems where code size and memory size is at a premium. With the stuff I'm working on, we're using scripting languages where we can, to test, prototype, etc. but in the end we won't have any embedded scripting language on the current product. > (Ruby has some very elegant parts, those designed from scratch, but > e.g. all of those $_ $` $' $! etc etc that it borrowed from Perl > surely can't be considered *elegant*...???)...? No, certainly not. But then again, I have yet to come across a Ruby program which uses them. In fact, I often argue against including them in future versions of Ruby, as well as some of the non-oo-like Kernel methods like "open" and "gsub" which are also Perl cruft. I'm curious though, how do you know that Ruby has $_, $` and friends? Did you see it in a book, online, in a critique of Ruby, or in code? Like I said, I've never seen them in code, but they're mentioned in books, and always used in critiques of Ruby. To me, criticizing $` in Ruby is like criticizing C for having Duff's Device. > I'll move on to something else -- after all Python and Ruby are clearly > both perfectly general-purpose languages, so it's not as if I'll soon > run out of application domains to explore, hm?-) Nope, and it's fun to hear your reports of your explorations. I don't have much time these days to do my own explorations. The only thing I'd like better is if you'd explore what I find interesting, rather than what you find interesting... but that's probably asking a bit too much, isn't it? ;) Ben