From: ahodgkin@... Date: 2019-10-29T20:38:56+00:00 Subject: [ruby-core:95582] [Ruby master Feature#16276] For consideration: "private do...end" / "protected do...end" Issue #16276 has been updated by adh1003 (Andrew Hodgkinson). shevegen (Robert A. Heiler) wrote: > > As noted in the pseudocode above, we can clean up some of the issues around > > the special syntax needed for "private constants", too. > > I have no problem either way but I think "constants" is a bit of a misnomer > in general. The ruby philosophy here is more that ruby allows you to change > it if you want to. Agree with all you said and appreciate the detailed feedback - but on this, and in many ways on the use of `send`, those are workarounds for "I really know what I'm doing". Private methods are not normally callable by conventional syntax, and constants pretty much are constants; attempts to redefine them raise warnings, so although it's possible it is, again, inadvisable and private scope constants _are_ a thing (and are useful). The reason for public/protected/private is not just about what "can be done". It's about the contract you're drawing within your class or module, to which clients of that class or module must adhere. Public things are for anyone; protected things for subclasses; private things are implementation. This is vital - no mere decoration - it goes to the very core of OOP and software engineering. Calling `send`� to hack into a private method means the caller is breaking the contract with the target entity and risks breaking at any time, since that entity is freely at liberty to change anything in its private implementation at any time. duerst (Martin D�rst) wrote: > > class Foo > > def bla > > end > > private > > def hop > > end > > end > > This simply is sloppy coding [...left-indent "private"...] Coding style wars wage often. Some of it is functional and objective, but much of it is aesthetic and subjective. The complaint about the coding style does not, I think, really change whether or not we might want to tighten the behaviour of the public/protected/private declarations using block-like syntax in a manner that would be 100% backwards compatible with all existing code (since the no-block syntax would still be there and not be deprecated). shyouhei (Shyouhei Urabe) wrote: > - C++: There are `private`, but no `private {}` > - Java: There are `private`, but no `private {}` > - Scala: There are `private`, but no `private {}` > - Kotlin: There are `private`, but no `private {}` > - Rust: Everything are private by default, there is `pub` instead. But there is no `pub {}` > > Correct me if I'm wrong. But it seems the idea of "private with a block" isn't seen anywhere. In those languages it's impossible (or extremely difficult, via complex reflection programming) to call a private method as a client of the class, but in Ruby you just use `send` - not that you usually should. In most of those languages it's impossible (or again extremely difficult) to redefine a constant, but in Ruby you can do so easily (`const_defined?`, `remove_const`, `const_set`) - again, not that you should. All of those languages are statically, strongly typed, but Ruby is not. Things like C++ or Java are surely (in general) bad (or at best, difficult) places to look for syntax to copy, since they're generally hopelessly over complicated and require extremely heavy IDE support to make any kind of sense out of a typical code base. Ruby is typically far simpler and clearer; that's part of the reason why it was made in the first place. Ruby is its own language. Just because other languages don't do it, does not mean Ruby would not benefit. And again, this is an _extension_ to the existing syntax, not a replacement. ---------------------------------------- Feature #16276: For consideration: "private do...end" / "protected do...end" https://bugs.ruby-lang.org/issues/16276#change-82370 * Author: adh1003 (Andrew Hodgkinson) * Status: Open * Priority: Normal * Assignee: * Target version: ---------------------------------------- Private or protected declarations in Ruby classes are problematic. The single, standalone `public`, `private` or `protected` statements cause all following methods - *except* "private" class methods, notably - to have that protection level. It is not idiomatic in Ruby to indent method definitions after such declarations, so it becomes at a glance very hard to see what a method's protection level is when just diving into a piece of source code. One must carefully scroll *up* the code searching for a relevant declaration (easily missed, when everything's at the same indentation level) or have an IDE sufficiently advanced to give you that information automatically (and none of the lightweight editors I prefer personally have yet to support this). Forcibly indenting code after declarations helps, but most Ruby developers find this unfamiliar and most auto-formatters/linters will reset it or, at best, complain. Further, the difficulty in defining private *class* methods or constants tells us that perhaps there's more we should do here - but of course, we want to maintain backwards compatibility. On the face of it, I can't see much in the way of allowing the `public`, `private` or `protected` declarations to - *optionally* - support a block-like syntax. ``` class Foo # ...there may be prior old-school public/private/protected declarations... def method_at_whatever_traditional_ruby_protection_level_applies puts "I'm traditional" end private do def some_private_instance_method puts "I'm private" end def self.some_private_class_method puts "I'm also private - principle of least surprise" end NO_NEED_FOR_PRIVATE_CONSTANT_DECLARATIONS_EITHER = "private" end def another_method_at_whatever_traditional_ruby_protection_level_applies puts "I'm also traditional" end end ``` My suggestion here confines all `public do...end`, `protected do...end` or `private do...end` protections strictly to the confines of the block alone. Outside the block - both before and after - traditional Ruby protection semantics apply, allowing one to add new block-based protection-enclosed method declarations inside any existing code base without fear of accidentally changing the protection level of any methods defined below the new block. As noted in the pseudocode above, we can clean up some of the issues around the special syntax needed for "private constants", too. I see a lot of wins in here but I'm aware I may be na�ve - for example, arising unanswered questions include: * Is the use of a block-like syntax making unwarranted assumptions about what the Ruby compiler can do during its various parsing phases? * Does the use of a block-like syntax imply we should support things like Procs too? (I *think* probably not - I see this as just syntax sugar to provide a new feature reusing a familiar idiom but without diving down any other rabbit holes, at least not in the first implementation) I've no idea how one would go about implementing this inside Ruby Core, as I've never tackled that before. If someone is keen to pick up the feature, great! Alternatively, if a rough idea of how it *might* be implemented could be sketched out, then I might be able to have a go at implementation myself and submit a PR - assuming anyone is keen on the idea in the first place `:-)` -- https://bugs.ruby-lang.org/ Unsubscribe: