• empw 6 months ago

    I haven't written any ruby for over a decade and a half, when ruby 2.x was still on the horizon. But I do know the source of "eigenclass". It was first jokingly used in an odd instructional programming book / web comic / experimental art piece by "why the lucky stiff" who was briefly prominent in ruby-land then erased himself from the internet. It's funny that it has now become an established term of art for Ruby people.

    • lloeki 5 months ago

      Sunny Ripert paid a wonderful tribute to _why as a talk at ParisRB 2020.

      https://m.youtube.com/watch?v=njr39cVU7d0

      It was not so much aimed at the "old guard" (those that knew about _why) as the "next generation" (those that never heard of him).

      At some point Sunny asked to raise hands if one knew about _why, maybe half did, tops.

      By the end of the talk the emotion in the room was palpable.

      • Lio 5 months ago

        I still refer to the * operator as “splat” after a presentation I saw him give in London in 2007.

        _why is most definitely gone but not forgotten.

        • riffraff 5 months ago

          I thought splat was actually the "official" usage these days, tho I think some people call it spread

          • byroot 5 months ago

            It is yes [0].

            > You can turn an Array into an argument list with * (or splat) operator

            > You can turn a Hash into keyword arguments with the * (keyword splat) operator:

            It's also named spat across the MRI codebase, e.g. `VM_CALL_ARGS_SPLAT` etc.

            [0] https://docs.ruby-lang.org/en/master/syntax/calling_methods_...

            • Etheryte 5 months ago

              It's called spread in Javascript [0], where the keyword is `...`.

              [0] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...

              • dragonwriter 5 months ago

                splat is the official name in Ruby, spread comes from the similar JS construct (obviously, lots of people using Ruby also use JS, so its natural for terminology from one context to sometimes get applied to similar concepts in the other even where it isn’t official.)

            • nixpulvis 6 months ago

              I remember reading WPGTR in college. Really inspired me to play around and learn the language. I've always kept my printed copy in a safe place.

              • adriand 5 months ago

                I read it after college when I first started working with Rails 1 after I joined a friend’s company. Funny to think that was almost two decades ago. I still remember the quirky art style, although I will admit to preferring a more prosaic book when I learned the language. But it was a fun community and the sense of creativity was really apparent.

              • insane_dreamer 5 months ago

                loved _why’s stuff back when he was still around.

                • KerrAvon 6 months ago

                  _why's influence is indelible.

                • lcnPylGDnU4H9OF 6 months ago

                  > There are at least three ways to define a method in a Ruby singleton class.

                  It's worth noting that two of such ways will, perhaps unintuitively, ignore the `private` keyword.

                    private
                    def self.foo
                      # ...
                    end
                  
                    def x.foo
                      # ...
                    end
                  
                  That will define a public method `:foo` on each of `self`'s and `x`'s singleton classes. If you want the method to be private, either 1) explicitly make the method private using `Class#private` or `Class#private_class_method` or 2) use the `class << self` (or `class << x`) syntax in order for the `private` keyword to work as expected.

                    private_class_method def self.foo
                      # ...
                    end
                  
                    def self.foo
                      # ...
                    end
                    private_class_method :foo # `def` will return a symbol of the defined method name so the above syntax is usually sufficient.
                  
                    def x.foo
                      # ...
                    end
                    x.singleton_class.send :private, :foo # Class#private is a private method(!) so must be called using Object#send.
                  
                    class << x
                    private
                      def foo
                        # ...
                      end
                    end
                  
                  > The eternal question… Why is Ruby like this?

                  Joy! :) I'm pretty sure matz would agree.

                  • dragonwriter 5 months ago

                    > It's worth noting that two of such ways will, perhaps unintuitively, ignore the `private` keyword.

                    No, this explanation is wrong, because there isn't actually a `private` keyword, only the Module#private method [0] which, when called with no arguments, changes the visibility of future methods defined in the target module.

                    Those examples call the `Module#private` method with no arguments in one context changing the visibility of future methods defined in that context, and then use an explicit prefix to define methods in a different context.

                    When you don't forget that `private` is a private instance method on Module and not a keyword, the behavior is much simpler to understand.

                    [0] https://ruby-doc.org/3.4.1/Module.html#method-i-private

                    • lcnPylGDnU4H9OF 5 months ago

                      Thanks for the correction! It can be hard to appreciate how true “everything is an object” is.

                      • dragonwriter 5 months ago

                        That and how, between block arguments and optional parens on method invocation, Ruby allows (and the core exploits this) defining lots of constructs that look like keyword-based syntax as methods.

                  • xutopia 6 months ago

                    I love it when someone dives a bit deeper behind something pretty common for most Ruby devs. It's actually a really elegant pattern that is used and it's everywhere in Ruby.

                    • pansa2 5 months ago

                      > In Ruby, every object that is instantiated is represented internally by basically three things:

                      > * A table of instance values

                      > * A pointer to the class of the object, used for method lookup

                      > * A pointer to a unique class for that instance, called the “singleton class” of the object, also used for method lookup

                      I don't think this is accurate. The source code shows a generic `RObject` [0] contains flags, a pointer to a class (named `klass`), and instance variables. An `RClass` [1] contains flags, `klass`, `super` and a table of methods.

                      In both cases there is only a single pointer to a class that's used for method lookup.

                      -

                      > Ruby will look in the singleton class for the specific user instance first, and will only look for an instance method of the class if there is no matching method in the singleton class.

                      This is true, but it implies that Ruby does two separate lookups. The way it actually works is more elegant.

                      An object's `klass` points to its singleton class, and method lookup happens only on that class and its superclasses. The second lookup implied above happens implicitly, because the class of the object is an ancestor of the singleton class.

                      Specifically, for `class C`, its `klass` points to the singleton class `<< C`, whose ancestors are `<< Object`, `<< BasicObject`, `Class`, `Module`, `Object` and `BasicObject`.

                      IMO Ruby's whole object model, and in particular the design of this inheritance chain, is beautiful and underappreciated.

                      -

                      > I’m not really sure why the Smalltalk solution wasn’t used

                      I think the way Ruby actually works is closer to the Smalltalk approach than the author realizes.

                      -

                      [0] https://github.com/ruby/ruby/blob/71f402c5d50919b0329d04704d...

                      [1] https://github.com/ruby/ruby/blob/71f402c5d50919b0329d04704d...

                      • ryukoposting 5 months ago

                        Having embedded MRI into a variety of side projects over the years, I can confirm your evaluation of Ruby's method lookup procedure is accurate, at least in the context of that legacy, reference implementation of the language. I also agree that Ruby's design is deeply underappreciated.

                      • mrinterweb 6 months ago

                        Don't forget about the Singleton module ("include Singleton"). This one trips me up in terms of what is being referred to as a "singleton". This is more of an singleton class instance where there can only be only one class instance per-class. https://ruby-doc.org/3.4.1/stdlibs/singleton/Singleton.html

                        • Lammy 6 months ago

                          > What we’ve been calling “class methods” are actually instance methods of the metaclass.

                          This also shows up if you ever want to use a Refinement on a “class method”. The thing you must `refine` is the `singleton_class`.

                          Here's a live example from my UUID library where I refine `Time::now` and one of my own utility class' methods to test the time-went-backwards and network-card-changed cases for incrementing the sequence value while generating time-based UUIDs: https://github.com/okeeblow/DistorteD/blob/3e9bbc744479afd3e...

                          • inopinatus 5 months ago

                            Noel recommends def self.foo over class << self, implying that these are syntactic equivalents, but I beg to differ; the former does not update the third implicit context (aka the default definee) whilst the latter does, per yugui’s classic article on the matter https://blog.yugui.jp/entry/846, and this makes more sense to me in common usage.

                            So instead of treating them as syntactic equals when they’re not, I reserve the former as a special case, a clear sign that the following method body was intended to operate in the implicit definition context of its surroundings for some reason.

                            • Alifatisk 6 months ago

                              I have to admit, years back when I learned Ruby I found this syntax to be very bizzare

                                class User
                                  class << self
                                    def create_from_data
                                    end
                                  end
                                end
                              
                              Specifically, this: class << self

                              But when reading about it, it made sense

                              • undefined 5 months ago
                                [deleted]
                                • andrekandre 5 months ago

                                    > In Smalltal, you interact with your code through an code browser that is part of the system.
                                  
                                  small spelling mistake: Smalltal → Smalltalk
                                  • rubyfan 6 months ago

                                    Great read, I’ve written several ruby extensions in c and this write up made total sense.

                                    • undefined 6 months ago
                                      [deleted]
                                      • corytheboyd 6 months ago

                                        Went in expecting a basic how-to about the Singleton module, but this is so much more, you clearly know your shit, and I love deep dives like this!