Thread: Ruby Or Python

    #16
  1. Hello World :)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Mar 2003
    Location
    Hull, UK
    Posts
    2,537
    Rep Power
    69
    Originally Posted by LinuxPenguin
    ruby beats python on iterating though each character in a string, i don't think python has a really simple way of doing that.

    ruby: "blah".each_char {|ch| puts ch.ljust(500)}

    The classes in python don't have protected and private members in python either, which is a pain, and your use of the pickle class shows that it isn't quite as simple as the ruby one, where you get an optional parameter for filename. If it's provided, it writes to file, if not it returns a string, but in yours, you have to use another function.

    Don't get me wrong, python's an alright language, and the if-name-main trick looks like crap in ruby, but i prefer ruby overall
    Code:
    for ch in "blah": print ch.ljust(500)
    Arguably cleaner than in Ruby. I'll reply to the main thread once I've had dinner .

    Mark.

    Comments on this post

    • xlordt agrees : More, More, More!!
    programming language development: www.netytan.com Hula

  2. #17
  3. Hello World :)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Mar 2003
    Location
    Hull, UK
    Posts
    2,537
    Rep Power
    69

    My thoughts on Ruby


    Ruby seems nice but does it really offer anything substantial that Python doesn't?

    LinuxPenguin's examples* are all possible in Python (sometimes clearer) and all of the Python examples are all possible in Ruby (also sometimes cleaner). If it came down to a syntax issue then you'd just pick the one that suited your eyes and be done with it.

    I'm not an expert in Ruby, in fact I'm pretty new to it however I do know Python intimately we dated for a long time .

    Over the past three years though I must have looked at Ruby five or more times, thought that's not Pythonic and walked off. In hindsight that was a bad choice IMO because since straying from the Python path I've noticed a lot of apparent deficiencies. Don't hang me for this, it's just my opinion .

    It's a bad idea to compare languages form the inside because you have to [try] deal with your own bias/opinions.

    They're both powerful languages however where Python has had to change a lot over the years Ruby seems to have started out in the "right" direction.

    There are no hacked on meta-classes for instance, Ruby started out with full and planned support for OO. Python has steadily been appended on that front and it shows when you compare the two.

    Blocks are obviously a powerful feature and they allow things that you simply can't handle elegantly in Python. Closures etc.

    Pythons lambda is a travesty to any Lisp user, it's almost useless in comparison to that of other languages and should probably never have been hacked on. The problem is that there was a desire for it.

    Python also originally had a very strange and limited scope. Nested/Lexical scope was added in Python-2.1 as part of __future__ but Python still doesn't seem to fully support things like Lexical scoping and or closures .

    It can be argued that they aren't needed because objects serve a similar purpose however they can be very useful and would provide Python users with a way of safely encapsulating data. Something not possible under Pythons current object system.

    Closures also tend to be more flexible, binding data to an action rather than binding actions to data. You could consider them anti-objects .

    Ruby also seems to have a cleaner concept for functions. In Python they're just classes that overload x y and z in standard Python notation. In Ruby they're methods, with all that that implies. I think this elegance on it's own should be enough to make any hacker smile .

    Ruby's syntax is terser, and maybe way too terse for the average pythonista however some features it makes available are well worthy of envy it's my unsupported theory that list comprehension's were added into Python as a response to Ruby's more flexible block forms.

    On the other hand to Ruby users may well see Pythons forced program flow as unbearable. It's nice at first because you're almost guaranteed that code will be well formed but this quickly becomes a smack in the face of elegance.

    It's snakes and ladders people, neither language has really nailed it down yet but I think Ruby comes a lot closer to a coherent whole... even with all those `end' statements which aren't exactly pretty.

    When it comes down to it there isn't much between the too, probably why people are having such a hard time choosing between but what is remarkable is the speed at which the Ruby world has exploded.

    Two years ago Ruby was nothing but a distant echo. Sales of Ruby books recently surpassed sales of Python books, and not by any small order. Think rocket-ship passing a hand-glider.

    Many a time I have read that Ruby will be the next Java (I assume this was meant to be a complement ). It's already being gripped by the business world and that may be enough to carry it far past Python.

    It does like everything else come down to a personal choice so I would recommend that you try both. Personally Ruby seems to fit my new mindset much more comfortably.

    Where I do still use Python from time to time when I do it quickly dawns on me how even with it's very elegant syntax elegance seems to allude almost all Python code. From a Lispy point of view .

    * You use the same syntax to access elements in Python string and lists; and to a lesser degree Dictionaries.

    Slicing in Python also works very similar as in Ruby though I can't comment on things like "somestring"[:7:2] because I don't know if they're possible in Ruby. If it's not then chalk one up for Python .

    Take care guys,

    Mark.

    Comments on this post

    • theBlackDragon agrees : Good insightful and neutral comparison, I chalc one up for you :)
    programming language development: www.netytan.com Hula

  4. #18
  5. fork while true;
    Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    May 2005
    Location
    England, UK
    Posts
    5,538
    Rep Power
    1051
    somestring[7,2]

    I'm going to whine at ruby now

    Over the past few days i've been trying to go into gtk development with dynamic languages (hey, they're much quicker to write than C), and my natural first choice was ruby, i mean it has the ruby-gtk2 module, gotta be good, right?

    Wrong.

    Ruby has always been poorly documented, but it's usually not a problem since i happen to have bought a copy of the pickaxe. The problem, is that the pickaxe doesn't cover thrid party modules (and i don't expect it to).

    I've been trying to survive on the documentation, and it's shocking, as is all ruby documentation.

    I took it upon myself to use the python equivalent, which is much better documented, even if the language isn't quite as nice.

    One of the things I'd like to note here is that python has a much better way of inheriting and extending premade classes, as i discovered trying to extend a gtk toolbar... It was much harder in ruby than python because of the way ruby used the blocks. In a lisp you would have passed a lambda as a parameter, but in ruby you receive the lambda as a block instead, and you can't pass the block on to the next function This left me in a rather sticky position, and i wished the yield function allowed a little more flexibility. In python you don't use a block and so i was free to subclass everything with no difficulties.

    Needless to say my python gtk2 app is going much smoother, with no block issues and good documentation on a module i've never used before...

    So maybe it's not just a straight comparison. For most things, I prefer ruby, but in some areas, python really has it beat, partially because of weaknesses in the ruby language.

    That said, mark already extolled the virtues of lisp, and while we might disagree about flavours, i've got to agree it's the way forward.
  6. #19
  7. Hello World :)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Mar 2003
    Location
    Hull, UK
    Posts
    2,537
    Rep Power
    69
    Today I found something that Python doesn't have but Ruby does: continuations. I've known Python doesn't support them* for quite a while but I didn't know that Ruby did.

    Continuations are a very general and equally powerful way of expressing program flow you might think of them a mini time-machines that are capable of bringing one thing back or forward, sort of like Homer Simpsons toaster .

    They seem to be most commonly used in to implement generators but they're the building blocks for all sorts of coolness including something called tail-call optimization.

    This allows recursion to be effectively turned into iteration while maintain it's abstract nature. That's is a very good thing .

    The catch is that raw continuations in the wrong hands can lead to very dense code very quickly. Maybe this is why Python doesn't not to include them? I'm going to look into it later today .

    I've been playing around with them in Scheme which has first class continuations and they do seem to be flexible and useful.

    * Its technically possible to hack up continuations in any language with closures and a garbage collector (or so I've read) but having them as a core part of the language is obviously going to be much nicer.

    Just my $0.0002

    Mark.
    programming language development: www.netytan.com Hula

  8. #20
  9. Hello World :)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Mar 2003
    Location
    Hull, UK
    Posts
    2,537
    Rep Power
    69
    Originally Posted by LinuxPenguin
    somestring[7,2]

    I'm going to whine at ruby now

    Over the past few days i've been trying to go into gtk development with dynamic languages (hey, they're much quicker to write than C), and my natural first choice was ruby, i mean it has the ruby-gtk2 module, gotta be good, right?

    Wrong.

    Ruby has always been poorly documented, but it's usually not a problem since i happen to have bought a copy of the pickaxe. The problem, is that the pickaxe doesn't cover thrid party modules (and i don't expect it to).

    I've been trying to survive on the documentation, and it's shocking, as is all ruby documentation.

    I took it upon myself to use the python equivalent, which is much better documented, even if the language isn't quite as nice.

    One of the things I'd like to note here is that python has a much better way of inheriting and extending premade classes, as i discovered trying to extend a gtk toolbar... It was much harder in ruby than python because of the way ruby used the blocks. In a lisp you would have passed a lambda as a parameter, but in ruby you receive the lambda as a block instead, and you can't pass the block on to the next function This left me in a rather sticky position, and i wished the yield function allowed a little more flexibility. In python you don't use a block and so i was free to subclass everything with no difficulties.

    Needless to say my python gtk2 app is going much smoother, with no block issues and good documentation on a module i've never used before...

    So maybe it's not just a straight comparison. For most things, I prefer ruby, but in some areas, python really has it beat, partially because of weaknesses in the ruby language.

    That said, mark already extolled the virtues of lisp, and while we might disagree about flavours, i've got to agree it's the way forward.
    Hmmm, I thought Ruby blocks would be first class . I don't know but it seems to me that if they can be passed around in variables you should be able to pass them on wherever there needed Ruby does have a lambda form.

    Anyway, Ruby's docs are much more minimal thats for sure. Some people like it but I can't agree. I don't like having to wade though masses of documentation to find the answer to a simple question (this is a major problem with Cocoa) but having documentation to look at when you get stuck is a win.

    I think it may have something to do with the fact that a lot of the docs are apparently awaiting translation from Japanese. I'm sure things will get better in the future but until then: comp.lang.ruby

    I like Strawberry you like Chocolate. What can I say Scheme just suites me .

    Later

    Mark.
    programming language development: www.netytan.com Hula

  10. #21
  11. fork while true;
    Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    May 2005
    Location
    England, UK
    Posts
    5,538
    Rep Power
    1051
    Continuations are a pain, because while you might understand them and use them in your code, when the time comes for someone else to edit and improve that code, they're going to sit there going `eh? What's that do?`. It took me a couple of minutes to grasp what it was on about, but not everyone is going to pick it up like that. And inevitably, it will come to be maintenance time, and only you will be able to maintain it.

    Shorter is not always better, hence why python may have left them out
  12. #22
  13. fork while true;
    Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    May 2005
    Location
    England, UK
    Posts
    5,538
    Rep Power
    1051
    Ruby blocks, the problem is that you don't pass a block as a parameter, lets take some CL here

    (map (lambda ()) '(a b c))

    See there, you can pass an arbitrary lambda in as a parameter.

    problem with ruby, you can't get access to your block, you can only call it

    x = new sublist(qw(a, b, c))
    x.map {|z| print z}

    so lets assume i have access to the sublist object and my map function looks like this (actually map is a mixin from enumerable but it doesn't matter for the sake of this)

    def map()
    #so i've got my block, yummy, i can call it
    #yield(member_of_array)
    #now what if i wanted to pass it along to, say my parent's mapp function?
    #self.mapp {yield}
    end

    See you can't do that...

    So you'd think pass it as a lamdba? Well you need access to the block to be able to do that, it effectively forms a closure.

    Ruby's docs have had since 93 to catch up, and they're lagging way behind. As far as i'm concerned, if i didn't have the pickaxe, ruby wouldn't be worth programming in, and the 3rd party libraries are largely unusable (there is an occasional gem, however)

    The docs are still fairly crap in japanese, but in comparison, much better. Compare it to python, however, and you're having a laugh. Pythons docs are much much better.

    *shrug* to each their own
  14. #23
  15. Hello World :)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Mar 2003
    Location
    Hull, UK
    Posts
    2,537
    Rep Power
    69
    Originally Posted by LinuxPenguin
    Continuations are a pain, because while you might understand them and use them in your code, when the time comes for someone else to edit and improve that code, they're going to sit there going `eh? What's that do?`. It took me a couple of minutes to grasp what it was on about, but not everyone is going to pick it up like that. And inevitably, it will come to be maintenance time, and only you will be able to maintain it.

    Shorter is not always better, hence why python may have left them out
    Just a thought but when learning how to use continuations you invariably have to read other peoples code. As a noobie you manage it you managed to pick it up in a few minutes so assuming that a more experienced programmer wouldn't be able to maintain your code may be off base. Then, maybe it isn't .

    Pain or not they allow some things which wouldn't be possible otherwise and that's where they're useful. I don't believe that the standard thinking used in some large corporations is a good model to work by. Why have those of average intellect allocating memory etc.

    Continuations should probably be treated along similar same lines; if complex code needs to be maintained getting someone with a brain to do it would make sense .

    If code is well formatted, commented, thought-out and documented then I don't see a reason why you shouldn't use them where they'd make the solution more elegant. Of course the pointless use of continuations can only lead to trouble but they're not something you'd use in ever task .

    It seems to me that you might create a new construct once say yield and then use that. If you find another area where continuations could provide a similar advantage then you'd add another construct. Obviously yield isn't going to cause the same degree of confusion.

    They're of value on web *rails leveraged continuations somewhere in there. I haven't looked into this very far because rails really isn't of any major interest to me .

    Why not stamp a handle-with-care notice on them and be done with it .

    Take care LP,

    Mark.
    programming language development: www.netytan.com Hula

  16. #24
  17. Hello World :)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Mar 2003
    Location
    Hull, UK
    Posts
    2,537
    Rep Power
    69
    Originally Posted by LinuxPenguin
    Ruby blocks, the problem is that you don't pass a block as a parameter, lets take some CL here

    (map (lambda ()) '(a b c))

    See there, you can pass an arbitrary lambda in as a parameter.

    problem with ruby, you can't get access to your block, you can only call it

    x = new sublist(qw(a, b, c))
    x.map {|z| print z}

    so lets assume i have access to the sublist object and my map function looks like this (actually map is a mixin from enumerable but it doesn't matter for the sake of this)

    def map()
    #so i've got my block, yummy, i can call it
    #yield(member_of_array)
    #now what if i wanted to pass it along to, say my parent's mapp function?
    #self.mapp {yield}
    end

    See you can't do that...

    So you'd think pass it as a lamdba? Well you need access to the block to be able to do that, it effectively forms a closure.

    Ruby's docs have had since 93 to catch up, and they're lagging way behind. As far as i'm concerned, if i didn't have the pickaxe, ruby wouldn't be worth programming in, and the 3rd party libraries are largely unusable (there is an occasional gem, however)

    The docs are still fairly crap in japanese, but in comparison, much better. Compare it to python, however, and you're having a laugh. Pythons docs are much much better.

    *shrug* to each their own
    I don't know, I can't read Japanese hehe. Maybe one day but not so much right now . Python's docs are very good, well organized and concise.

    One thing I don't like about Python (one of the only things I may add) is that Python doesn't seem to follow it's own naming conventions names appear in places with _, in others all lowercase and in some others camel-case .

    Code:
    #!/usr/bin/env ruby
    
    def function_one(&block)
        function_two(&block)
    end
    
    def function_two(&block)
        yield block
    end
    
    function_one { puts "hello" }
    Learning Lisp does come in handy, even for playing with totally orthogonal languages . This is the first Ruby I've ever written and it does the impossible.

    It has quite a nice syntax, I don't know if it's semantics really measure up to Lisps in my eyes but it's nice all the same.

    Take care,

    Mark.
    programming language development: www.netytan.com Hula

  18. #25
  19. fork while true;
    Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    May 2005
    Location
    England, UK
    Posts
    5,538
    Rep Power
    1051
    no, the point is that the prebuilt module expects you to pass it in as a standard block

    func {|z| print z}

    you can't just feed it a block like that and hope it buys it because simply, it won't, that's not the way it works.

    If it simply called it a parameter at the end it would be that simple, but it's not, and ruby doesn't have a getaround for it. It's one of those rare but annoying cases i'm afraid. yield handles 95% of needs just fine, but it's those special cases that are the frustrating ones.

    The entire gtk library in ruby sucks *** anyway, tbqh, it works much better in python and makes subclassing much easier
  20. #26
  21. Hello World :)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Mar 2003
    Location
    Hull, UK
    Posts
    2,537
    Rep Power
    69
    I can only assume that you don't know how to use Lisp at all because high order functions still need to be bound to a variable to be called which is what I did here.

    Lambdas passed to map also have to take the correct number of arguments and that is in Scheme. There is no map in Lisp .

    Blocks in Ruby preformed the same action as Lisp would produce.

    Surely if you're subclassing like you said you were then you can override these methods and get some control over the passed in blocks. Ruby doesn't seem to care wether you include a &block variable so there can't be any interface problems what you do get is the block bound to a variable and that you can pass around however you like. Don't believe me google closures and blocks in Ruby.

    They're nothing more than lambda's (but they don't have there own scope apparently). They don't form a closure from what I can see and I doubt that Ruby has it's own definition of what a closure is.

    Code:
    #!/usr/bin/env ruby
    
    def function_one(&block)
        function_two(&block)
    end
    
    def function_two()
        yield "LP"
    end
    
    function_one { |x| puts "hello #{x}" }
    Here you can see that function_one is passed a block, it passes that to function_two and function_two calls that block with whatever like it would any other block passed directly.

    This is in the standard form you mentioned so If I'm missing something please tell me. It seems to full-fill all of what you mentioned above .

    Have fun,

    Mark.
    programming language development: www.netytan.com Hula

  22. #27
  23. No Profile Picture
    Contributing User
    Devshed Intermediate (1500 - 1999 posts)

    Join Date
    Feb 2004
    Location
    London, England
    Posts
    1,585
    Rep Power
    1373
    Python does have closures - you can define a function within a function and return it to the calling scope. The inner function can access variables in the calling function, i.e. its closure. For example:

    python Code:
    >>> def times(n):
    ... 	def _f(x): return x * n
    ... 	return _f
    ... 
    >>> t3 = times(3)
    >>> t3(7)
    21


    However python closures are read only - ie a function cannot re-assign a variable in the enclosing scope. It is possible to work around this by using a mutable object, but I have not yet found a situation where this is needed. BTW the various function decorators are implemented as closures, so they are fairly widely used.

    Python does not currently support coroutines, but PEP 342 will add them to the next version.

    Python lambdas suck, as has been mentioned several times in this thread. However in Python you can define a named function and pass it around since functions are first-class objects - you can do anything with a named function that you can do with a lambda. I have not found a way to pass functions/methods around in Ruby, since there seems to be no way to refer to a function without calling it. You can of course use blocks in Ruby, but as LinuxPenguin has found out, this is not the same thing.

    Dave
  24. #28
  25. Hello World :)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Mar 2003
    Location
    Hull, UK
    Posts
    2,537
    Rep Power
    69
    Originally Posted by DevCoach
    Python does have closures - you can define a function within a function and return it to the calling scope. The inner function can access variables in the calling function, i.e. its closure. For example:

    python Code:
    >>> def times(n):
    ... 	def _f(x): return x * n
    ... 	return _f
    ... 
    >>> t3 = times(3)
    >>> t3(7)
    21


    However python closures are read only - ie a function cannot re-assign a variable in the enclosing scope. It is possible to work around this by using a mutable object, but I have not yet found a situation where this is needed. BTW the various function decorators are implemented as closures, so they are fairly widely used.

    Python does not currently support coroutines, but PEP 342 will add them to the next version.

    Python lambdas suck, as has been mentioned several times in this thread. However in Python you can define a named function and pass it around since functions are first-class objects - you can do anything with a named function that you can do with a lambda. I have not found a way to pass functions/methods around in Ruby, since there seems to be no way to refer to a function without calling it. You can of course use blocks in Ruby, but as LinuxPenguin has found out, this is not the same thing.

    Dave
    Hey Dave,

    I think you could agree that Python support for closures isn't exactly full. Changing the values in closures is one of the main things you do to them. Having to wrap objects in [] so you can change them is a little ugly; you don't do it so much in Python but in more functional languages it's a very powerful technique. It would be awe-sum if it carried over nicely but it just doesn't just a small wart on veneer of an otherwise beautiful snake .

    It's a fair comment to say "just create a named function" but that's hardly the best solution around. If they fixed lambda up then you'd have a much nicer way to do this IMO. Instead it's being removed in Pyhton3

    I guess I'm just being too picky but there are a few of the least polished parts of Python and they're not attractive this goes part way to making some things in Python feel hacked on and that to be honest is one of my main reason for preferring Ruby. The other being that it feels more like Lisp.

    That would be a fairly hefty limitation Dave. I pass functions around all the time damn-it! I'm not a Ruby guy so I had to look this up .

    Code:
    #!/usr/bin/env ruby
    
    def function_1()
      return "hello"
    end
    
    def function_2(f)
      puts send(f)
    end
    
    def function_3(f)
      puts f.call
    end
    
    function_2(:function_1)
    function_3(method(:function_1))
    Blocks server as lambda forms but you can also pass functions around by name and call them when needed. This isn't as nice as in Python but it's no more or less restrictive.

    I personally will take it over nested functions and read-only closures . I'll just see how it goes and if I'm not happy with Ruby I always have Python waiting in the wings... sounds like some ****ed up relasionship there .

    Personal choice, I still much prefer Scheme but out of the two Ruby feels the least restrictive.

    Take care Dave,

    Mark.
    programming language development: www.netytan.com Hula

  26. #29
  27. Only the strong survives!!.
    Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    Feb 2003
    Location
    A World of wonders.
    Posts
    5,583
    Rep Power
    407
    hmm i never used closures in python, what is it good for? and what can i do with it?
  28. #30
  29. fork while true;
    Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    May 2005
    Location
    England, UK
    Posts
    5,538
    Rep Power
    1051
    Closures mean you have a variable/function wrapped up so you can't touch it. It's more to prevent people cocking up than anything

    And in python you can always override that. It's actually part of the python philosophy that you should be able to fiddle with anything if you really want, but are discouraged from doing so. You can even modify tuples if you really want to.

IMN logo majestic logo threadwatch logo seochat tools logo