[ruby-core:95882] Re: [Ruby master Feature#16276] For consideration: "private do...end" / "protected do...end"
From:
Martin J. Dürst <duerst@...>
Date:
2019-11-19 04:40:04 UTC
List:
ruby-core #95882
I thought this comment would show up at https://bugs.ruby-lang.org/issues/16276, and wanted to reply there, but it didn't show up there, so I'm replying directly by mail. On 2019/11/19 09:59, ahodgkin@rowing.org.uk wrote: > Issue #16276 has been updated by adh1003 (Andrew Hodgkinson). > > > mame (Yusuke Endoh) wrote: >> adh1003 (Andrew Hodgkinson) wrote: >>> shyouhei (Shyouhei Urabe) wrote: >>> >>>> I can think of other cursed usages of private taking a block. >>> >>> Then it is fortunate, is it not, that this is _not what I am proposing_. >> >> No, not fair enough. It is what you are proposing, even if you didn't intend. We need to care about all the possibilities as far as we can. That's the language design. > > That's absurd, since you're claiming I made a proposal "even if I didn't intend" - even though I wrote very clearly what I meant, somehow I didn't mean it? I intended precisely what I wrote, which *does not* suggest use of actual blocks. In your proposal, at some point you say "support a block-like syntax", but at some other point, you say "strictly to the confines of the block alone", "below the new block", and so on. So you yourself may not have wanted to suggest the use of actual blocks, but it's easy to read your proposal that way. Also, most Ruby programmers will look at this and see a block, and talk about it as a block, and so on. It would be quite difficult to make sure everybody understands that a do-end after the keyword 'private' is NOT a block, but just something block-like. > Anyway, this is clearly not going to happen so we'll just stick with the super-awkward "private_class_method" hackery and so forth. How disappointing. Such is life. Reasonable indenting has served me well for over 10 years, but if you want to use some 'hackery', that's of course your choice. > ---------------------------------------- > Feature #16276: For consideration: "private do...end" / "protected do...end" > https://bugs.ruby-lang.org/issues/16276#change-82717 > > * 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 `:-)` > Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe> <http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>