Private visibility should be removed from Ruby 2

On Oct 3, 2006, at 11:07 AM, Tomasz W. wrote:

Then could you explain, whether:

These are probably questions better asked of irb, but I’ll try…

a = Name.new(‘foo’, ‘bar’)
a.instance_eval { a.sortable } # correct or not ?

I have no idea what “correct” means here, but I can tell you that
Ruby allows protected methods to be called function-style for the
current object and method style for another object of the same class:

a.instance_eval { a.sortable } # correct or not ?
NoMethodError: protected method `sortable’ called for #<struct Name
first=“foo”, last=“bar”>
from (irb):20
from (irb):20
from :0

a.instance_eval { sortable }
=> [“bar”, “foo”]

a.instance_eval { self.sortable }
NoMethodError: protected method `sortable’ called for #<struct Name
first=“foo”, last=“bar”>
from (irb):23
from (irb):23
from :0

You do seem to be able to use either style in method definitions for
the current object though:

class Name < Struct.new(:first, :last)
def full
“#{first} #{last}”
end

?> def last_first

"#{last}, #{first}"

end

?> def sortable

[last, first]

end
protected :sortable

?> def <=>(other)

self.sortable <=> other.sortable

end
end
=> nil

Name.new(“James”, “Gray”) <=> Name.new(“Dana”, “Gray”)
=> 1

Name.instance_eval { a.sortable } # correct or not ?

Well, it blows up and I consider that “correct”, yes. You are inside
the Name class here, not an instance of that class.

James Edward G. II

On 10/3/06, James Edward G. II [email protected] wrote:

On Oct 3, 2006, at 11:07 AM, Tomasz W. wrote:

a.instance_eval { self.sortable }
NoMethodError: protected method `sortable’ called for #<struct Name
first=“foo”, last=“bar”>
from (irb):23
from (irb):23
from :0

So why doesn’t a.instance_eval { self.sortable } work ?
I stand by my statement that pretty much nobody understands “protected”.

Tomasz W. wrote:

Now imagine a C++ object. It is not a black box at all. It has
multiple interfaces, and everything that communicates with it must
know exactly what at least some of them are. Like with Smalltalk
object, it receives messages. But the sender addresses messages to
different interfaces, not to the object itself. So one message “bar”
can be sent to “Foo in public context”, while other message “bar” can
be sent to “Bar in private context”. It is pretty meaningless to talk
about “sending messages to objects” in C++, as the receiver is not an
object (but one of its many interfaces) and the message must know
exactly what interface it is targetting.

Indeed, C++ doesn’t purport to have messages or methods. The C++
specification on purpose use the term “member functions”. The “message”
does not need to know what interface it is targetting - the caller
needs to know that it is satisfying all the restrictions that the
function signature and class of the object.

However to call it different interfaces is misleading too - it is a
single interface, but the interface specifies pre-conditions that must
be satisfied before you are allowed to use it. . Private/protected is
only part of that - the types of the arguments are also part of it. Yet
I assume you wouldn’t claim it has multiple arguments because it acts
differently if you try to pass a string instead of an integer to the
same function? Even Ruby has pre-conditions that must be met before a
method call can be successfully completed.

One difference is that in C++ a larger set of those pre-conditions are
enforced by the compiler as part of type checking up front, whereas in
Ruby more is left up to the developer, or will result in failures
during testing instead. The other is that C++ mentality is very much to
use the compiler to enforce design: Make compilation fail if the client
of a piece of code tries to do something he/she shouldn’t, such as
calling member functions that are meant for internal use only. A lot of
work on C++ meta-programming focus on adding more restrictions to push
failures forward to compile time to limit the problem space that needs
to be covered for testing, and to limit needs for runtime checks.

I think it’s unfair to say that this means C++ objects are not black
box. If anything, they are more so: The typical design aim is to narrow
the interface as much as possible. private/public/protected specifiers
are tools to achieve that, exactly in order to ensure that not only
attributes, but also member functions not meant for public use gets
hidden from clients. Hiding the interface doesn’t achieve anything
other than push the verification that the compiler does in a language
like C++ into the test suite, so if that is what you mean by black box
I see it as a bad thing.

Vidar

On Oct 3, 2006, at 11:38 AM, Tomasz W. wrote:

I stand by my statement that pretty much nobody understands
“protected”.

Because that’s a method call, not a function-style call.

James Edward G. II

On 10/3/06, James Edward G. II [email protected] wrote:

On Oct 3, 2006, at 11:38 AM, Tomasz W. wrote:

On 10/3/06, James Edward G. II [email protected]
So why doesn’t a.instance_eval { self.sortable } work ?
I stand by my statement that pretty much nobody understands
“protected”.

Because that’s a method call, not a function-style call.

So what’s the final rule ?

Is it something like:
protected method can be called if “implicit self” is used
or if self is the same or sub class of class in which method
was defined, and only from a method definition by `def’"

