1. 15
  1.  

  2. 7

    These are definitely things that a type system can keep from happening.

    1. 1

      Just because I’m ignorant - how would a type system keep one from accidentally choosing = rather than ==?

      1. 12

        In Rust, for example, assignments always evaluate to the unit type (), so if you use = in a place where a boolean is expected, you will get a type error.

        1. 1

          I love Rust, but I consistently hear “It’s not stable enough” when talking about using it in any kind of commercial setting. I know companies are using it, and I’m NOT saying they’re RIGHT to say this, but it’s what I’m hearing.

          1. 3

            It’s just an example; any language with a static type system that has had more than half an hour’s worth of thought put into it will work the same way.

        2. 5

          You don’t even need a type system for that. Lua will flag that as an error because = is a statement, while == is an expression. (Of course; the distinction between statements and expressions is not the best way to solve the problem; I’d much rather see it solved by replacing assignment with let and replacing == with pattern matching, but what can you do.)

          1. 3

            but what can you do.

            Write a new compiler! :)

          2. 3

            By making something an immutable type? Even C can catch this if you do 1 = foo rather than 1 == foo.

            1. 2

              simply avoiding coercion of non-booleans to true/false in a boolean context would do it. likewise, not silently discarding extra arguments to a function would have helped with the second one. neither of those things would really affect ruby’s nature; the existing type system would be more than capable of accommodating them.

          3. 4

            In addition to Yoda expressions, you should also .freeze everything in sight.

            Only remove the .freeze if your unit tests prove you need to mutate them.

            Sound radical? No, it’s not. For example ruby strings are now frozen by default.

            1. 4

              At that point wouldn’t you be better off switching to a language where widespread immutability is more idiomatic, rather than trying to coerce ruby into such a style?

              1. 2

                Sort of like my C / C++ / D style.

                Everything I do is const / immutable / pure / single assignment until I find a reason not to.

                I would prefer my languages to have that sane default, but then provide a keyword to mark things as mutable when it is more convenient.

                So far I haven’t found a pure functional language that has given me what I have needed from the various other languages I use….

                Clojure is looking very interesting… but I really wish it would divorce itself from the jvm.

                1. 1

                  I almost exclusively use Scala these days. var/val are equally defaultlike. If you’ve got the time to go into it, what’s keeping you off Rust or OCaml?

                  1. 2

                    Scala, Rust, OCAML.

                    I find the jvm environment very constraining/irritating, but if I was forced to it I’d probably go for Clojure since I really like the way Rich Hickey thinks.

                    I tried Ocaml, oh, maybe a decade back and it simply didn’t make the grade back then. maybe it has matured and I should have another look at it.

                    I have taken a poke at Rust and D recently, there are some things I really like about Rust, and other things I really like about D.

                    Currently I’m in favour of D.

                2. 1

                  Statements like this assume that you ALWAYS have a choice of which language to use for a given task. There are all kinds of real world constraints, very easily to dismiss from our comfy armchair, which can make doing so not a valid choice.

                  1. 1

                    A “real world constraint” that means you’re stuck on Ruby? No, I don’t buy it. Using Ruby at all implies a reasonably modern setup and a use case where runtime performance isn’t critical, at which point FFIing into another language is always going to be possible..

                    1. 1

                      Then I envy you for the parallel universe you live in. Most of us have a scripting language that’s pretty much mandated by our place of work.

                      My current employer is a Python/C++ shop. The last one was a Ruby shop.

                      Nobody chooses anything else because everyone knows the language of choice, and the entire pre-existing codebase is written in that language.

                      Not everyone works for grain fed native cultured lovingly hand crafted startups where people can express their cultural otherness by using any tool they like any time they like without a care as to its repercussions on maintainability.

                      1. 1

                        Heh, I work at a big bank. I’m not saying everyone has a free choice of language (I don’t get to use Idris, much as I’d like to), but I can’t believe Ruby would ever be the only option (if only because you’d need a higher-performance alternative for critical pieces).

                        1. 1

                          With all due respect, you need to get out more :) Two jobs ago I worked at a Ruby on Rails shop. We ran a retail site with many thousands of simultaneous users, and the RoR stack code was absolutely not the bottleneck.

                          There is such a thing as “fast enough”.

                          1. 1

                            RoR is fast enough 99% of the time, sure, but IME it’s a very rare application that doesn’t have one piece where it ends up needing to FFI into something a bit faster. (Which may well be via an existing gem wrapper, but if you’re willing to use such a thing you need to be able to maintain it, which means you need the skills to debug C++ or whatever it’s written in, at which point you should be willing to write similar code yourself (I mean you’d still need a business justification for doing it, but if it’s going to reduce the defect rate and result in more maintainable code that should be an adequate justification)).

                            1. 1

                              Again, I think you’re projecting. There are very stable canned solutions for the niche problems you’re referring to (handling the low level HA interface to a web server like Apache or nginx) like Passenger or Unicorn which require exactly zero C/C++ knowledge to be used.

                              Your use case is not everyone’s use case.

              2. 3

                I don’t want to create a language war, but it’s precisely why I love python. To a great extend, it rarely surprise me.

                1. 3

                  Ok, while we’re not starting a language war…. :-)

                  …try D some time.

                  The really interesting thing is the notion of “generic all the time”.

                  Ye Olde C++ programmers tend to think “Oooooo, templates are scary, for wizards only”.

                  But compile time function evaluation makes generic code simple and straight forward instead of deep magic.

                  Thus you have (nearly) all the flexibility of a duck typed language, but anything that is fubar at compile time is seen to be.

                  1. 2

                    I agree. While there are certainly some syntactic pits to fall into in Python, they tend to be less subtle than this.

                    This lack of ‘cleverness’ in its syntax is one of the many things I have come to love about Python.

                  2. 3

                    It returns the insult count for the given person – a number! Next Ruby interpreted the numerical value my block returned, 432, 892 or 321, as the sort order indicator. That’s right: Ruby will accept any positive value from the sort order block, not just 1, and consider that to mean the two objects are in descending order. Similarly, it will take any negative value to mean the values are in ascending order.

                    Given two integers, it’s fairly convenient just to subtract the two for comparison. Trivial example:

                    [1,2,3,4,5].max { |l,r| l - r }
                    

                    This is more helpful in Java than in Ruby, but the spirit applies: 0, positive, negative. https://en.wikipedia.org/wiki/Sign_function

                    1. 3

                      I love this style of article and would love to see more like it, especially with other languages and environments.

                      1. 2

                        Yes, = and == are not the same operator, and max and max_by are not the same function. I feel like James Mickens in The Night Watch, “Look, I get it. Multiplication is not addition. This has been known for years.”

                        And with all the Haskell users here, how has no one flagged this yet?

                        I could even use a language like Haskell where the type system is so powerful that merely by allowing my code to run with no errors, the compiler has mathematically proven my code is correct.

                        Good type systems certainly aid in correctness, but they aren’t magic.

                        1. 5

                          I think the author was just joking about Haskell. The next sentence is

                          (If this could only be true!)