Ask HN: What does Ruby have that Python doesn't?
About 6 months ago I decided to learn either Python or Ruby because I wanted a language to write webapps and simple computergames fast.
I kind of tried both for a while and Python gave the better impression in every way, readability, ease of use, libraries, documentation, expressiveness etc.
But there are so many really enthusiastic posts about Ruby and while Python has a lot of users and is very popular and successful I rarely see anyone rave about it. But maybe that just means it has gotten mainstream.
But anyway I like the Python philosophy that there should preferrably be one obvious way to do things. While similar in most ways, there the languages differ.
So, what do you Rubyists like so much about Ruby? Especially what do you think Pythion lacks?
231 comments
[ 4.3 ms ] story [ 320 ms ] threadOne (fairly minor) real world case where the syntax makes a difference is in web templates: you can use Ruby pretty much straight up to do templating, but Python requires more hoops and hacking, due in part to the whitespace issue. I like the fact that Ruby is flexible enough to be used as-is for templates as well as other code. BTW, it also needs to be said that that is the only place I've ever noticed the whitespace issue being any kind of problem: it's not the big deal that some python detractors make it out to be.
In short: if you're happy with Python...great! Keep using it, you made a good choice. If you want to learn another language, pick something a bit further from it... say, Erlang, Tcl, Java, or C, depending on what your needs are.
That's something cool. It would involve a new PEP and aggressive enforcement of PEP 8
Mostly I use Tcl as a sort of Lisp/Forth mashup :-)
Python's got dozens of ORMs, templating libs, web frameworks, unit test libs. The embarassment of riches definitely an issue, you could spend a week reading about python ORMs alone.
I liked Ruby, but found that Python clicked better for me. That, and call me crazy - but I prefer quiet competence to foaming at the mouth zealotry. There are plenty of people who rave about Python - but they've been doing it for a lot longer than the Ruby people (simply age of language).
Ruby also has gotten lots of people hooked via Rails, and that seems to be where most of the evangelism is coming from.
(edit: commented to clarify my meaning below, in another comment: http://news.ycombinator.com/item?id=283771)
Do you really pick your language by your perception of its users? I'm not sure that's a great criteria for choosing a tool. If an annoying dinner guest admired the butter knives, would you butter your roll with a fork?
Concrete example: The Ruby community is very focussed on the Web, so there's Rails but they aren't really interested in scientific computing so there isn't a real equivalent to NumPy.
I'd mod this up more if I could, because this is the best answer to the original question.
The important thing is the community, not the language. Decide what your problem is, find the people who are working on that problem, and use whatever they use.
The importance of community is the reason why the number of people who praise Lisp as a language is so much larger than the number who use Lisp every day: The Lisp community is small, unfocused, and arguably broken. Meanwhile, I work as a professional Drupal developer and am (god help me) gradually becoming an expert on PHP, but that has nothing to do with my nigh-nonexistent respect for PHP as a language. I do it because the Drupal community is large and growing larger, it includes as many noncoders as coders, and it's focused on building websites rather than obsessing over tools. The result seems to be that customers like using Drupal for their sites. Rails and the like are focused on making programmers feel empowered, but Drupal is focused on making site admins feel empowered.
I was reflecting on the original poster's comment:
"But there are so many really enthusiastic posts about Ruby and while Python has a lot of users and is very popular and successful I rarely see anyone rave about it."
It was a poor choice of words on my part - I meant to characterize that evangelism doesn't necessarily mean it's a better tool. I was reflecting more on his commentary about "enthusiastic posts" in my comment than any personal opinion on Ruby ( I find a bit of zealotry in the Rails people but that's neither a bad thing nor is it my place to comment on it). My preferences tend these days towards being slightly turned off by the loudly evangelised toolsets, simply from past experience of what happens to the communities when they get like that. After things calm down, and the happy masses move on to the Next Big Thing(tm), the languages, tools etc are often quietly solidified and iteratively improved (uncelebrated, in many cases) by those that stick around.
I recently came back to Perl, having joined a firm building systems in Perl, and was surprised at how much has happened in Perl in the 4 years since I stopped working with it. While so many of those that formerly evangelised about Perl moved on to Ruby and Python, the people who were forced to continue working with it every have found ways to improve it. Adding a try/catch syntax with proper exceptions, and similar constructs (albeit a bit Monkey Patch-ey) have made it much easier to work with.
It will be intresting to see what happens to Ruby when the Next Big Thing happens, and the community sheds a lot of it's more fickle members. That's not to say Ruby isn't a fantastic tool now, but I'm interested to see the maturity that comes from the difference between those who think it's really the best tool for them as opposed to the tool that everyone loves.
Seriously, I envy ruby's blocks and being able to redefine a class later in your code (monkeypatching-easy-syntax).
Oh, and Shoes :)
shoes is good for simple apps. But if you need complex controls like trees and sliders, coding in shoes would get annoying. Also the documentation for shoes leaves something to be desired.
but it is pretty fun.. i'm coding a shoes app right now and would recommend it
in my opinion, this is powerful and elegant.
that being said, i have little experience with python, but what i've seen never wowed me. it seems like it has a well written collection of libraries, but that seems to come from the community more than the language. correct me if i'm wrong.
The bad thing is the cultural tendency of the Ruby community towards monkey patching, which in my opinion trades long term maintainability for short term convenience.
I'm curious, how did you arrive at that conclusion?
Like I say, this isn't a good thing or a bad thing, it's just interesting.
But, y'know, you could try quantifying it if you like, by looking at the libraries available for each language, and looking at how many jobs are "Ruby" as their main skill and how many are "10 years of whatever + Python".
The python community has done significant development in science/math so they have stronger libraries in those fields. Python has had an influx of Railsy people due to Django and might get a shot in the arm from Google App Engine.
From a language perspective, I like the wealth of libraries for python. I like that many reference/experimental applications on web stuff is in python. The whitespace issue for me has disappeared and I'm actually leaning toward liking it more than ruby's block delimiters. The template/erb issue can be diffused by looking at HAML. (That's a cool way of incorporating pythonic indentation to templates.) Unicode is solid in python.
Ruby is a better choice if you like to reshape the language into something that could potentially look un-Ruby. It's possible I haven't gotten far enough into python yet, but I can see why metaprogramming and DSLs are more prevalent in ruby than python, and it's not just "one way" culture. (Ruby's optional parentheses for method calls is an example of a language feature that fosters DSL use.)
This also bugs me to no end: nil.to_i == 0, 0 evals true, but nil evals false.
Python's lack for me is anonymous functions. It's cumbersome to set up 40 slightly different named functions and a hash table (or some "factory pattern" thing) to do the same job as 3-4 lines of Ruby. Symbols are nice too.
But for my personal work I choose Python for the libraries, cleanliness, and performance.
I'm frequently tempted to write a python-like scheme syntax to sit in my python programs so I can just do this stuff and to hell with the excuses used to prevent my first code block from above from working.
Lua:
You can in fact call functions with the implicit (via :) self parameter with any desired "self" by using the "." rather than ":" invocation syntax and providing an explicit self. ":" is purely sugar which is optional in all cases. One neat thing about Lua is that the user can define basically arbitrary semantics for inheritance, mixins, and all sorts of meta stuff very simply. And you can define them on a per-object basis. It's very powerful. The drawback is that you have to implement these things yourself (unless you use a 3rd-party lib which provides some common patterns like you'd see in Python or Ruby).Seriously, though, I'm not arguing python's anonymous functions are just as good as ruby's. I'm curious about his particular situation where "3-4 lines of Ruby" is all it takes.
On some level choice of programming language is irrelevant, since any specified functionality can be written in any turing complete language. Arguments about programming language are arguments about style rather than substance.
I suspect that the python vs. ruby debate is like arguing about whether keyboards or guitar are superior musical instruments. They both have their place and the world would be sadder and smaller place if either one went missing.
Remember this: Every language you learn is a big investment in time and energy, and I don't think many people can be really proficient in more than 2 or 3 languages. Some can, but not most.
So, choose wisely, because you will likely be using that language for a long time to come. I personally prefer python because it's more widespread and right now, you have more available to you when you know it than with ruby.
Even if you spend a month learning Ruby and never use it again, it will still irrevocably change the way you approach writing code.
I would also throw Lisp in. And Forth. And Haskell. And Smalltalk...
But then, we are not talking about a month anymore...
Very cool? YES! worth learning? Absolutely! "changing the way I write code irrevocably? Not a chance!
I'm fairly confident that it did. Once you've really learned it, Ruby creates paths in your brain that you will try to follow forever, even if you're not coding in Ruby anymore.
If it didn't, then you never gave Ruby a real chance.
Certainly the "ah-ha" moment for ruby was much less intense than my ah-ha moment of Lisp, Python, SmallTalk and Erlang. And it's definitely more straight forward to me than Haskell, Prolog, OCAML or Forth.
That's just the reality of it.
i think it's mostly mentality. if you think languages are hard to learn, then they will probably seem that way because you will allow yourself too much time to play around with mere details, whereas if you recognize there isn't much to them, you can accomplish a lot in no time at all
And if you hit the reply button and say that you have, then I demand to see code samples.
one paradigm i've yet to try out is the "goal-oriented" languages a la Prolog. i'll get to them
my point isn't about me though, despite how great i am. i just think that thinking about languages as if they were huge monoliths isn't the best way of thinking about them, because it will hurt your ability to try out new languages and perspectives. they are things that you should revel in, not keep away from because they seem daunting
A language is not just the syntax of the language itself, it's also the code style, the convention, the best practise, the language specific stuff, the API of the libraries available, the best way of doing things with libraries.
If you use python to write simple number crunching console applications, then switch to ruby, that is an easy switch.
But if you're writing a Web application using Python and Django and you switch to writing DirectSound using C++, and you tell me you can do this in a week, then you are a genius.
The syntax of languages are trivial, but that's like saying you can discover the colors used in a painting. That's the easy part. The difficult part is knowing how it works. Let me list a few examples of technologies that I think differ strongly from each other that make it difficult to switch
- MFC with C++
- Django with Python
- DirectShow with C++
- VHDL
- ASM
- Javascript with JQuery
- CSS with HTML
- Helix Framework with C++
- Quicktime API with C++
- OpenGL with .NET
- LISP
Have you ever had to switch between things on that level? Or are you talking more of a python to ruby switch?
all the web things, CSS HTML, JS, PHP etc. XML things like XSLT and XQuery (both of which btw are strict functional languages), etc. both JVM and .NET runtimes. API's can be their own sorts of languages. matlab, mathematica and so on
funnily, i grew up on Java. but everything changed once i met languages with first-class functions
my current favorite languages are Lua and Arc. if Arc had a solid implementation i would use it a lot
It sounds like you went and implemented your DSL on top of assembler, which is really bad practise.
I have a hard time believing that's achievable in a "couple of weeks", regardless of the level of someone's "genius".
(Also, just because something compiles doesn't mean you're good at it.)
but if you worry about the details of the language, it will prematurely affect the structures that you create. in this mode it's harder to write "advanced" things because you are respecting the language too much, and are more confined to its syntax/semantics
if you stay above/outside the language, you will naturally pull it up
Writing Java in Lisp doesn't mean you've mastered Lisp. There is a difference between understanding the logic and creating the implementation in the best way possible, given the language.
As a very simplistic example, C and Python have two different ways to iterate. You could write a loop in Python in a C-like way, but there are much better ways to do it (list comprehensions).
On the flip side, just because C doesn't have list comprehensions doesn't mean it's less powerful as a language. It just does things in a different way. Knowing those sorts of things is why being idiomatic in a language is part of mastering it.
i'm not talking about java. i'm talking about structures -- problems, their domains, and the machinations that can be used to solve them, independent of any language or implementation
One can write every language the same way, but that's not programming. You can't learn python and then write C the python way. You can't write Python as you would Java.
Syntactically, it's possible, but that's a different language you are using then.
Don't confuse syntax or knowing when to use particular constructs with knowing a language. Call me slow, but it took me 3 years before I felt confident that I really knew most of C++. I know when to use Boost, when to use STD, What AtlArray is, how to write an IDL file, what extern 'C' does, what an stdcall is, how my variables are layed on my stack, what Gui toolkits are available, how Borland C++ makes properties appear in C++ classes, when one should use an int64, etc.
It takes time to learn that stuff, but to be really good at a language, you need to know it.
We're like doctors, you don't need to apply your knowledge all the time, but when you need it, you need to be aware of what exists and where to look it up.
If they ask me - write a webserver under Windows, I need to instantly be able to think of 3-4 libraries I could use for the low level stuff, and then decide which is best. All that takes time.
The syntax is nothing. A language is a whole lot more than that. You can't stay above a language. You need to delve into the language, you need to have a feeling for the language, you need to feel inside you how to express things in a particular programming language.
When you describe a problem to me, I can see the C++ structure in my minds eye. I can mentally walk through the code, see where I would use templates, where I would use an interface class, where I would subclass and so on.
I can't do the same with python, because even though I know the syntax, I've not used it long enough to get an extreme feel for the language. And the python folks like to reduce stuff down to short lines, and that's something you don't do in C++.
Learning a programming language is learning a new way to think. Not a new way to string sentences together.
I'd use BaseHTTPServer. Batteries included and all that. ;-)
I agree with your general point though. It takes me about 6 months to feel proficient in a language. It's not just the syntax - it's the idioms, packaging infrastructure, unit testing tools, code organization principles, code conventions, etc.
Whereas the Peter Norvigs of the world need ten years.
Sigh.
When I was in college and looking for internships, I put about 20 languages on my resume - Basic, Pascal, DCL, C, C++, Java, JavaScript, Perl, Assembler, PHP, HTML, SQL, CSS, InstallShield, Common Lisp, Scheme, Dylan, Haskell, Ocaml, and Erlang. After all, I'd written code in all of them, even if "code" was just a small 100-line program.
By the time I was looking for my first job, I'd pruned that to the C, C++, Java, PHP, JavaScript, Lisp, Haskell, and Erlang.
Now, I don't even list skills any more, just what I've done and what technologies I used to do it. But the list of languages that I consider myself proficient in is Java, PHP, Python, and JavaScript.
I used to wonder why it was that adults got so stupid between graduating from college and their mid-30s. Now I know - it's not that they're getting stupider, it's that their world and the difficulty of problems they face is expanding faster than their abilities. I feel much, much dumber than I did when I started college - but the program that took me a month then, I can whip off in a weekend now.
If you're such a language whiz you might want to master basic English.
Python doesn't have an equivalent, but it does have __getattr__, which is arguably more powerful but less convenient.
It is about how the language makes you feel. If you're going to be spending >5 hours a day writing in some language, it is of great importance how that language makes you feel when you write it. Simply said, writing Ruby makes me happier than I've ever been while writing code.
Python is to German as Ruby is to French. You can get roughly the same message across equally well in both languages, but French just sounds so much better.
I think I'm stretching the metaphor past its breaking point.
/bitter
:-)
Mmm hmm. How's that American SST coming on? I'm English and your comment even annoyed me.
Really, I'd say to try both languages and pick whichever one you like best. They're very similar in what they let you accomplish, but have very different feel. What works for one person won't necessarily work for another.
so to me Python seems more of a team production dynamic language than one where i can get into flow and crank shit out
There's a joke going around that a Python team will finish a project before a C++ team can decide which brace style to use...
But don't take my comments as saying only ruby is supported on the Mac, or only python on Linux - in reality it's only a light preference one way or the other.
And vice versa, there must be some Linux distros that have tools written in Ruby, right? Particularly some of the newer ones, I seem to recall hearing that their system tools were Ruby.
I'm actually quite puzzled by this.
That's one thing I do like about Ruby; it wasn't always this way, but RubyForge + GitHub (Oh, GitHub!) + RubyGems combine to make for a very fluid feedback mechanism and make good use of The Cloud.
The result is that new libs get announced, distributed, tested, and improved by rabid Rubyists rather... rapidly.
Instead, Python finds another way, like powerful list comprehensions that can be used wherever Ruby would use blocks and maps.
So I would say you can learn some very interesting things from either language, and there's a good chance they will be different interesting things.
That being said, having the easy ability to create lambdas or blocks is hugely benefitial. sighs and I wish python would hop on board there, but I don't think it ever will.
The problem is that Ruby blocks were designed to imitate the behaviour of C-like blocks, while lambdas are true closures. (Don't get me started on why procs are just like lambdas only different).
The difference between a block and a lambda is most clearly seen by asking what the return keyword does in a block vs. what it does in a lambda.
So in Ruby you can write something like:
If blocks were syntactic sugar for lambdas, this method would always return 'none of the above'. Of course, there is another, very elegant way to write this method that doesn't rely on the return keyword or the semantics of blocks, and one can easily argue that this would be an improvement.Right I would be arguing as the latter.
My problem is that these small niggling differences between all the different types of callable items (including what I think is simply disgusting use of a special form "yield") confuses the whole mess.
I'm glad that all these different ways to use callables exists. That's "A good thing" in my opinion. But I can't help but feel that their quirks and differences couldn't be consolidated into a single experience.
De-rails-ing conversations about Ruby is often an improvement.
takes his hat off
and how would the return statement be scoped if the block was created inside a different function?
This first approach doesn't use an internal lambda but is idiomatic - (do/end does not create a block in Lua - it creates a scope):
At the Lua repl:
The next approach duplicates the semantics of the Ruby code you posted, if Ruby blocks were actually lambdas: Now, if you want the nonlocal return properties of Ruby blocks in Lua, you need to be a bit more clever than I feel at the moment. There's probably a trick available via coroutines, because coroutine.yield() yields to the caller of the currently running coroutine, rather than to the caller of the currently running function.Making anonymous function creation less verbose is a popular topic on the Lua mailing list. "function (args) return args end" is more verbose than "do |args| args end". There are several implementations via community-developed macro extensions. I wouldn't be surprised to see something appear in the Lua 5.2 RC candidate later this year.
In the real world, I'd probably write something like this in Lua:
Implementation of table:find(cond) is left as an exercise for the reader.But properly optimized tail recursion.
Actually, if you have generalized folds (folds over all data types, not just lists), all recursion can be expressed in terms of a fold. That's the point of a fold function: it captures the recursion pattern over a data type, letting you parameterize just the specific operation that replaces the constructor.
In practice, I found that the mutability of basic structures was more of a problem. By default, your subscripting/attribute assignment all mutate the original object instead of creating new ones. When I did FP in Python, I did a few decorators to hide this, but it still felt like an ugly kludge that was fighting the language.
http://mvanier.livejournal.com/998.html
but in the sense of can you put up a significant web app in 2 or 3 days, do lots of companies use it (along with C, java, C#, javascript).
r vs. p can't be reduced to 15 bullet points, but one of the best things i remember is Alex Martelli in 2003, so he was talking about ruby 1.6 and python 2.3, i believe, but still valid
http://groups.google.com/group/comp.lang.python/msg/28422d70...
and here's the last thread from May.
http://news.ycombinator.com/item?id=157269
There's the other killer apps: Python: twisted, zope, SQLalchemy, mercurial. Ruby: rake, capistrano, rspec, adhearsion, merb, puppet, metasploit. I'm sure python has a bunch more, but i've been living in rails-land.
There are however also some great alternatives within the Python community, in addition to Django which I no longer tend to use.
Pylons, which is very Rails like including having similar WebHelpers functions, and a port of the Rails "routes" system.
TurboGears, which is currently re-tooling itself to be based on Pylons.
And a variety of others that I'm probably forgetting.
I'm admittedly ignorant on alternatives on the Ruby side, but would be interested to see what other web frameworks people have built and the pros cons vs. Rails.
Merb is the big one. Think Rails, but more lightweight, greater emphasis on scaling and performance, and open to several ORMs (not just ActiveRecord), templating languages (not just ERB), and Javascript libraries.
Camping is a Ruby micro-framework that's been around for a while. The framework itself is 4kb, and Camping apps are designed to sit in one file. Used a bit on the side, but not especially widely for production work.
Sinatra is a newer microframework that looks similar to web.py, but in Ruby. Looks useful, and I've been meaning to get around to it.
The nice thing about Rails, Merb, and Camping is that if you know one, the others will be familiar. They're all MVC frameworks that support ActiveRecord (and other ORMs, sometimes). They all favor convention over configuration.
Sounds exactly like the reasons why I went to Pylons. I found SQLAlchemy to be a lot more powerful than the Django ORM, and we needed more application components to be 'detached' from the web interface which got wonky in Django.
I'll have to check these out, thanks.
I personally find CherryPy to be great for writing small web-apps. I haven't used it for anything larger yet, but I suspect that I'll continue to prefer it over other python web frameworks.
The continuation-based web frameworks make state management on the server transparent; but they have a scalability problem since state can't move between servers or even be taken out of memory on the same server.
Now once somebody makes serializable continuations practical - certainly a hard problem - it would be a jolt to web development on at least the same that Rails has been.
I lived with Python for 4 years before I lost an argument at my own company and had my project moved to Ruby. I've since moved in with Ruby and haven't looked back.
* Everything in Python feels like a symbol table hack. Private methods? We have those! Just exploit this bug in the class symbol table lookup code!
* First-class symbols. There may be little difference under the hood between a Ruby interned string and a Python string atom, but there's definitely a difference syntactically. This is a difference that is hard to articulate, but if you've written much C, it's like having every "enum" you could ever want predefined for you, and completely eliminates "magic numbers".
* Blocks and lambdas. I've read GvR's take on this. I know he thinks a named function is just as good --- maybe even better! --- than an anonymous function. I had nested named functions/functors in C++ and Java. Even Tcl "uplevel" is better than Python's castrated lambda.
* Method definitions in Ruby don't need to accept a "self" argument. Again: all of Python feels like a symbol table hack to me.
* Ruby has first-class Regexps. Python has an "re" library. You know what else has an "re" library? C.
* I haven't found an expression that is better written as a list comprehension than as a map/reduce/select expression.
There are painful things about Ruby:
* The FFI is immature. Outside of Common Lisp, Python ctypes may be the best FFI out there.
* I never got Python to crash on me (at least, not where it was Python's fault). I crash Ruby once a week.
* Ruby is palpably slower than everything. If performance matters to you and you don't know C, you may be better off in Python.
* The community is led by the nose by Rails developers, which can at times feel like a worst-of-all-worlds grab bag of methodology programmers, web designers, and dabblers.
Yeah, but this is an area where both languages are just a mess. If python's lambda is castrated, ruby's notion of an anonymous function is tumorous. We've got blocks, procs, lambdas and methods? What's the difference?
Ruby mixes up the syntactic requirements of "passing" some code to a loop to iterate with with the data requirements of binding a function to a scope. It's just a huge mess.
LISP and Scheme figured all this out decades ago, and yet only Javascript (and, almost, perl) among common scripting languages has managed to absorb the lesson.
Your Ruby problem with blocks and Proc objects is a nit about elegance and semantics. How often does the difference between an actual Proc object and a block actually affect you? More importantly, if the cost of fixing that nit is that we wind up with Lisp's or Javascript's lambda notation, who would accept that? Javascript has relatively consistent semantics for anonymous functions, but extremely clumsy syntax.
Python simply doesn't have real lambdas. It has the ability to pass something called a lambda in place of a function, and that something forces you to think about things like the difference between a statement and an expression. It then tells you that you don't in fact want anonymous functions, but instead you want to define tens of itty bitty named functions and use them instead. You also "want" that "self" argument to all your methods, and you "want" to tack two underscores to the front of your method names to make them private.
So, I half agree with you. Yes, it would be nice if there was a (zero-cost) way of fixing Ruby's block semantics. Yes, I can rely on Lisp's lambda semantics slightly more than I can on Ruby's, which does start to matter when you start writing domain-specific language code. But I don't agree that this has any bearing on the Python vs. Ruby argument. Python lambdas suck.
But ruby's methods really do suck, and so do the complex construction of Blocks. While I recognize that blocks allow you to do weird things (like use return on the calling scope), the fact that they necessitate a special form (yield) and cannot be bound to a variable, and are not passed as standard function parameters just makes them inconsistent and gross.
Methods which aren't first class functions (but can be transformed into one with the helpful helper function!) also suck, and passing those around in a functional way is just a lesson in futility.
All that being said, I have much more faith in these warts being fixed as time goes on, than python's nasty lambda, and the gross over use of dunders.
Which brings us to another point - when exactly do you actually need them? I have for every 1000 lines of ruby code maybe one line of "yield" code, and this is only to further extend classes for flexibility. Other languages dont allow you to choose what you want to have, ruby does.
You simply have to make decisions when to use what.
For me it is simplicity, elegance and beauty. These are my biggest design criterias.
The inconsistency is annoying, but 99.999% of the time, Ruby is actually giving you what you want.
I've tried to explain it like this. To me ruby feels Turtles all the way down with respect to Objects, but some kind of nightmare tunnel of interleaved beasts down with Functions.
I don't think I should have to make that compromise, so I'll happily go about writing my ruby when I have to, but I'm waiting for the language that is consistent all the way down.
If I could replace every yield I've ever written in ruby with a .call() I would be so much happier :)
http://blog.sidu.in/2007/11/ruby-blocks-gotchas.html
is a good run down of some of the problems here
How many people will use yield _AND_ self.send in the same method please?! That seems like an awfully complicated and contrived example. Who the heck does this?
Newspeak is coming... http://gbracha.blogspot.com/
Lua is close.
That's my own language, and quite obscure (FlightGear uses it, and I've done quite a bit with it personally). But if you want to include Lua too, we might as well be consistent. I was trying to stay within languages with which most readers here would be familiar.
For that matter, Ocaml/Haskell/Erlang all get it right, and those are not pet languages. And Cecil and Dylan almost get it right, but have some complications introduced by multimethods. So it's really just the popular languages tha screw up.
It also makes this pointless but interesting piece of code possible:
Tcl, in its own way, is more powerful than both Ruby and Python in that only the syntax is a given. There is nothing special about 'if', 'while', and other control structures, which are not syntax, but commands. Indeed, you can write your own control structure commands in Tcl itself, with 'do ... while' being a classic example.
Can you elaborate on why you think Python's lambda is castrated?
Python's lambda doesn't allow the use of statements (correct me if I'm wrong I haven't written Python in a few years and they may have "fixed" this).
Meanwhile Ruby only allows expressions too - the catch here is that everything in Ruby is an expression.
That is why people consider them castrated - in most languages I'm aware of that have a "lambda" statement, it can be read as "create an anonymous function that executes this body of statements". In python it reads as "perform a simple transformation or calculation on or with these arguments", as that's all it's generally good for.
And no, that's not all method_missing. looks like method_missing plus a block.
You can do all that stuff with python, though the syntax isn't as loose; you can't omit the () around method calls which is what I think you're doing here in Ruby. That restriction tends to improve readability and reduce bugs at the cost of making it harder to have a truly transparent DSL.
But isn't it surprisingly annoying to do method_missing in Python? Again, you have to catch the exception case to the symbol table lookup, and cons up a callable that knows to catch the arguments the right way.
Here's the entire method_missing call I needed to make x86 work inside a Ruby block:
No, it's not surprisingly annoying. You can override just about anything within the rules of the Python syntax. You can override what << and + and | all do. You can override [] and ().
You just have to live within the Python syntax, which unfortunately for DSLs is stricter than Ruby syntax. But when you're not doing DSLs, that stricter syntax is usually a good thing.
A callable object in Python (e.g., a function or method, though not necessarily limited to these) can take advantage of two special options in declaring its argument signature. One is a feature shared between Python and Ruby: you can prefix the final argument with a single asterisk, which will be interpreted as "accept any number of additional positional arguments, and store them as a list in a variable of this name".
So, for example:
Which does pretty much what it looks like it should do; you pass any number of arguments, and it echoes them back, each argument printed on a separate line.The other part is something Ruby doesn't really support, because Ruby doesn't have a true analogue of Python's keyword arguments: using a double asterisk says, essentially, "accept any number of keyword arguments, and store them as a key/value mapping in a variable of this name".
So, for example:
If you then did, say, `print_keyword_args(name='Bob', email='bob@example.com')`, you'd get back the output (ordering of items may vary with the Python implementation, but usually you're not concerned with ordering -- that's what positional arguments are for): These can also be combined into a standard idiom for a callable which accepts any combination of any number of named and keyword arguments: These sorts of idioms are incredibly useful for dynamic programming; for example, I work with (and help develop) the Django web framework, and our object-relational mapper uses the `kwargs` idiom to set up query methods which dynamically adapt the arguments they accept to the particular data model you're querying against.I used to think this too. But, then I actually learned ruby, and it turns out to be pretty easy to discern method calls from local variables, unless you are working with horridly long methods, which is a separate issue.
Remember that an instance variable is prefixed with @ in ruby, so if you see something that looks like it could either be a method call or a reference to a local variable, it's pretty easy to quickly examine the local scope to check. It's usually so obvious that you don't need to, though.
There are definitely some potentially tricky situations (closures, etc), but in over a year of working with ruby full time, I have yet to encounter one.
While any programmer who would write this deserves to be fired, I can't come up with a good reason why it should be valid to write it in the first place.
Anyway, here is the one that comes to my brain flow naturally. It seems python writers need () in order to feel happy, otherwise they think they get confused about things (hopefully they dont have a small brain):
What will happen in this perfectly valid Ruby code? Where do the parentheses belong? Do you know off the top of your head?fun1(x) fun1(x + y) fun1(x + y.foo()) fun1(x + y.foo(bar))
Btw you omitted what x and y are. My first assumption is that these must be variables that allow the + method
It does not really make a lot of sense though, give the last example:
class Cat def initialize(name) @name = name end def foo(how = :h) case how when :h how = 'happily' when :u how = 'unhappily' end puts @name+' meows '+how+'.' end end
y = Cat.new 'Tom'
y.foo # "Tom meows happily." bar = :u y.foo bar # "Tom meows unhappily."
x = '"At the end of the day "
x + y.foo bar # "At the end of the day Tom meows unhappily."
etc.. I simply have no idea what fun1 should do. Maybe it will involve Jerry mouse and return a conditional story where it is explained why Tom the cat is unhappy.
Btw this is a really contrived example because I tried to model your stipulation of the above code into this. It really makes no sense at all to use variables without any real idea why one should use that.
Why do people WANT to be complex when simplicity is so much more elegant?
I demand the pre tag or a "code" tag or something that allows us to add code nicely formatted :P
> While any programmer who would write this deserves to be fired...
That's exactly my point. The only example you could come up with was a straw man.
> ...I can't come up with a good reason why it should be valid to write it in the first place.
Can you come up with a good reason it matters in practical, real world situations?
In Python you can fiddle with the machinery that creates class objects and use it to do whatever you need. In Ruby, as far as I know, that's simply not possible.
(and, yeah, you need to look up the attribute hooks in Python, because it looks kinda silly when your cherry-picked examples are of things you actually _can_ do in Python)
What I'm looking for is something equivalent to Python's "metaclass" declaration, which lets you completely control the way the class object is created. I've been told by fairly knowledgeable Rubyists that there isn't really an equivalent, and that after-the-fact monkeypatching or factory solutions like yours are the only way to come at the problem in Ruby.
print word
where does "word" come from?
Anyway, this setup is in no way different to ruby's super
super("foo") super("bar")
I really fail to see the point here. What is different? I simply do not see what the python example shows "a bit more clearly" here. I dont even get where "word" comes from.
Besides, "monkeypatching" is a deragotary term invented by pythonistas who do not understand Ruby or think that by adding complexity you can feel "meta" programming so clearly. In my opinion the metaprogramming demanding people are wanking hippos that continually feel a need to add needless and useless complexity on top of problems and in situations where there simply should not be any of that.
Both ruby and python are way to complicated. Can you believe this? At the same time, both are a LOT more elegant than languages like perl or php. Perl 6 still has not managed to get rid of the useless ; at line ends. They managed to eliminate () around if's.
Wow. I am soooo impressed. In 100 more years Perl 7 will be THE best language arrr!!!
But it is a shame that there are not more good languagesl ike ruby or python, because in fact there simply are not that many good languages existing anyway. It takes so much effort to grow a language....
And yes - both ruby and python are very good languages. The fact that there are idiots using the language who have a loud mouth badmouthing either of these two decent languages is annoying, but one can not do much about it.
For everyone else I recommend reading the "why it does not matter" blog. It really summarizes a lot of why ruby and python fill a very similar ecosystem, behaving like rivals who continually try to point out how incredibly stupid the other language is.
Grow up. Use what you prefer, and end this stupid war.
> print word
> where does "word" come from?
Note that Monkey is a function that takes a parameter word. So every invocation of Monkey creates a class that will always .shout() the parameter word.> Anyway, this setup is in no way different to ruby's super
> super("foo") super("bar")
No.
You'll note that these two class definitions create a class Chimp that's descended from a class like _SomeMonkeyThatSaysFoo, and a class Gorilla that's descended from a class like _SomeMonkeyThatSaysBar.That is what the parent poster has challenged anyone to reproduce in Ruby.
> Grow up. Use what you prefer, and end this stupid war.
Programming language wars are at least as old as the Internet, so the admonition to "Grow up" hold no water in this case.
I could quite reasonably parody your closing statement as: "Grow up. So who cares whether a hammer or celery makes a better tool? Just leave us alone, hammer-users."
However it will let you subclass 'Module', which is the superclass of Class, and you can use this to achieve similar ends if not quite as elegantly.
The way class methods work wrt to inheritance is a bit different in ruby though, and gives you quite a lot of power to provide special behaviours to subclasses via class methods which can be called in the subclass class definition. The kind of "we provide a DSL for you to use in your class definitions to configure the subclass" tricks which (IIRC) tend to require metaclasses in python, don't require them in ruby.
There is also an 'inherited' class method callback on Class, which you can use to run code whenever a new class inherits from your class. And this can be used to achieve a lot of things that pythonistas might use metaclasses for.
On the whole I think anything possible in one language is possible in the other when it comes to metaprogramming, it's just a matter of how you go about it and how elegant it feels.
module SpecialBehavioursForClass def extended(klass) klass.class_eval { ...do anything you like to classes including these behaviours as though you're in their class definition block itself... } end
endthen
Class MySpecialClass extend SpecialBehavioursForClass
end(note how there's already a class method 'attr_accessor' which does this - but just to reinforce how you'd go about making something similar yourself)
then: MySpecialClass.is_a?(SpecialBehavioursForClass) returns true.
However, MySpecialClass.class == Class it's not actually an instance of a metaclass as these don't exist in Ruby.
You can achieve the exact same things though, using Modules, class methods, and the .inherited / .included / .extended callbacks.
tada!
it's just considered bad python style to do that... because it tromples your global namespace!!
Number of times I've been bit by forgetting the right import statement for a piece of Python library functionality: considerably worse.
I know, "plural of anecdotes" and all that. I think it's hard to argue that Ruby isn't easier to use "out of the box" than Python is, though. How do you say:
in Python? Because, yeah, "days" and "hours" on Numeric? Shit's all crazy! But totally worth it.I also do not know why cpan is mentiond FIRST as perl's greatest assets. To me i think a language should easily provide the capabilities to the programmer without addons, AND I also think that there SHOULD BE ONLY ONE "CPAN" FOR ALL THE SCRIPTING LANGUAGES OUT THERE.
I find it totally silly that there are any distinctions at all.
But back to gems:
I for example am using Ruby since almost 5 years without gems. Others seem to like it that you can simply do "gem install rails" and thats it (unless the debian package manager starts to hate it again... which is btw another thing that sucks.)
I agree that there are people who are concerned with "namespace" pollution, but I simply think so many people are trying to overemphasize. The worst was when I talked to a C# hardcore guy. He basically claimed that being flexible like Ruby is ALWAYS bad (C# does not allow you to change core methods. You must subclass and change that new class then. This is not a smart solution, it simply binds and restricts the developer, and claims that this will be better in the long run. My question is - why not allow being flexible AT THE CHOOSING OF THE DEVELOPER IN QUESTION? The reason is simple. C# is a typical language that is developed from the top-down.
It would be so much better if creating good languages would be a lot easier, so noone has to cater to arrogant developers who try to impose their thinking pattern onto your brain.
In fact I can think of a common one, that many people forget, we often forget the gem include (being why rails includes it for you).
Whenever I read it, people seem to make up contrived problems - and do not give any example.
I would like specific examples please where this interferes with your code.
So far it simply did not interfere with my own ruby code, and I have written really a lot over the 5 years here, including my own bigger "alternative" to gems. (I wanted to release it, but I was lazy and always felt it is easier to use my own idioms. The problem with this approach is that, while it really makes creating something super fast, I would either have to unbundle everything again so I can distribute it, or bundle everything. Both things have huge problems, because if i unbundle everything it will take quite some time to rewrite things really "cleanly" enough for _other_ people. For my personal needs it is totally fine. And if I would distribute things "bundled" together, which means I could release today, then people would simply complain that there are so many things "bundled" together they simply wont need.
Complaining people are annoying.
i know because I am one of them)
from dateutils import relativedelta import datetime datetime.now() - relativedelta(days=3, hours=2)
>It isn't bad at all. (And does not really matter)
* First-class symbols.
>Ok, but python has first class functions.
* Blocks and lambdas. I've read GvR's take on this.
>GvR is right.
* Method definitions in Ruby don't need to accept a "self" argument.
>It isn't bad at all. (And does not really matter)
* Ruby has first-class Regexps. Python has an "re" library. You know what else has an "re" library? C.
> Ruby has private methods. JAva has private methods too. Therefore ruby is bad.
And so on...
p.s. And if you need oop features why use ruby instead of java?
Probably because he values his sanity.
Where would we be without language wars?
Having said that the one thing that Ruby does have is current developer mindset. Important for language development and progression. Is Python to Ruby what Perl is to Php? Used a lot but not mentioned as much?
http://www.reddit.com/r/programming/comments/6xkti/what_does...
Try 1.9. It's usable today, and should be fully stable by January. Performance-wise, it's on par with Python.
I'm not sure what points you're trying to make with your other complaints, but I guess if you "feel" things are hackish, that's OK. What you might consider feeble-minded hacks Python coders consider simple, straightforward implementations.
> * I haven't found an expression that is better written as a list comprehension than as a map/reduce/select expression.
map/select are better iff you have a concise block syntax.
For mapping with a single ready function, all styles are reasonable:
Now suppose you want to modify the mapping function to foo(bar(i)). You could cascade it: but this quickly gets out of hand and makes modifications painful. What you really want is a place to write arbitrary expressions instead of just a function name.With comprehensions OR a good block syntax, it's a smooth transition:
But without one, the change is ugly and annoying: So why wouldn't Python just embrace a nice block syntax? Precisely because this naturally leads to expressing most control structures as functions taking blocks!Now that is not wrong in itself, but it is a question of taste. Pythonic taste favors a different approach: instead of passing the block directly to a function, have a few built-in control structures that can act as combinators.
E.g. don't write an "each" method that accepts a block - write an iterator, and use the built-in "for" loop as a bridge between the iterator and the block. Why would this be any better?
1. Because we can: it turns out that the vast majority of custom control structures can be sorted into a few patterns (iteration, pre/post guards, function wrapping), each served by one natural combinator ("for", "with", decorators). There is a price: it takes time until new patterns are recognized and the missing combinator is added (e.g. "with" is a very recent addition).
2. Decoupling: an iterator is a self-contained passive object that can be used outside of a for loop. An "each" method takes control and is less versatile.
3. Readability: seeing the combinator gives you an immediate idea about the style of flow control. This is just a matter of taste (Lisp and Ruby solve this with naming conventions).
4. Syntax taste: stupid as it sounds, passing blocks to functions is just alien to Python's syntax. Many smart people tried to marry them - and it wasn't a pretty sight...
But in the end you can't judge decisions of taste by pro/con arguments. You have to look at the sweet spots (and the sour spots) that arise in practice. A particularly nice sweet spot that arose in Python is the combination of reduction functions with generator expressions:
This is very cool because the map-reduce pattern covers lots of useful computations. Of course it's just a one case and YMMV. I'm sure Ruby has its own sweet spots...If you're after writing simple computer games fast, then you might have a look at Pygame: http://www.pygame.org/news.html
There are also a number of visual effects companies (ILM, Dreamworks) that use Python as their system scripting language. I don't know if it's because of that community, but I find a number of graphics/games libraries in Python: http://www.vrplumber.com/py3d.py and http://vpython.org/
Blender the open source 3D modeling program used Python as it's scripting language last I checked: http://www.blender.org/
I don't know if Ruby has libraries like that or not. I've only used Ruby to mess around with Rails.
* having to declare "self" in every method argument — reading code, it just clutters up the screen/page
* the big use of of double underscores for special methods (i.e., __init__, __str__, __getattr__, etc...) — IMV, it's gooberish...
* no switch/case statement
In defense of Python over Ruby:
* I prefer the whitespace over the Pascal-ish begin/end, especially for real life code solutions
* the Ruby shorthand syntax IMV at times obfuscates code clarity - is it a method or variable I am looking at?
That said, I'd much rather code in either Ruby or Python than in Java or C...