Is it correct ?
Why does it work this way (especially the `def only’ part) ?

On 10/3/06, Trans [email protected] wrote:

|Having a single well-defined interface was a big win for Smalltalk.

as an error. If you want to remove “private” from Ruby2, I expect
associated. How many Rubyists would know that saying “private function”
is redundant?

Lots of folks I guess, if you define a function of a method called
without
an explicit receiver.
As a matter of fact I disagree with this definition as there are just no
functions in Ruby.
One might define a “function call” as an implicit method call, for which
there does not seem to be any reason.
There are method calls with an explicit receiver, and there are method
calls
without.
The later only are allowed for private methods, that is how I found it
defined in Pixcacke, does everyone agree on this?

For what Matz’s concern is about avoiding to define #puts etc. on Object
level visibly, I would prefer a different approach.

public and protected modes do not change. private mode changes in so far
that private methods can be called from within the instance of the class
of
it’s definition, even with an explicit receiver, that can be the
Singlteon
class BTW.

#puts and friends are looked after when all other name resolutions fail,
a
straight forward idea would be to have a toplevel object of class Void
(no
methods) with Kernel mixed in or a specific class TopLevel or BuiltIns.
This
would have the (ugly?) sideeffect that there would be objects in Ruby
that
are not Object.
After some thoughts I believe that this is exactly what Matz wanted to
model, I feel that his original approach was not the best one, because
of
all these subtle side effects, that probably were not easily
predicatable.

Honestly one the syntax features that UI alwasy found out of place was

I’m curious why the public/private nomenclature was chosen over
‘method/function’ and why#funcall is being suggested now (moving away
from that choice?).

Me too as I fail to see any needs for functions as long as we accept
truely
private methods.
Truely private methods (as right now) are an important modelling tool
for
data hiding and I would truely hate to miss this tool in Ruby.

end
That one I like very much, what would you suggest as call syntax? a.foo
or
a.@foo, I simply hate the later.

T.

Cheers
Robert


Deux choses sont infinies : l’univers et la bêtise humaine ; en ce qui
concerne l’univers, je n’en ai pas acquis la certitude absolue.

  • Albert Einstein

Hi,

In message “Re: Private visibility should be removed from Ruby 2 [was:
Caveats with #method_missing]”
on Tue, 3 Oct 2006 21:20:21 +0900, “Tomasz W.”
[email protected] writes:

|> |* remove “protected” visibility completely
|
|Nobody uses “protected” (0 uses in standard library - can anybody find some
|code that actually uses it ?). Nobody understands it.

“protected” is like “friend” in C++. Currently a few programs use it,
but it does not mean it isn’t useful.

|How was it supposed to work ? Am I the only one with a problem here ?

This is a bug. I should have checked protected visibility based on
real “self” within instance_eval. It will be fixed soon.

|And getting rid of it make metaprogramming easier.
|One example: I have no idea how to make delegation by method_missing
|that behaves correctly with public, protected and private methods.
|Delegation would either have to ignore visibility (what is wrong -
|see preexplanation again) or fail to forward some methods.

Removing visibility makes the issue much easier, I admit. But you may
agree that visibility has its own merit on the other hand. It’s just
a trade off. It might mean the demand for the delegation along with
the original visibility.

I will be back with your other points later.

						matz.