Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I don't programme much any more but the whole beauty of Ruby that it pretty much heavily relies on #respond_to? / duck typing and thus you don't rely on types or class checking at all.




Most ruby code isn't written like that - it's written like most static languages, where objects conform to interfaces / traits / type classes / pick your poison. The community is shifting towards explicitly specifying and statically checking types now. rbs and sorbet are a testament to this.

I wouldn't say it's really a beauty of the language, it may have been the original design intent but time has shown what's actually maintainable.


I don’t think the existence of a library to do something is evidence of the community shifting. For me the complete absence of types from any Ruby I see IRL or in examples from conference talks, readmes etc is evidence that the community is uninterested despite tons of effort from big players.

I think there's some real sample bias in that definition of "the community" though, because people who are passionate Ruby programmers giving conference talks, running meetups, etc are often a distinctly different group than the regular-old programmers making business software go 'round every day. The big players writing tools for bringing various flavors of type safety into Ruby are doing it because they're experiencing the pain of having lots of programmers working on large, complex software over years-long periods with the tools that Ruby gives you out of the box. They often employ some of those community fixtures, but thats not the majority of an engineering organization.

The reality is that there certainly are enthusiast programmers who can thrive with the lightweight elegance of stock Ruby, but most people writing code professionally aren't enthusiast programmers under ideal conditions. Everything is always a little more distracted, a little less well-defined, and a little more coupled to legacy than anyone would want. And those are the conditions where I want my tools working as hard as possible, automatically, for me / my teams.


Using #respond_to? is normally a code smell. The point of duck typing is exactly that it allows you to avoid checking the type of a class. As long as the object responds to the correct messages, the type does not matter.

#respond_to? is fine, it's really more #is_a? that is a code smell, in my opinion. As long as you're dispatching based on #respond_to? (i.e. "does this respond to each") by calling the method you're checking, when it does respond, you're fine as far as duck typing goes. It's when you check #is_a? and then dispatch based on type where things get weird.

An example I always used to use was something like a method that could take a single item or a collection:

    def unpicky(something)
      if something.respond_to?(:each)
        # unpack using each or recurse to something.each do |item| unpicky(item) end
      else
        # main body
      end
    end

Structural typing like this is completely compatible with the concept of duck typing. Indeed, it's basically doing static checking of duck typing.

I don't think you're really losing the ability to check if an object responds to a message ie a_car.respond_to?(:color) just because theres type annotations. And I assume the type checker doesnt yell if you do a_car.color after that -- or if it does there's surely an equivalent to Typescript's `any` to accomplish it.

And T-Ruby apparently provides interfaces to avoid needing to do this at all (assuming both sides are written in T-Ruby I assume) https://type-ruby.github.io/docs/learn/interfaces/defining-i...

...which is awesome!

As for authoring classes, respond_to_missing?/method_missing should be rare, usually in a situation where its the only way to accomplish something. There's never been a reason to write something like:

    class Car
        def respond_to_missing?(name, priv)
            [:color, :color=].include?(name)
        end
        def method_missing(name, *args, &block)
            if name == :color
                @color
            elsif name == :color=
                @color = args.first
            end
        end
    end
Instead of

    class Car
        def color; @color; end
        def color=(value); @color = value; end
    end
Or, more idiomatically

    class Car
        attr_accessor :color
    end
And for that last case, T-Ruby apparently covers it with:

    class Car
        attr_accessor :color: String
    end



Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: