1. 52
  1.  

  2. 25

    The inevitable fate of languages with no definition of done: an ever-decreasing bar to language additions.

    1. 17

      I like that the most recent C standard added no new features.

      1. 2

        It was only bugfixes, clarifications to language and bringing the de jure wording for some features into line with the de facto meanings?

        1. 5

          Basically. C18 is a “bugfix release” for C11. C2x isn’t supposed to add too much either, mostly decimal arithmetic, IIRC.

      2. 5

        I would have so much respect for a language designer who just said “that’s it, it’s done.”

        1. 7

          Doesn’t this describe lua?

          1. 6

            Or even more, Standard ML, which comes with a spec and not a reference implementation.

        2. 4

          Isn’t one of Ruby’s goals “developer happiness”?

          It’s hard to go from this to a language spec, and well at some point you have to handle the conflicts between developers who enjoy a simple language, versus those who like to ad[oa]pt every shiny features of their week-end programming tools.

          IMHO, adding more stuff to Ruby will only make it worse, unless the core team start taking cues from Rust’s development model.

          1. 16

            you have to handle the conflicts between developers who enjoy a simple language

            Developers who enjoy a simple language would have left Ruby long ago.

            1. 4

              Ruby was never a simple language and Rails started using every niche behaviour there was. It was only capable of writing good inner DSLs to hide this.

              1. 3

                Which is why - despite being a professional Rubyist for years - I reach for a Lisp these days when coding.

                1. 1

                  I think a lot did, and Ruby (MRI) is not getting simpler.

                  1. 5

                    Also, a lot of awesome people joined. We overemphasize leavers, because they are usually already at the top of the community.

                    Ruby is also larger than ever, even if its growth is somewhat on a plateau.

                2. 13

                  unless the core team start taking cues from Rust’s development model

                  I think Rust is on a similar feature death march, it just hasn’t been going on for long enough to make it readily apparent.

                  1. 1

                    Isn’t one of Ruby’s goals “developer happiness”?

                    I’ve most often heard this expressed as “principle of least surprise”.

                    Kind of tough to keep to that and yet evolve the language in a meaningful way. See my response to @soc for my weak theory that major changes should just get a whole new language name.

                    1. 6

                      Note that Matz has himself said that the measure for surprise is his surprise.

                      1. 3

                        That makes a lot of sense and explains a bunch, in that it makes the decisions he made to evolve the language more cogent as his own personal sensibilities around language design evolved.

                        While there’s no principle of least surprise corollary per se, I think you can certainly make comparisons to Guido with Python. He went to work at Dropbox and Google, and worked on GINORMOUS code bases where type hinting is a huge help, and was also on a type theory kick, so he evolved the language in that direction despite the pitchforks and torches carried by large chunks of the community.

                  2. 4

                    So I’m unsure as to whether I’d go quite as far as you do in this statement but I’d actually been thinking that this reminded me a lot of all the controversy in the Python community around some of the more tectonic language changes like the addition of type hinting in Python 3.

                    I’m almost to the point where I feel like language designers who want to make tectonic changes should be honest with themselves and their audience and just change the language’s name.

                    For instance, well written Python 2 and well written, idiomatic, heavily type hinted Python 3 feel very different to me and to many others fans. This isn’t necessarily a bad thing, but maybe we could suck some of the pointless “Who moved my cheese?” controversy out of the conversation and focus on what’s different and maybe better or worse instead.

                    Ruby’s evolution has certainly been contentious - the syntactic sugar borrowed from Perl is part of what attracted many of us to the language initially (Yes I was a Perl guy in the 90s. So were many of us. No shame :) but when Matz realized how problematic it could be in the modern context and moved away from it, a whole lot of code broke and there was a whole lot of unhappy, even if ultimately many people agreed it was a good idea.

                    1. 2

                      I think I’d regard this ongoing feature creep in language as just as sleazy as those online services that keep adjusting their privacy agreement after you have signed up to collect more and more data on you.

                      In the end, if language designers were honest they should probably give their “new” language a new name. I assume that the “immediate adoption” of reusing the name of an existing language is too enticing though.

                      1. 4

                        These languages are open source while say Github/Google/Facebook aren’t. The whole point of open source is that users have control.

                        If enough people really care, they can fork it, and forks matter (XEmacs, etc.).

                        I’m one of those people who doesn’t really see the value in Python 3. But it actually provides the perfect opportunity for someone to fork Python 2, because it’s stable, and it has a stable set of libraries.

                        I haven’t seen very serious efforts to do this, which indicates to me that the community doesn’t care enough. (A few people have tried, to their credit, but overall the message is clear.) Lots of people will complain about things but they don’t want to put in the effort to fix them or even maintain the status quo.

                        1. 2

                          I think I’d regard this ongoing feature creep in language as just as sleazy as those online services that keep adjusting their privacy agreement after you have signed up to collect more and more data on you.

                          The way you phrased this shines a light on an interesting facet of this whole discussion: The contract between a language’s designer(s) and its user community.

                          From the designers perspective, this is their bat and ball, but it seems like at least some users don’t see it that way.

                          1. 2

                            I haven’t seen very serious efforts to do this, which indicates to me that the community doesn’t care enough. (A few people have tried, to their credit, but overall the message is clear.) Lots of people will complain about things but they don’t want to put in the effort to fix them or even maintain the status quo.

                            Trick being you need to fork not just the language but the ecosystem. HUGE parts of the Python ecosystem have pointedly abandoned 2 and made incompatible changes, so everything your fork eats is frozen in time. Pretty high price to pay unless, as you say, you really, REALLY care.

                      2. 22

                        There’s some irony here in this complaint coming from bbatsov, the author of Rubocop, where the constant, never-ending creep of additional on-by-default cops enforcing ever-more-specific and squirely tastes has forced basically every project I know of to throw up their hands and just refuse to upgrade the damned thing at a certain point out of frustration with Every. Single. Upgrade. introducing some new ever-more-rigid requirements on everyone that you then have to go and add to the endlessly growing blacklist of cops.

                        And this happens, of course, because there’s no definition of “Done” and the broader community is made up of many people with many tastes and use cases proposing many changes, which through some alchemical combination of consensus and maintainers’ tastes, make it into the project. It’s really the exact same phenomenon.

                        There’s no silver bullet, I guess, but this is all a bit “physician, heal thyself”

                        1. 12

                          I’m also confused by this. Additionally, Bozhidar should know that the “three people complaining” are not three random people, but for example Eric Wong (author of Unicorn) and nobu, who is part of the MRI team after all.

                          So, what does this post sum up to? 4 things that didn’t happen and a feature he doesn’t like and the personal request for Matz to chill out.

                          1. 8

                            Trying to satisfy Rubocop is the ultimate in automated code golf. The default ABC and method line count metrics was absolutely insane last time I used it.

                            1. 4

                              FYI - https://github.com/rubocop-hq/rubocop/pull/7184 :-)

                              I’m well aware of the issue you mention (and it will be resolved before 1.0 is released), but you’re really comparing apples to oranges here.

                            2. 10

                              He adds a feature to master, gets feedback on it and reverts as necessary. I can see advantages to this approach: everyone focuses on the specific implementation and its trade offs, as opposed to an RFC with no code behind it.

                              1. 3

                                My main concern is the lack of vision, not the exact development approach. As Matz admitted himself - some things were added with no real consideration how they fit into the broader picture, and that worries me the most.

                              2. 7

                                Parameter forwarding is a nice convenience that doesn’t suffer from any of the problems of |>: mixing positional args with kwargs and a block means forwarding arguments is kind of annoying in Ruby. I welcome ...

                                As my Ruby has tended more toward a functional style I’ve been doing this sort of thing a lot more.

                                1. 5

                                  These retrospectives on evolving and ageing languages make good case studies. My personal takeaway: if you could write a piece of syntax as easily as any other library, all of these syntax tweaks and additions would become complete non-issues. It would eliminate reams and reams of bikeshedding in the issue tracker if you could just do import syntax/flipflop.

                                  1. 3

                                    Every Ruby project potentially having slightly different syntax sounds like a nightmare to me.

                                    1. 4

                                      Not trying to be glib, but… DSLs?

                                      1. 2

                                        DSL’s built on Ruby all follow the same syntax though.

                                        I suppose there might be a few out there where Ruby is outright parsing some other text, but those are mercifully rare.

                                        1. 2

                                          But a DSL has a different syntax to vanilla Ruby, because otherwise it would be a regular library, not a DSL.

                                          Is syntax sugar like a new sigil or infix operator (which is what most of these are) really that different to a DSL? Fundamentally, I mean, not just in that one of them uses tokens and the other uses characters. You have to learn something new the first time you encounter a new DSL exactly the same as you would for a new character syntax. Having been knee-deep in this kind of stuff for a few months now, I’m seeing less and less of a distinction.

                                          1. 6

                                            There aren’t any real Ruby DSLs. Ruby programmers just oddly refer to class methods called at the top level without parentheses as “DSLs” (or, more rarely, instance methods called without parentheses in what other languages would call a “builder pattern”).

                                            Ruby doesn’t support macros or other syntax-level features that would enable an actual DSL.

                                            1. 2

                                              I know, they’re technically only eDSLs, but my point remains. All syntax changes are the same. They could have added real DSLs (edit: you know, “just add this massive feature” :) and never had to decide between @1 and _1.

                                              1. 1

                                                They’re DSLs in the sense that any library API is a DSL, and in this respect I think Ruby does DSLs a lot better than other languages with “real” DSLs. APIs can be (almost) as expressive as real DSLs and they’re still using normal language syntax and semantics. Lisp is definitely more expressive and it’s still technically using the same syntax, but the semantics can vary wildly.

                                        2. 2

                                          Until you realise that less powerful languages have the same problem - except their abstractions aren’t expressed in a clear DSL courtesy Ruby or Lisp metaprogramming, they’re splattered throughout the application in AbstractFactoryFactories and FooUtility classes.

                                        3. 2

                                          In Lisp we trust! ;-)

                                        4. 5

                                          Interesting. I’m using Ruby since ages, starting with 1.8 (with some old software even using Ruby 1.6)… And I’ve never used RubyOnRails much. I like Ruby as one of the most readable programming languages. However, over time more and more obscure operators are added that are not understandable by looking at them in itself. I don’t like this development, but it isn’t at all a new one. Back when 1.9 was introduced, they added this -> operator. In my opinion, this was a first design mistake; until the current day, I fail to see how this should resemble a λ or even a Λ it is supposed to resemble. I stick to using the lambda method. Likewise, the &:symbol syntax is plain ugly. |> looks like a syntax error, and ... conflicts in its meaning with the expected one (variadic argument list). Appearently this list is only about to get longer and longer.

                                          Please stop adding operators to Ruby. It makes the language unreadable.

                                          1. 8

                                            Back when 1.9 was introduced, they added this -> operator. In my opinion, this was a first design mistake; until the current day, I fail to see how this should resemble a λ or even a Λ it is supposed to resemble.

                                            is a pretty widespread function notation in math papers, ie writing the square function as x ↦ x². This is usually done when we need to emphasize that functions are mappings between sets, or when distinguishing functions from sets of functions.

                                            1. 2

                                              … conflicts in its meaning with the expected one (variadic argument list).

                                              I don’t understand, isn’t that exactly what it is?

                                              1. 3

                                                No, Ruby has *args for a variadic argument list. The ... syntax only provides a way to forward arguments. It replaces this idiom:

                                                def foo(*args)
                                                  bar(*args)
                                                end
                                                

                                                Or, in case a block should be forwarded as well, this one:

                                                def foo(*args, &block)
                                                  bar(*args, &block)
                                                end
                                                

                                                This is needed rare enough that I don’t think it warrants its own syntax feature.

                                                1. 2

                                                  This is most likely driven by the changes to keyword arguments; I believe they will likely no longer be included in *args once they become a first-class feature rather than syntax sugar for a Hash.

                                            2. 4

                                              The biggest problem that ruby has is Elixir.

                                              1. 0

                                                This reads like a rant, tag suggested.

                                                Regarding the pipe-line operator, that’s exactly how it works in Elm, and it’s quite useful there.

                                                1. 3

                                                  I don’t think so… I’m unfamiliar with Elm, but based on this article it appears that Elm’s pipeline works similarly to Haskell’s, no?

                                                  # given
                                                  foo "bar"
                                                    |> baz
                                                    |> quux
                                                  
                                                  # Ruby's pipeline is equivalent to
                                                  foo("bar").baz.quux
                                                  
                                                  # Elm and Haskell's work more like
                                                  quux(baz(foo("bar")))