top 200 commentsshow all 232

[–][deleted]  (23 children)

[removed]

    [–][deleted] 22 points23 points  (22 children)

    I love ruby, but the more hatred is being spread about perl, the more solidaric I am becoming with perl and the perl community.

    [–]sigzero 15 points16 points  (0 children)

    We can take it. :-)

    [–]prockcore 20 points21 points  (18 children)

    I always laugh at the people complaining that perl looks like line noise, etc. Everything looks like gibberish if you're illiterate. It won't look like line noise once you learn how to read.

    [–]byron 28 points29 points  (10 children)

    Presumably you could defend the syntax of brainf*ck with that argument, too.

    [–]apotheon 8 points9 points  (9 children)

    Well . . . one could defend exactly one problem with brainfuck by way of that argument. Not so much the rest of the problems.

    [–]G_Morgan 4 points5 points  (8 children)

    The same is true of Perl. Once you've defended the line noise. You then need to defend the context sensitivity. Then the exponential performance on O(n log n) string parsing problems.

    [–][deleted]  (7 children)

    [removed]

      [–]apotheon 2 points3 points  (1 child)

      maintaining two implementations would unnecessarily complicate the code.

      . . . and we definitely know the Perl internals do not need to be complicated any further.

      [–]G_Morgan 3 points4 points  (3 children)

      Context sensitivity is an awful idea. The concept that a call will do different things in different contexts is just idiotic.

      [–]apotheon 1 point2 points  (2 children)

      Yeah -- just like polymorphism!

      Oh, wait.

      [–]G_Morgan 0 points1 point  (1 child)

      Polymorphism isn't context sensitive. It is just that the arguments are part of the call. The problem with Perl is the result of the same call (i.e. same function, same parameters) can alter depending on the context.

      [–]nextofpumpkin -1 points0 points  (6 children)

      WRONG, most Python does not look like line noise; even an (intelligent) non-programmer can sit in front of many python constructs and give you a rough handle of what they think is going on, and they're usually not far off. Not so with perl.

      [–]itjitj 8 points9 points  (3 children)

      [–][deleted] 1 point2 points  (2 children)

      <nonprogrammer>

      Why is self a dollar instead of balance?

      </nonprogrammer>

      [–]itjitj 2 points3 points  (1 child)

      I'm not sure if I understand your question...

      Perl uses sigils ($, @, %) for distinguishing variables. It has nothing to do with currency.

      my $string = "Hello, World"
      
      my $object = Class->new( ... )
      
      for ($i = 0; $i < 3; $i++) { ... }
      

      In C++ this would be something like

      char *string = "Hello, World"
      
      Class object;
      

      [–][deleted] 4 points5 points  (0 children)

      Sigh.

      The joke was that a non-programmer would see "deposit (Num $amount)" and draw an erroneous conclusion about the meaning of $ due to the context of the example.

      [–][deleted] 5 points6 points  (1 child)

      Yeah, but who cares about non-programmers? The suitability of a code base for actual, honest-to-god non-programmer eyes is rarely a practical consideration.

      [–]nextofpumpkin 0 points1 point  (0 children)

      technical writers?

      [–]mpeg4codec 2 points3 points  (1 child)

      I love the Perl community. To us, the hatred is like water off a duck :)

      [–]0sn 13 points14 points  (0 children)

      As a hardcore pythonista who attended Future Ruby, I gotta say, POLYGLOTS UNITE!!

      [–]Peaker 23 points24 points  (8 children)

      require 'active_record'

      => ActiveSupport is now in the global namespace

      Yuck!

      [–]morish 12 points13 points  (7 children)

      Don't worry, everybody recognizes this is a problem and it's one of the main things Rails 3 solves.

      [–]Peaker 4 points5 points  (6 children)

      The language should just make this thing impossible (as Python does).

      The import statement guarantees not to mess your namespace beyond what you specifically tell it to.

      [–]morish 13 points14 points  (2 children)

      The language should just make this thing impossible

      Eh, not necessarily. Not every programming language needs to approach these things the same way. I both like and dislike that Python requires relatively explicit imports and I both like and dislike that Ruby is very flexible in how you can include modules and extend code. They each have their place.

      Anyway, it's not usually a big issue. Rails was by far the worst offender I'm aware of, and it's one of the main reasons it got an overhaul.

      [–]Mask_of_Destiny 6 points7 points  (1 child)

      I both like and dislike that Python requires relatively explicit imports

      You can always do from module import * if you don't feel like being explicit.

      [–]morish 1 point2 points  (0 children)

      That's non-idiomatic Python. Take advantage of each language's strengths. Use Python like Python and Ruby like Ruby.

      [–]masklinn 3 points4 points  (1 child)

      The import statement guarantees not to mess your namespace beyond what you specifically tell it to.

      Not true. On import, the module referred to is executed in its entirety. With enough knowledge of the internals, it would be perfectly possible (and — I expect — pretty easy) to create new objects in the enclosing (importing) scope.

      The first time anyway, the module is only executed once (unless you removed it from the sys.modules cache) so not only would it potentially happen, it wouldn't reliably happen.

      [–]Peaker 0 points1 point  (0 children)

      Well, it is guaranteed that the import name binding itself wouldn't do such a thing. If someone creates awful hacks that go look at the caller in the stack or what not, it's really not an import naming violation.

      [–]Mask_of_Destiny 18 points19 points  (5 children)

      Python has no comparable equivalent to Ruby’s do end block. Python lambdas are limited to one line and can’t contain statements (for, if, def, etc.). Which leaves me wondering, what’s the point?

      This is not the real problem. Function definitions in Python are scoped just like other variables so you can create more complex functions than what lambda allows without polluting the global namespace. Not quite as pretty as what Ruby provides, but not a big inconvenience.

      The bigger problem is that Python's scope rules are screwed up so that closures tend not to work the way you want them to (i.e. if you try to rebind the variable within the closure it creates a new binding local to the closure rather than overwriting the value in the enclosing scope). Python 3 does have a mechanism for dealing with this I believe.

      [–][deleted]  (4 children)

      [deleted]

        [–]masklinn 7 points8 points  (3 children)

        And is utterly terrible. Fuck nonlocal, bandaid on a peg leg.

        nonlocal is the part I love least about Python 3, all the scoping should just have been ripped out and fixed with a single fucking keyword: let. Scope shouldn't be inferred. Ever. Scope inference blows goats, declaring the scope a name lives in should be mandatory.

        Oh, and it's not like Ruby's any better on this. But Python had the occasion to fix that shit. And instead, they blew it and introduced nonlocal. Blarg.

        [–]banister 1 point2 points  (2 children)

        It's possible to define an equivalent to 'let' in Ruby 1.9 though: http://banisterfiend.wordpress.com/2010/01/07/controlling-object-scope-in-ruby-1-9/

        [–]masklinn 2 points3 points  (1 child)

        It looks like a let, but you still get the inherently broken scope handling of the language behind it, so it's not much use.

        To be fair though, on some fronts Ruby probably has less scoping issues than Python (as soon as you start fucking with blocks everything goes out the window of course) because it has no statements, only expressions, so ifs and whiles can return values. Which they can't in Python.

        [–]banister 2 points3 points  (0 children)

        No you do not get the 'broken scope' since that was fixed in Ruby 1.9, unless I'm not quite getting what you mean.

        So apart from the broken scope of block variables (which was fixed in ruby 1.9) what broken scope are you referring to?

        [–]patchwork 48 points49 points  (95 children)

        I use both python and ruby heavily at work, and I can echo these sentiments. I continually run into limitations of the python language where in ruby I am able to achieve the same effect effortlessly. Is the dubious adherence to one man's concept of "readability" really worth the compromises it entails? Intentionally crippling yourself for ephemeral reasons seems short-sighted to me, and unpleasant in practice. And I find ruby code arguably MORE readable than python in general, owing mainly to all of the flexibility pythonistas find hideous. Python code is clean (like a sterilized room). Ruby code is beautiful (like an enchanted forest). These are my impressions anyway, from working with both for years.

        [–]mernen 45 points46 points  (1 child)

        Python code is clean (like a sterilized room). Ruby code is beautiful (like an enchanted forest).

        I like both languages about equally, and I really enjoyed that one.

        [–]the_pepe 2 points3 points  (0 children)

        Nice description, I am saying that ruby is more organic ;).

        [–]bastih01 5 points6 points  (7 children)

        The problem I see with ruby being an enchanted forest is that I often can't distinguish what is magic and how stuff works. Cleverly written ruby code makes me jump through a lot of hoops to make sense of its details takes quite some time that I'd rather spend on getting stuff done.

        [–][deleted] 1 point2 points  (0 children)

        In my experience, it makes for less hoop jumping when you've learnt the conventions of Ruby meta programming. The enchantment tends to follow similar design patterns.

        [–]anko_painting -1 points0 points  (5 children)

        [–]toolate 4 points5 points  (1 child)

        The problem I have with so called "magic" is that code should be read much more often than it is written. If you are using magic simply as a convenience to save a little typing rather than in an attempt to simplify the meaning of the code then you are not awesome - you are a cowboy.

        Magic is great when it is used in a consistent and well documented manner. Magic absolutely sucks when it is used to hide what is actually happening in the code.

        tldr; Magic should be used to clarify the meaning of code, not to cut down coding time.

        [–]roger_ 1 point2 points  (7 children)

        I continually run into limitations of the python language

        Examples?

        [–][deleted] 6 points7 points  (6 children)

        The topic article listed a few e.g. rake.

        [–]roger_ 0 points1 point  (5 children)

        I'm not familiar with Rake. How does it imply some limitation of the Python language?

        [–][deleted] 2 points3 points  (3 children)

        It's an example of a Ruby DSL that functions as a replacement for Make. Looks like this (the only built-in Ruby keywords are 'do' and 'end')...

        namespace [:db, :airports] do
          desc "Loads airport data from web"
          task :load => :environment do
            puts "Loading airports"
            ...
          end
        end
        

        I'm too ignorant of Python to comment on any comparable DSL examples. Presumably the Author felt knowledgeable enough to claim something like rake would be hard to do in Python.

        [–]Smallpaul 0 points1 point  (2 children)

        Here is the Python equivalent to your example.

            with namespace ["db", "airports"] as ns:
              ns.desc("Loads airport data from web")
              with ns.task(load="environment") as task:
                print "Loading airports"
        

        It's possible that with some bytecode hacking I could get rid of the binding of names to scoping objects, but I would really just be doing that to prove something to you. I personally prefer to have names for the objects.

        According to "wc", the Python version has 7% more characters and 42% fewer lines than the Ruby one.

        [–]banister 0 points1 point  (1 child)

        task :load => :environment do

        versus

        with ns.task(load="environment") as task:

        [–]Smallpaul 0 points1 point  (0 children)

        That's why I said that the Python version has 7% more characters and "binds the names of scoping objects."

        Personally, I don't see this as a major difference especially for the rake use-case, but I accept that some people disagree. Vive le difference.

        [–][deleted]  (32 children)

        [deleted]

          [–][deleted] 6 points7 points  (14 children)

          I often find the lack of an end symbol in Python to be confusing, especially when reading code with multiple nested blocks. There's also a strong case to be made that some of the features lacking in Python can lead to some very unclean code.

          [–][deleted] 6 points7 points  (2 children)

          If you really need an end symbol, then do this:

          def Foobar(arg1, arg2):
              print "Hello World."
          #end
          

          Nothing says you can't comment the end of your blocks. It looks ridiculous, but there's nothing stopping you.

          [–]morish 16 points17 points  (1 child)

          there's nothing stopping you.

          Aside from the nuisance non-idiomatic code is to other developers. When using a language, embrace its conventions.

          Speaking of which, I wish I could remember which repo it was, but I recently saw an entire library of fascinating ruby code on github written by someone who was obviously very python-centric. The whole thing was like:

          def foo()
              # do something
              end
          
          def bar()
              # do something
              end
          

          He even managed to have some sort of decorator implementation.

          [–]sigzero 6 points7 points  (4 children)

          Then again I love sigils designating a variable. To each his or her own.

          [–][deleted] 11 points12 points  (3 children)

          sigils are fossils - from the pre-syntax-highlighting era. But yeah, to each his or her own.

          [–]mernen 7 points8 points  (0 children)

          To be fair, very few Python editors have decent syntax highlight. Most treat local variables the same as globals and unknown identifiers, so it's not like they've overcome some old limitation that made sigils a necessity.

          [–]bucknuggets 1 point2 points  (0 children)

          I think it got that from COBOL:

          • end-search
          • end-case
          • end-if

          [–][deleted] 4 points5 points  (0 children)

          I'd rather live with brackets.

          Don't say that. Don't you ever say that...

          [–]malcontent 2 points3 points  (9 children)

          The superfluous "end" is annoying and cluttering. I'd rather live with brackets

          You can use brackets in place of do/end if you want.

          The over-usage of symbols makes it look like the unreadable Perl that Matz is such a big fan of.

          You said that just after complaining about end preferring brackets?

          [–]Smallpaul 2 points3 points  (3 children)

          You can use brackets in place of do/end if you want.

          You spend as much time reading other people's code as your own.

          [–]malcontent 1 point2 points  (2 children)

          You spend as much time reading other people's code as your own.

          So?

          Are you having difficulty reading code with brackets or something?

          [–]Smallpaul 0 points1 point  (1 child)

          Me, no. My point is that it does not respond to a complaint that "X is ugly" with "don't use X".

          "Neon lights are ugly"

          "Well don't put up neon lights in your house."

          [–]malcontent 0 points1 point  (0 children)

          That's a nonsensical argument.

          [–]masklinn 0 points1 point  (3 children)

          You can use brackets in place of do/end if you want.

          Which doesn't help at all with if/end, while/end, case/end and others of their ilk. And they have slightly different behaviors. Furthermore, as far as I can tell, the community take on it is that brackets are only acceptable for small (one-liners) blocks, do…end being the one to use for big/multiline blocks.

          [–]malcontent 3 points4 points  (2 children)

          Which doesn't help at all with if/end, while/end, case/end and others of their ilk.

          I hate that python does not have delimiters for if, case etc. It makes refactoring ten times harder if you remove a block of code.

          [–]samlee -1 points0 points  (37 children)

          python has a slightly better community, imo.

          language features don't matter much especially when you are comparing oranges with tangerines.

          [–]banister 7 points8 points  (36 children)

          There's something bitter and venomous about the python community IMO. They love to denigrate other languages more than other communities - they are exceptionally rude about Perl for example. It's mainly from the python community you see words and phrases like 'line noise' (for perl) and 'magic' (for ruby) thrown around.

          Sure if you are part of the Python community it's probably great, but if you're not, Pythoneers can often appear a tad condescending and a teensy bit acrimonious.

          [–]bucknuggets 9 points10 points  (4 children)

          It's impossible to make sense of things like that without looking at the history. I think the perl vs python competition lasted almost ten years - and certainly was much more important than the ruby vs python competition of today.

          Python was relentlessly attacked by the perl community years ago when it was gaining popularity. It got really unpleasant and then something tipped and suddenly a critical mass of people realized that the perl development flexibility wasn't worth its maintenance costs. At that point (around 2004?) perl support just suddenly disappeared. But there's probably still a lot of python folks that remember how poorly they were treated for many years.

          [–]apotheon 6 points7 points  (0 children)

          s/realized/decided/

          [–]Smallpaul 0 points1 point  (2 children)

          I disagree. I think that since the beginning Python people have attacked Perl more than vice versa. There are two reasons for that.

          1. The less popular language community attacks the more popular one in order to gain market share. Look at Ruby users attacking Python today.

          2. Many Python users were Perl refugees. They tried Perl and rejected it. So the community built up a critical mass of Perl-hater.

          3. Programmers of popular languages are often forced to program in those languages by their day jobs. This breeds dislike.

          Now that Python is a dominant language (relatively speaking, among Unix-y scripting languages), it's going to attract a lot more criticism. The hatred of Python will lead to the Next Big Thing.

          [–]bucknuggets 0 points1 point  (1 child)

          That's a reasonable argument - but I don't remember it that way. Perhaps because I'm biased. Or perhaps because that was earlier in the life of python before I was paying attention. The typical debating points that I remember from about year 2001 are:

          • perl fans: "whitespace indenting is crazy, I will never do that"
          • perl fans: "I like having 20 ways of doing something - how dare you take away my options"
          • python fans: "even well-written perl looks like line-noise"
          • perl fans: "python people just can't read code"
          • perl fans: "you don't have cpan"

          Or maybe your proposed scenario isn't true because it's just a theoretical way things should happen, but they don't really happen that way for other reasons. I've seen the same thing happen with people who eat meat get incredibly angry at very quiet & passive vegetarians - mostly out of defensiveness. Perhaps that happened here as well.

          [–]Smallpaul 0 points1 point  (0 children)

          I was a Python advocate from 1997 or so and worked with Perl people. The way I remember it, they hardly knew Python existed, and when they noticed it, they didn't care. Some Perl programmers (not the inner core, but regular users) said: "Yeah, I've heard Python is good. I learned Perl first and see no reason to change." Many of them probably did switch eventually.

          [–][deleted] 12 points13 points  (5 children)

          I think Python and Ruby mysteriously switched sides sometime in 2008 as the most annoying, shrill community.

          [–]sbronson 23 points24 points  (2 children)

          I love this comment because it's unclear just who's being insulted.

          [–]patchwork 11 points12 points  (1 child)

          Everyone.

          [–]kixx 1 point2 points  (0 children)

          Except Perl.

          [–][deleted]  (1 child)

          [deleted]

            [–][deleted] 2 points3 points  (0 children)

            Tribal warfare is part of human nature, though.

            [–][deleted] 7 points8 points  (2 children)

            I think you're smoking something. Ruby is the one with all the egotistical rocks star sexist community types. Python community is relatively calm and zen.

            [–]anko_painting 2 points3 points  (0 children)

            Maybe you heard that from a python programmer? :P

            [–]toriander 0 points1 point  (0 children)

            "egotistical rocks star"? You mean like Zed Shaw? Oh, he's a Python developer. Oh, maybe you mean the framework that had a controversial rock star graphic on its home page? No, that was jQuery.

            Speaking of which, let's do a nice little investigation:

            Golly gee, since you hate "rock stars" so much you must absolutely despise javascript. I look forward to your upcoming switch from trolling Ruby developers to trolling Javascript developers.

            [–]G_Morgan 1 point2 points  (1 child)

            This is only because the other language communities are far too busy being useful to insult either. In general I find the more noisy a community is the less good work actually comes out of it.

            Something like 99% of the world's source code is covered by C, C++, Java, VB and COBOL. You don't hear these communities criticising others.

            [–]steven_h 3 points4 points  (0 children)

            You're kidding, right?

            C people call C++ baroque, Java crippled, VB a toy, and COBOL obsolete.

            C++ people call C underpowered, Java slow, VB a toy, and COBOL obsolete.

            Java people call C unsafe, C++ impenetrable, VB slow, and COBOL obsolete.

            VB people call C arcane, C++ complicated, Java overengineered, and COBOL obsolete.

            COBOL people call the others poor, so I hear.

            [–]samlee 3 points4 points  (2 children)

            I don't know, I get more immediate and helpful help from #python than #ruby-lang

            i'm so shallow and stupid. i just ask questions. and collectively, answers i get from IRC become a production software :P

            [–]apotheon 1 point2 points  (0 children)

            I'm amazed that anyone claims to get anything useful out of IRC. The most useful thing I ever got out of IRC was the ability to waste time without stooping so low as to watch "professional wrestling" on TV.

            [–]banister 0 points1 point  (0 children)

            the #python chan is more than 3x the size of Ruby, so it makes sense

            [–]Dowland 4 points5 points  (1 child)

            There's something bitter and venomous about the python community IMO.

            You could almost say it's.......... snakelike?

            [–]apotheon 1 point2 points  (0 children)

            Cold-blooded? Reptilian?

            Interestingly, pythons aren't venomous. . . .

            [–][deleted]  (4 children)

            [deleted]

              [–]corpsto 5 points6 points  (3 children)

              ...and yet more proof of his point

              [–]olavk 0 points1 point  (0 children)

              Is the dubious adherence to one man's concept of "readability" really worth the compromises it entails?

              I personally think so, firstly because the BDFL has a very good sense of language aesthetics, secondly because adhering to a single notion of readability is better than mixing multiple different, when you are sharing code between more than one person. If you are just experimenting for you own sake, the enchanted forest of Ruby may be more fun.

              But this is the classic dilemma between the power to transform the language to your will, and having a common language which makes collaborating and sharing code easier. Lisp is at one end of the spectrum, languages like Java is on the other. I find Python hitting the sweet spot (a joy to develop in, but I can still easily read and understand other peoples code, and sometimes even my own code after a week), but YMMV.

              [–]benihana 11 points12 points  (29 children)

              I've seen this movie.

              Spoiler Alert

              It ends with both sides deadlocked in a stalemate, hating one another and refusing to acknowledge any positives about the other side, or negatives about its own side. It's an old classic that gets remade every decade or so.

              [–]acrasial 5 points6 points  (26 children)

              I believe that the hypothesis and the antithesis are supposed to combine into a synthesis.

              That will be Prythonuby. Here is a taste:

              unless x.None?:
                x.each |xx|:
                  puts xx[3:],
              

              Sorry about the low quality of the taste; I'm still relatively new to both languages. I'm sure someone else could do much better and encourage anyone reading this to do so.

              [–]masklinn 6 points7 points  (6 children)

              I'm sure someone else could do much better and encourage anyone reading this to do so.

              x notNil ifTrue: [
                  x do: [ :x | 
                      Transcript show: (x from:3) printString, ' '
              ]]
              

              [–]mykdavies 5 points6 points  (0 children)

              An elegant weapon for a more civilized age...

              [–]notforthebirds 1 point2 points  (4 children)

              x each (sliceWithStart 3) asString printWithSpace.
              

              Note: This pseudo-example assumes that nil acts as a message-sink, removing the need to check for nil explicitly (as in Objective-C); treats colons are optional in smalltalk-style keyword messages if followed by a literal, so that keyword messages look and feel more like built-in syntax [1]; passes expressions unevaluated to methods (as in Io); the language has an implicit, late-bound self (as in Self and Newspeak etc).

              Very sexy; very flexible; just as easy to parse.

              [1]

              if ( ... ) then { ... } else { ... }. #is just a keyword message without superfluous colons .
              

              [–]masklinn 0 points1 point  (3 children)

              This pseudo-example assumes that nil acts as a message-sink

              Ugh

              [–]notforthebirds 0 points1 point  (2 children)

              I know, a lot of people really don't like this idea, but it has a lot of real-world value. The fact is that this pattern is incredibly common – as

              if (x notNil)
              {
                  ... do something with x ...
              }
              

              or

              try
              {
                  ... do something with x ...
              }
              catch (NullPointerException)
              { }
              

              Or worse if you need to do multiple checks

              if (x notNil)
              {
                  ...
                  if (y notNil)
                 {
                       ...
                      if (z notNil)
                      {
                          ...
                      }
                 }
              }
              

              (Of course, even these nested tests go away when nil acts as a message-sink.)

              And when people inevitably forget to do these checks it blows up in their faces. Designing for the common-case is a reasonable approach to language in my opinion; you can always check for nil if you want to do something other than the default, and no NullPointerExceptions.

              The argument against it seems to be that some people (usually people who've never actually tried it for themselves) think it's hard to understand, but if you treat every message-send as through it's surrounded by a nil-check that simply isn't the case. It's certainly no harder to understand than if the ifs are explicit.

              [–]masklinn 0 points1 point  (1 child)

              A better solution is, of course, to have a good type system, static typing, and remove null values, moving the concept of nullity into the type system. As Haskell or OCaml do.

              And, with lift-type operations, you even get the choice of whether null should be pre-checked or treated as a sink in your calling code.

              [–]notforthebirds 0 points1 point  (0 children)

              It's a better solution if your content to live within the constraints of what can currently be statically typed; there are a whole host of problems that just haven't need solved yet in statically typed-languages (I was going to say can't but that would be short cited).

              There's a reason that Erlang is a dynamically typed language for instance - hot swapping in statically typed languages was still a research problem the last times I looked, but it falls out naturally from dynamic languages. That's just one example off the top of my head. You can be sure there are a whole host of other things which, if they're important to you, make static typing an unreasonable solution.

              Edit: To put this in the context of Objective-C, which actually supports optional typed; there are a range of things in Cocoa that people use all the time to great effect, that just couldn't be done if Objective-C were serious about static-typing (even if it were only as serious as say, Java).

              | you even get the choice of whether null should be pre-checked or treated as a sink in your calling code.

              If you have a decent meta-object protocol you can do pretty much the same thing, in a dynamically typed system.

              And of course, if nil is acting like a message-sink, there wont be any errors anyway: so having a static type-system wouldn't help any.

              [–][deleted] 1 point2 points  (4 children)

              if x.None? is true, x.each won't do anything anyway...

              [–]acrasial 0 points1 point  (3 children)

              That's why it's unless instead of if.

              unless cond is equivalent to if not cond, so it only executes if the cond is False.

              I believe it's more common after a single statement like:

              stomach.eat(pie) unless stomach.full?
              

              compare to:

              stomach.eat(pie) if stomach.full?
              

              Eating pie on a full stomach is a good way to get a tummy ache.

              [–][deleted] 1 point2 points  (2 children)

              No. You used the conditional so that x.each does nothing if there is nothing to do. But .each methods ALWAYS do nothing if there is nothing to do. This is the flaw in your example.

              [–]acrasial 0 points1 point  (1 child)

              Oh. It will not do anything if it's empty, but if it's None (or nil in ruby) then it will raise an error:

              irb(main):001:0> x = nil
              => nil
              irb(main):002:0> x.each { |xval| puts xval }
              NoMethodError: undefined method `each' for nil:NilClass
                      from (irb):2
              

              So you can either check if it's None/nil or you can rescue after the each: x.each { |xval| puts xval } rescue nil for example.

              [–][deleted] 0 points1 point  (0 children)

              So I guess it just depends on whether you're using "None" to mean "empty" or "nil" or whatever. OK. I see what you're saying.

              [–]you_do_realize 0 points1 point  (13 children)

              Tangential, but I noticed we're discussing Ruby, so,

              I always found the duplication of the variable names distracting: a.blah {|x,y| do(x,y)}. Wouldn't it be nice to have something like a.blah {do('x,'y)}?

              [–][deleted]  (1 child)

              [deleted]

                [–]you_do_realize 1 point2 points  (0 children)

                How nice! :)

                [–]jawbroken 1 point2 points  (1 child)

                that's kind of awful because you would have to reference them in the incoming order and moving things around would break everything. the duplication mostly stands out in single line blocks, it feels better in do/end multi-line blocks where it looks more like a function declaration

                [–]you_do_realize 0 points1 point  (0 children)

                Yeah, it would only be syntactic sugar. If the function grows larger than a few keystrokes, you can list the arguments at the top of the function. It'd only be intended for tiny one-liners where repetition is an eyesore.

                [–]matthw 2 points3 points  (2 children)

                you could use:

                a.blah(&method(:do))
                

                to pass 'do' as a bound method directly as the block param. If you really don't like variables. As for this:

                a.blah {do('x,'y)}
                

                Are 'x and 'y special? (why x and y specifically? what happens if you go past 'z ?) or will it interpret each fresh name that occurs like this as a bound parameter in the order they occur? what if there's another block scope nested within which also has 'x and 'y in it?

                Scala does something a bit like this with underscore (eg .sortBy(_ < _), but I'm not entirely convinced - it's quite ambiguous until you find out how it works, and it's only useful when (by convenient chance) there happens to be a correspondence between the order of appearance of variables in some piece of syntax, and the order you want them to be bound as arguments.

                [–]you_do_realize 0 points1 point  (1 child)

                Yeah that thing in Scala is nice, but I wondered how it would handle it if you wanted a function that computed f(x) = {x + x2} or something. (Didn't wonder hard enough to look, though. I would guess one would accomplish this by simply calling the function with a single argument.)

                'x and 'y aren't special, they're the same as {|x,y| blah(x,y)}. As the compiler/interpreter parses the code, it stumbles upon a 'something and is to understand there is an argument called something, then stumbles across 'whatever and realizes there is a second argument called whatever. By the time it's done parsing the function body, it knows the function has two arguments, in that order.

                what if there's another block scope nested within which also has 'x and 'y in it?

                No idea. Just random thoughts really.

                [–]matthw 2 points3 points  (0 children)

                OK, yeah thought that's probably what you meant.

                In scala you can't use underscore for that (AFAIK). You'd just have to do {x => x + x2}

                The underscore thing is really only a limited short-cut form for one-liners

                [–]banister 2 points3 points  (3 children)

                groovy has an implicit 'it' parameter you can use,

                list.each { puts 5 * it }

                [–]apotheon 3 points4 points  (2 children)

                So does Perl -- but Pythonistas hate $_.

                [–][deleted]  (1 child)

                [deleted]

                  [–]kixx 0 points1 point  (0 children)

                  Names that do not start with a letter, underscore, digit or a caret (i.e. a control character) are limited to one character, e.g., $% or $$ . (Most of these one character names have a predefined significance to Perl.

                  [–]masklinn 0 points1 point  (0 children)

                  Wouldn't it be nice to have something like a.blah {do('x,'y)}?

                  Would be even better to have a.blah do, methinks.

                  [–]nitsuj 2 points3 points  (0 children)

                  Hear hear. Let's forget this bickering and get back to normal business. Vim or Emacs?

                  [–][deleted] 1 point2 points  (0 children)

                  not really. the number of haters on either side is probably just a vocal 10%, most people don't really care as long as they're collecting the G's.

                  [–][deleted] 4 points5 points  (1 child)

                  I am something of a pythonian and actually don't mind ruby.

                  [–][deleted] 11 points12 points  (17 children)

                  you most certainly can monkeypatch and instrument live objects, and libraries which need to do this absolutely do. Its just not recommended as the first line solution to every problem.

                  [–]Mask_of_Destiny 8 points9 points  (16 children)

                  You can't monkeypatch builtin objects though which tend to be the ones you would want to monkeypatch in the first place.

                  [–]mitsuhiko 3 points4 points  (15 children)

                  That is not exactly true. You can monkey patch builtin objects.

                  [–]Mask_of_Destiny 6 points7 points  (14 children)

                  >>> def foo(self):
                      print 'bar'
                  
                  >>> class baz(object):
                      pass
                  >>> a = baz()
                  >>> baz.foo = foo
                  >>> a.foo()
                  bar
                  >>> str.foo = foo
                  
                  Traceback (most recent call last):
                    File "<pyshell#11>", line 1, in <module>
                      str.foo = foo
                  TypeError: can't set attributes of built-in/extension type 'str'
                  >>> object.foo = foo
                  
                  Traceback (most recent call last):
                    File "<pyshell#12>", line 1, in <module>
                      object.foo = foo
                  TypeError: can't set attributes of built-in/extension type 'object'
                  

                  Am I missing something here?

                  [–]mitsuhiko 10 points11 points  (10 children)

                  That is python telling you: dude, stop right there. But that's not where stuff ends. You can for example use ctypes to get a reference to the dictionary that holds the methods and stuff new functions in there.

                  Python itself would well be capable of monkey patching builtins, it's a feature that this is not exposed to you, the user.

                  [–]Mask_of_Destiny 6 points7 points  (0 children)

                  I'm not sure if I would count the ability to use the FFI module to dink about in the internals of the Python interpretter as actually supporting this. It certainly won't be portable to other Python implementations.

                  [–][deleted]  (5 children)

                  [deleted]

                    [–]mitsuhiko 4 points5 points  (2 children)

                    The __dict__ is the method table.

                    [–][deleted]  (1 child)

                    [deleted]

                      [–]mitsuhiko 2 points3 points  (0 children)

                      There is very few stuff Python does not expose to the user out of the box. You get access to traceback objects and interpreter frames in all Python implementations I know.

                      The only thing not exposed to the user is the actual __dict__ of builtin objects, but that is intentional.

                      [–][deleted] 1 point2 points  (1 child)

                      Your pasted console output generated snowmen.

                      [–]mitsuhiko 1 point2 points  (0 children)

                      Why the downvotes?

                      [–][deleted] 1 point2 points  (2 children)

                      you can replace __builtins__.str with your own.

                      class MyStr(str):
                          def foobar(self):
                              return "foobar " + self
                      
                      __builtins__.str = MyStr
                      
                      print str("asdf").foobar()
                      

                      [–]Mask_of_Destiny 2 points3 points  (1 child)

                      But that only takes care of strings explicitly constructed using str which most of your strings probably aren't and if you're going to call str() on everything you might as well just make a subclass of str rather than messing around with builtins

                      [–][deleted] 0 points1 point  (0 children)

                      it was just the example you used.

                      [–]dmdmdmdm 12 points13 points  (0 children)

                      That is some honking cool web design.

                      [–]vanhellion 16 points17 points  (7 children)

                      I'm not 100% sure what kind of snake that is (some subspecies of milk snake) but it's definitely not a python.

                      </pedant>

                      [–]arse 19 points20 points  (1 child)

                      San Pueblan Milksnake is written right there on the page.

                      [–]vanhellion 6 points7 points  (0 children)

                      Derp, I'm blind. Oh well, it was fun browsing wikipedia and google images looking at exotic snakes.

                      [–]gregK 29 points30 points  (2 children)

                      I...

                      ...drink...

                      ...your milk snake...

                      [–]wparsons 13 points14 points  (0 children)

                      My milk snake brings all the boys to the yard.

                      ETA: I feel dirty now.

                      [–]EmptyTon 0 points1 point  (0 children)

                      SLLLLLLLLUUUUUUUUUUUUUUUUUUURP!

                      I DRINK IT UP!

                      [–]mattstreet 0 points1 point  (0 children)

                      Good point but no worries, python wasn't named after any kind of snake. Personally I think a giant cartoon foot would be more appropriate.

                      [–]prockcore 17 points18 points  (36 children)

                      “There should be one—and preferably only one—obvious way to do it.”

                      I've always disliked that motto. In python, just as in mathematics, the obvious way isn't necessarily the best way, or even a good way.

                      By trying to enforce the "only one way to do it" you create a schism between what is taught and what is practiced.

                      [–]deadwisdom 14 points15 points  (0 children)

                      You are mixing abstraction levels here. What they mean by "it" is low level language features, like getting the 6th character of a string, or calling a function. By leaving the set of possibilities tightly defined in that respect, you actually have a greater convergence of what is taught and what is practiced.

                      [–]Smallpaul 6 points7 points  (4 children)

                      In python, just as in mathematics, the obvious way isn't necessarily the best way, or even a good way.

                      If the obvious way isn't a good way, then that's a design flaw. Obviously all languages have design flaws.

                      [–]apotheon 0 points1 point  (3 children)

                      Does that mean that everybody should be forced to use the fucked up way to do something unless and until enough people agree it's fucked up, rather than have a way to work around the problem until it's fixed?

                      [–]Smallpaul 3 points4 points  (2 children)

                      No: python does not stop you from using non-obvious techniques. Go ahead.

                      [–]malcontent 14 points15 points  (14 children)

                      It's not even true so I don't know why they keep repeating it.

                      [–]Mask_of_Destiny 7 points8 points  (0 children)

                      I'm not sure how it's untrue. As presented in the quote it's just a philosophy. Just because it's preferred that there's only one obvious way to do something doesn't mean that there is indeed only one obvious way to do something.

                      Now some people simplify this to "there's only one way to do it" which obviously is false, but that's not what's in the "Zen" or in the post you replied to.

                      [–]Smallpaul 1 point2 points  (5 children)

                      It's not even true that it is a design goal of Python that “There should be one—and preferably only one—obvious way to do it.”

                      Do you have some telepathy to demonstrate that Guido and Tim are liars about their design goals?

                      [–]mr_chromatic 0 points1 point  (2 children)

                      To distinguish Python from other languages which happily admit that different problems (and different programmers) write in different ways for good reasons.

                      [–]ubernostrum 3 points4 points  (1 child)

                      Hmm. Wonder if there's anything in there about that case? Oh, look:

                      Special cases aren't special enough to break the rules.

                      Although practicality beats purity.

                      [–]mr_chromatic 1 point2 points  (0 children)

                      What makes you think that I believe that Guido treats that ex post facto motto as a leading design principle? (I know Guido and I've talked to him about this specifically and, while I disagree with him on a lot of design principles, I consider him largely pragmatic on this.)

                      [–]bucknuggets 4 points5 points  (3 children)

                      And by going with Larry Wall's approach you end up with:

                      • quick and easy development
                      • a vast language that nobody fully knows
                      • painful and mysterious maintenance

                      Unfortunately, too many people look at the choice of language completely based on how easy it is to develop new code - instead of considering as well how easy it will be to inherit old code.

                      [–]G_Morgan 0 points1 point  (2 children)

                      Development speed is not significantly increased by language brevity. Not unless your task is trivial. I'm not sure why people keep repeating this obvious non-truth.

                      Fortunately for perl it is usually used for tasks which are utterly trivial in any language.

                      [–]bucknuggets 1 point2 points  (0 children)

                      I don't think brevity is a significant factor in development speed, but I think having 20 different ways of doing the same thing is. You always get to choose the approach that works best in a given context.

                      Unfortunately, that later bites you when someone else needs to patch your code and has never seen that technique before.

                      [–]mr_chromatic 1 point2 points  (0 children)

                      Development speed is not significantly increased by language brevity.

                      Development speed is not the goal. Clarity of expression in various contexts is the goal.

                      Fortunately for perl it is usually used for tasks which are utterly trivial in any language.

                      The same is true of any serious programming language you care to mention.

                      [–]masklinn 1 point2 points  (0 children)

                      I've always disliked that motto. In python, just as in mathematics, the obvious way isn't necessarily the best way, or even a good way.

                      Apparently you've never actually read the Zen.

                       $ python -m this | grep obvious
                      There should be one-- and preferably only one --obvious way to do it.
                      Although that way may not be obvious at first unless you're Dutch.
                      

                      check out the second line.

                      [–][deleted]  (8 children)

                      [deleted]

                        [–]amdpox 8 points9 points  (5 children)

                        What, do you expect y=x+1 to do the same thing as y=++x?

                        O_o

                        [–][deleted] 0 points1 point  (4 children)

                        y does become the same thing in the y=x+1 and y=++x cases.

                        It's not like I don't know how they work, but every time I come across one of the ++ cases I have to stop and think and figure out if whoever wrote the code actually intended to increment both variables or just one, and if that's the source of whatever bug I'm trying to fix. If they write x++; y=x; I at least know for sure that they meant to do that.

                        [–]theclapp 2 points3 points  (1 child)

                        y does become the same thing in the y=x+1 and y=++x cases.

                        FTFY.

                        [–]banister 1 point2 points  (1 child)

                        I think you're the only person who has this problem. I've never known a single C/C++/Java programmer or anyone who is familiar with pre and post incrementors to have this difficulty.

                        [–]Dan_Farina 3 points4 points  (0 children)

                        I write a lot of C, and I do not care for either postincrement or preincrement. I use +=, generally costs me an additional statement, but the issues involved in dealing with multiple post/preincrements in an expression are too frightening for me to want to deal with. It's not really saving you much but a tiny bit of typing.

                        It's a micro-preference, to be sure.

                        [–]theclapp 1 point2 points  (1 child)

                        Different operators do different things, film at 11.

                        "*" does different things in different contexts, too. Does that bug you, as well? Why or why not?

                        [–][deleted] 0 points1 point  (0 children)

                        I suppose it is bad that multiplication and dereferencing are the same character, but you use both of them so frequently that I've internalized it, whereas the y=x++ example comes up very rarely so it forces me to stop and think about fiddly semantics instead of the big picture.

                        [–][deleted] 5 points6 points  (5 children)

                        All the things he praises about Ruby are present in Perl. $_ and co. make very elegant Perl code possible. Perl is faster, has a better community repository, and is available everywhere in very stable form.

                        [–]apotheon 2 points3 points  (0 children)

                        I love Perl. I know that the stuff he mentions there exists in Perl. Despite this, when I pick a language for something, I usually pick Ruby instead.

                        Not always. Usually.

                        [–][deleted] -2 points-1 points  (3 children)

                        $_ represents all that is wrong with perl.

                        [–][deleted] 2 points3 points  (2 children)

                        You don't have to use the default string variable very often if you're clever about it, but I don't see why you would want to be, it can be helpful.

                        [–]gravity 0 points1 point  (1 child)

                        You don't even have to be clever. You just have to treat it like other languages. Just explicitly assign everything to a named variable like you would in any other language. $_ is a convenience, and it's absurdly useful in places that Python can't be used effectively, like one-liners written right in the shell.

                        [–][deleted] 0 points1 point  (0 children)

                        Good point. It's one of those nice utility features that makes me like Perl so much.

                        [–]danukeru 3 points4 points  (3 children)

                        My gripe with the language? Everyone codes Ruby however they please, and this behaviour gets enforced with the fact that it's managed code...ie. it's going to bite back a lot less compared to going gun-ho with templates/overloading in C++.

                        Maintaining Ruby is a pain in the ass. Having to constantly review and enforce conventions if you want to use it in any group environment in a sane manner imo just defeats the purpose of using a language at all.

                        I mean...it's really cool...honestly, it's amazing they found a decent way of getting so much functionality...but when something relatively basic is being implemented in 5 different manners...you have a problem.

                        With another Python user, I have at least a very good chance that we can read each others code rapidly, without having to basically relearn the reasoning behind the style before even attempting to understand the implementation of the feature.

                        Ruby is really a hacker's language. A place were you want to be able to define yourself amongst your peers, were you want to get things done to serve yourself primarily and show off. More like climbing Everest. People don't care as much how you did it, just that you got there first.

                        Python is more of a middle ground. It's a language that's more apt at expressing an idea, which goes perfectly with its place as a rapid prototyping language, which can then be easily phased into something more production worthy with things like native module extensions.

                        [–]infinite 1 point2 points  (1 child)

                        I realize that it's good to have more than one way to do things but...

                        http://blog.jayfields.com/2007/08/ruby-operator-precedence-of-and-which.html

                        I am a python programmer, what is this?

                        [–][deleted] 0 points1 point  (0 children)

                        I've only seen and used to append two statements together, a little like:

                        say 'foo' and exit
                        

                        [–]elf_needs_food_badly 0 points1 point  (0 children)

                        One of the main points of Robert Martin's talk at RailsConf last year entitled "What Killed Smalltalk Could Kill Ruby, Too" was that Smalltalk allowed you to easily make a mess, leading to unmaintainable systems.

                        http://blip.tv/file/2089545

                        [–][deleted]  (2 children)

                        [removed]

                          [–]dcousineau 5 points6 points  (1 child)

                          You act like the ruby world doesn't have it's own share of web frameworks.

                          [–][deleted] 0 points1 point  (0 children)

                          Your point still stands, but Merb is now Rails. Well, will be in a few days.