11 ms·
Ruby is beautiful (but I'm moving to Python)
- jlees 16y agoThis is the reason I stuck with Python for my development and production code. Python scientific programs running on the backend, using all sorts of fancy libraries (NLTK and numpy mostly) and then a Django frontend that plugs right in. I'm dabbling with RoR and it's certainly pleasing at times, but there are the odd bits of Python I keep running into that make me smile too. Especially map. :] To me it seems that half the anti-Python sentiment is because you can write some truly terrible Python code, just as you can write some truly terrible Java code. You can also write some elegant Python code (although there are some situations where you just will run into those damned underscores), but it's in the minority. Coming from Perl (no, really) and Python, my main issue with trying to learn Ruby is all the extra syntax and punctuation. It just looks and feels wrong until you force your way through it and see it from the other side. There are some really nice advanced features of the language (I sat in on an advanced Ruby class and found it surprisingly easy to follow given a background in ML, Perl and others) so I'm still going to persevere and learn it, but I'm still at the "Ruby feels arse-backward" stage. I think to me Ruby feels like Python does to Rubyists. Sort of.
- spacemanaki 16y agoMap isn't really an "odd bit of Python" that you ran into, it's a bit of Lisp.
- jlees 16y agoActually, I know it from ML. I was more smiling at it existing in Python, than Python having 'invented' it.
- softbuilder 16y agoAn unsatisfying article. Judging from the code, I am not convinced that the author gets Ruby. At the very least, Proc#curry doesn't make a very compelling example.
- djacobs 16y agoI'm sorry you feel that way. What about that example makes you think I don't understand Ruby? Composing functions (and currying in arguments one at a time) is probably one of the more powerful things you can do with the language. I wasn't saying that is how I would implement filters. Just that that is the DRYest way to do so--and it's easy in Ruby.
- softbuilder 16y agoYou have nothing to be sorry about. If I had noticed that this was a self-post I would have phrased my response more personally and (hopefully) with more tact. I'm not looking to second guess each of your examples, many of which were fine. I felt that your currying example was trying to bring in a purely functional toolkit ala Lisp when it wasn't appropriate. Function composition (which you allude to in your reply, yet I don't see) and blocks (especially!) show off Ruby's functional capabilities quite well and would be just as effective and more practical. Btw, if you're quite new to Python, do yourself a favor and learn about list comprehensions. They can be quite wonderful. Good luck!
- djacobs 16y agoAh okay, I think I see your point. The currying example was intentionally Lisp-inspired. I didn't mention this, but I've also just started to program in Clojure--though not for work. As I say, I wouldn't use that last technique in my actual code. It just shows how powerful the language actually is. I think my normal code falls in line with the standard Ruby paradigms, but with a functional twist. And yes, list comprehensions are fantastic. :)
- deleted 16y ago[deleted]
- mcritz 16y agoI think the author has done a great job pointing out a need: science tools for Ruby.
- hyperbovine 16y agoI still think Ruby is a little too "expressive" to be taken seriously is scientific circles. In my view, DSLs are not a positive feature in academic work, because everybody's D is different from the next guy's. This is why the linga franca of almost all algorithms papers is, in fact, pseudocode. Python is sufficiently structured that it practically reads like pseudocode.
- sigzero 16y agoYes, but Perl has a huge scientific following as well, so Ruby should be able to used there as well. However, I think with Python and Perl in that niche, it would be hard for Ruby to break significant ground there unless a RoR moments hits for that area with Ruby.
- apl 16y agoThere was a similar discussion elsewhere about this. Short version: what's the point in developing them? Despite what ardent proponents of either will tell you, they're essentially the same language. Porting code from one to the other is straightforward or trivial. Learning one with a background in the other is a matter of days. I get it for the FORTRAN -> Java transition; I understand that you'd want to port your stuff to Python from Java. But why would anyone port massive and complex libraries (SciPy is not your regular "Yep, coded that in 4 days!"-gem) to a virtually identical language? [1] No point. Learn Python, and get some stuff done. [1] Now, if you're about to build a good scientific/numerical/statistical/(...) library for Clojure -- I'm all ears.
- djacobs 16y agoI am, in fact, trying my hand at stats in Clojure, to see if it's a viable alternative. I finished the Wilcoxon Rank Sum Test yesterday, and it's ridiculously elegant compared to the current SciPy implementation. Clojure is pretty fantastic. But where's the package management? Clojure might be a bit too young.
- telemachos 16y agoWhy is the website telling me I'm an administrator? http://d.pr/wfTk http://d.pr/wfTk
- djacobs 16y agoI'm having cache problems, sorry! (This is my first production app.) The problem should be solved for now, though I had to turn off caching to fix it. Urgh, Rails...
- telemachos 16y agoNo apologies necessary. I just wanted to make sure you saw it in case there was a hole you needed to close.
- SteveC 16y ago"Urgh, Rails..." You can hardly blame Rails for your programming error.
- djacobs 16y agoThat was just a comment on how easy it is to screw up caching in Rails. I acknowledge it was my fault.
- mnutt 16y agoYou can't use static page caching, but rails caching should work fine if you use administrator status as a cache key.
- telemachos 16y agoI'm not sure why this is bugging me, but p and puts are not the same thing in Ruby. In most non-debugging contexts, p 'hello world' would be odd since it would print the string for inspection (i.e. with the string literal quotes around it), no?
- djacobs 16y agoYes, that's true. And since I used println in the Java example, I guess I should switch the Ruby example to puts. Will do that now.
- jewbacca 16y agohttp://mitpress.mit.edu/sicp/full-text/book/book.html http://mitpress.mit.edu/sicp/full-text/book/book.html
- Estragon 16y agoI'm not saying you're wrong: I have been using python for so long, there are undoubtedly problems with it which I am so used to I just don't see them. But I'm curious about why python has a reputation in the ruby world as ugly. And yes, installing scipy from scratch is a bear. If you're using a modern linux distribution, you probably want to install a python scipy package.
- gvnonor 16y agoI think len() being a function instead of a method, explicitly specifying self for each method and other inconsistencies(albeit small) lead rubyists to think of python as ugly. I'm no rubyist(I prefer expediency to elegance, hence python over ruby), so take this with a grain of salt.
- tef__ 16y agothe thing is, self being explicit makes it more consistent unlike 'self' in other languages as a keyword, 'self' is just a variable with the same scoping. i.e self always refers to the most inner scope in other languages (a special variable), meanwhile self in python is wherever self was bound in the current scope. and fwiw: len is a holdover from earlier python (you can define a method __len__ if you want...)
- artsrc 16y agoOnce you make a parameter special, subsequent effort to hide that it is special seems odd. The self parameter looked different in the call to the function.
- masklinn 16y ago> len is a holdover from earlier python No. len is basically a multimethod. > (you can define a method __len__ if you want…) You have to, it's part of the length protocol, `len()` will not work if you don't. Because `len(o)` calls `o.__len__()`). If you start calling underscore-methods directly (outside of a super() access), you're heading for trouble with your coworkers.
- 16y ago
- drpancake 16y agoI think there's always been a bit of 'grass is greener' sentiment between the Python and Ruby communities. As a Python guy I do appreciate the look of Ruby code. However for sheer pragmatism Python wins; almost every API and library you can think of has its own Python bindings.
- steveklabnik 16y ago> However for sheer pragmatism Python wins; almost every API and library you can think of has its own Python bindings. This is largely true for Ruby too. Both have great C FFIs, so it's not hard to write these kinds of wrappers. I've never been wanting. I don't think you can really call this a general win for either language, though Ruby does tend to lose out to NumPy and SciPy (from what I hear).
- endtime 16y agoHmm, not for me. I think things like paren-free function calls are awful for readability and array.select &:even? is far, far less clear to me than filter(even, array) Ruby just seems to have tons of unnecessary syntax, I guess.
- zya 16y agoA lot of 'unnecessary' syntax is comming from the fact that block forms 'do..end, {}' are not objects in Ruby. I wish Ruby implemented them the same way as in Smalltalk, to be used as objects passed to a method's arguments. All the 'do..end, {}', '&', 'yield', block_given?, etc. would have been gone. And there would be just one unified way to construct and call a block. This is the only part of the language I find wrong in Ruby. Any Rubyists share the same feeling?
- chc 16y agoYes. I have a feeling it's not even an uncommon sentiment among Rubyists. Ruby's implementation of blocks was a huge chunk of technical debt that it incurred early on when it kind of wanted to be Perl, and all the attempts to patch it up while maintaining backwards compatibility have made it a hugely complex corner of the language. Ruby would be vastly less confusing if they threw out all the current syntax and semantics of blocks, straight-up aped Smalltalk's, and unified them with methods.
- tef__ 16y ago'I love that I can define + for any object in Ruby and that doing so gives me += for free.' fwiw: this works in python too >>> class Foo(object): ... def __add__(self, x): ... print "%s+%s"%(self,x) ... >>> a = Foo() >>> a+=8 <__main__.Foo object at 0x657d0>+8 >>> You can override __iadd__ separately too.
- deleted 16y ago[deleted]
- jfb 16y agoThis is a perfectly cromulent article, but as someone relatively new to Ruby, I don't see the beauty. Perhaps I've spent too much time with the airless asceticism of, say, Scheme, but Ruby just reads a mess to me. Too many synonyms, too much implicit behavior. There's too much language for my taste. Of course, beauty is in the eye of the beholder &c., &c., &c., and I wouldn't deny that there is a certain pragmatic attraction (even I like to get shit working). But beauty?
- steveklabnik 16y agoI think you've answered your own question: beauty is in the eye of the beholder. That said, I think Ruby is beautiful for a few reasons, but they mostly stem from the fact that Ruby strikes the perfect balance between Lisp and Other Languages: it's taken just enough of the good parts of Lisp and grafted them onto a more 'usual' language. Maybe 'grafted' is too harsh, it's Lisp _from the perspective of the rest of the world_. It's taking Lisp's ideas through a slightly different lens. Whatever, I'm almost rambling. You get the idea. Some people think Java is beautiful, too...
- masklinn 16y agoIt's mostly taking Smalltalk's ideas, not Lisp's, and it's crashing those ideas from orbit into Perl, of all things. Ruby doesn't have Lisp-style lambdas, or macros, or conses, it has blocks and messages (it tries to anyway) and classes. That's the Smalltalk recipe book. Ruby uses `select` and `reject`, `collect` and `inject`. Those come from Smalltalk's collections.
- steveklabnik 16y agoBroad generalizations are always false. Smalltalk's influence on Ruby is undeniable, but matz has specifically said Lisp influenced him, as well. You're speaking of Lisp's _features_, I'm talking about Lisp's _ideas_. It may not have 'Lisp macros,' but it does embrace metaprogramming, for example.
- 16y ago
- sahglie 16y agoOr you could use Ruby where it continues to make the most sense and use Python where that makes the most sense. After all, the languages are so similar that keeping them both in the tool belt has less mental overhead than say Ruby and Scala.
- insight 16y agoguys, sorry beautiful and sexy are not for Programming Languages. Really.
- grimen 16y agoI'm not a scientist but this article got a really valid and good point. I only know about this Ruby-lib within the scientific context: http://www.wedesoft.demon.co.uk/hornetseye-api/files/HornetsEye-txt.html http://www.wedesoft.demon.co.uk/hornetseye-api/files/Hornets... One thing that hit me though. The author of the article maybe should consider a little effort. I mean...libraries for scientists should probably be developed by scientists (the target group), which means it's an excellent opportunity for the ones that identify the problem to get something started. No code falls down from heaven. Supply and demand.
- oomkiller 16y agoAs a Ruby programmer, I think it's great to learn Python. While they are similar, there are many differences, and even some advantages to Python. Plus, it never hurts to add to your resume! Finally, Python is usually installed on more systems than Ruby, so if you do lot's of systems administration, you don't have to worry about adding another package.
- ludicast 16y agoTitle is a little flamebaity, considering it seems like he is adding python, rather than "moving to". I like both, but Ruby does it for me bigtime. I actually wish it also had Python's whitespace rules, but since I use Haml a lot I still benefit from it sometimes. One important facet of Ruby is that it was written to optimize programmer happiness. As a result, it is a lot of fun to code in. The article's author says something similar himself: "Now, I want to be clear: I like Ruby better than Python. Its semantics make more sense to me than Python’s, and the language itself is more beautiful." As someone who codes between 2 and 20 hours a day, a language like that is where I want to be. Ruby does have its gaps so other languages are needed too - I use actionscript for front-end stuff (instead of MacRuby) and functional languages for concurrent programming (instead of EventMachine).
- jpcx01 16y agoUsing Ruby extensively with CoffeeScript is also making me long for significant whitespace. I think CoffeeScript gets it perfect. Unfortunately, it's just a wrapper around JS so it has limited uses (until Node.js gets mature).
- ludicast 16y agoHaven't checked out CoffeeScript before, but it's very terse. Me like.
- rue 16y agoYes, I am not sure why one would "move". Learn Python, presto, you now know two handy languages and can use them at your discretion.
- djacobs 16y agoThat's valid. I'm adding it, not moving. That sounded weird for a title, though.
- jamesbritt 16y agoHow does Python's science libraries compare to Java's? If they're comparable, why not use JRuby and use all the Java libs you want?
- dkarl 16y agoIn Python, though, there seem to be competing managers (easy_install and pip) and separate ways to package libraries for uploading. I’m also hearing names like setuptools, distutils, distribute and virtualenv, and I have to say that the whole ecosystem isn’t too clear to me yet. And the documentation tends to assume I know what all the above mean already! This also bugged me the last time I wrote any Python code. I decided the sensible response was to go write Scala code until the situation resolved itself. Has it? (I hope Python never acquires the problem C has, where its users are scattered so far and wide that every halfway valid tool attracts enough satisfied users to sustain itself, preventing the community from being coherent enough to advance in any direction at all. Guido needs to be a Ghengis who keeps all the tribes pulled together and galloping in the same direction, not scattering into disconnected groups.)
- StavrosK 16y agoThose names are not all disjoint. pip has superseded easy_install, so you should use the former, distribute is a way to write setup packages (pip only installs them), and virtualenv is a way to avoid messing up your system with packages by installing them to a single, self-contained directory. There's really no fragmentation whatsoever that I've seen. Install a package using your preferred way, in the end everything installs fine whether it's built with setuptools, distutils or distribute (or just copy the files to your site-packages directory). I haven't read the entire blog post yet, so I haven't gotten to the part you quote, but that's my two cents.
- cdavid 16y agoActually, there is fragmentation: pip does not supersedes easy_install, since easy_install does things that pip cannot do (like installing from something that is not a source tarball). Also, distribute being a fork of setuptools, with neither distribute/setuptools being a superset of each other, means more fragmentation as well. Also, the affirmation that everything install fine whether you use setuptools/distribute/distutils is simply not true. We get almost daily bug reports/user complaints in numpy/scipy because of installation issues mostly caused by distutils, or people using pip/easy_install (which does not work with numpy distutils extensions). The situation is confusing for a lot of users, especially the ones who are not super familiar with python.
- yesimahuman 16y agoComparisons between Java with exception handling and a scripting language with a one liner that does no error checking are pretty worthless.
- djacobs 16y agoThe point is: when I'm writing a script (or better yet, doing this interactively), I don't want error checking. I see an error, and I fix it. This article centers around agile scripting for science, not building enterprise applications or libraries. The point is not that the two samples are exactly equivalent. The points is that you can go no simpler with Java's standard libraries.
- chrisbroadfoot 16y agoAu contraire, I am of the opinion that checked exceptions are the scourge of Java.
- srgseg 16y agoInstead of: public int[] filterEven(int[] array) { aggregator = int[array.size()] for(int i: array) { int aggregatorSize = 0; // The next line is the only unique part of // this function! if(array[i] % 2 == 0) { // Someone please tell me there's an easier way // to append to an array than this aggregator[aggregatorSize] = array[i]; aggregatorSize += 1; } } } int[] array = { 1, 2, 3, 4, 5, 6 }; filterEven(array); // => { 2, 4, 6 } in Java, you'd normally use collections and not arrays. So it'd be: List<Integer> result = new ArrayList<Integer>(); for(int i : argument) if(i%2==0) result.add(i); So it's really 2 lines, not 7. And if you really needed to work on an argument passed in the form of a primitive array, you'd use Arrays.asList(arrayArgument) to easily turn the array into a list. Java really shines when you are doing multithreaded code because you have a rich set of thread safe collections. (e.g. multiple simultaneous requests in a web app all modifying shared data structures). With reading something into a file, anyone that does this often will just use a library (either their own or a 3rd party one). Thus, they'd just do: String data = FileUtil.readFile("abc.txt");
- djacobs 16y agoDuly noted. I asked for alternatives because idiomatic Java eludes me. Thanks.
- chrisbroadfoot 16y agoAgreed. A lot of complaints about Java are because of shit APIs (standard library) rather than the language itself. It's certainly possible to write beautiful code in Java, it's just not very common :) One thing that Java could benefit from greatly would be type inference. That alone would remove so much syntactical noise. Honestly, who cares that you need to write a Main class? This is quite commonplace, and only really inhibits scripting tasks. In any real application, this is a non-issue.
- Tichy 16y agoWhat are good alternatives for data crunching? Incanter suitable yet?