News for hackers. Stuff that matters.
Re:Java 1.0 Turns 25 by jrochkind1 on Saturday January 23, 2021 @12:47PM (#25884441)
I was thinking of ruby as you write this... it's not quite true that in ruby "referencing a field on any object... is just sugar for a call to the getter/setter."

It's actually true that ruby makes it impossible to directly access fields in objects other than `self` (ie `this`). Seriously, it's not possible ruby takes away the ability to do so, thereby making it not even a choice anymore, you have to create a getter/setter, it's the only option. There is no sugar, there is simply a prohibition on direct access to iVars in other objects, period.

What might make it look like "sugar" is that parentheses method calls are optional in ruby -- `obj.foo` is just another syntax for `obj.foo()` Whether or not it's a getter, any method at all, nothing special for getter/setter here. That's literally the only thing going on here that makes you think there is "sugar", ruby syntax having parentheses be optional in method calls.

And additionally ruby gives you a shortcut "macro" to defining the getter/setter, `attr_accessor :foo` inside a class body just automatically defines the conventional getter and setter for you. You still do need to define them though, again no "sugar".

So ruby actually comes down solidly on the side of "yes, always use getters/setters"... in some ways this is what you are complaining about, people always doing it, right?

But it turns out differently and not annoying anyone, I think, because it was planned for by the language designers in the first place, both by making it mandatory (eliminating it as a point of debate or as something a programmer will spend any time ever considering when implmeenting), and by providing devices to make it convenient.

I think the choice to make parentheses optional in method calls actually goes along with the choice to forbid direct access to fields in other objects; both because there is now no need to syntactically distinguish between the two, and because it makes it less annoying to forbid. It also causes all sorts of other complexity in writing parsers for ruby though...

Re:Java 1.0 Turns 25 by derefr on Sunday January 24, 2021 @11:20AM (#25893187)
I happen to know a bit about Ruby. (A lot more than I know about Java, as it happens.) Let me pick a few nits :)

#instance_variable_get / #instance_variable_set is a thing. The (default) implementations of these methods on Object are just C code that do direct IVar reads/writes. You can thus think of #instance_variable_get and #instance_variable_set as real “field access” in Ruby. It’s just that, unlike most languages, there is sugar† for the getter/setter, and there isn’t any sugar for the “direct” field access.

† (The setter’s sugar is obvious — `a.b=x` is re-written by the lexer into a call `a.send(:"b=", x)`. The getter’s sugar is less obvious — it’s seemingly just a regular method call. But think about why Ruby makes parens optional on arity-0 method calls in the first place. To sweeten getters into something field-access-looking!)

But, well, you might say, #instance_variable_get is just a method, too! I can override it as I want! Really, it’s just another kind of getter/setter — sort of a categorical one.

Well, let’s go one level deeper — you can literally “reach into” the object to take a look at its IVars as it sees them:

    obj.instance_eval{ @foo }
“Objection! #instance_eval can be overridden! DRb proxy-objects do it!”

Well, okay, let’s get creative, and start breaking through the seemingly pure-OOP semantics of Ruby, revealing the more functional-language underpinnings:

    inst_eval_fn = Object.instance_method(:instance_eval)
    inst_eval_fn.bind(obj).call{ @foo }