From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: AS4713 221.184.0.0/13 X-Spam-Status: No, score=-3.9 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED, SPF_HELO_NONE,SPF_PASS shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from neon.ruby-lang.org (neon.ruby-lang.org [221.186.184.75]) by dcvr.yhbt.net (Postfix) with ESMTP id 4C6621F4C0 for ; Tue, 29 Oct 2019 20:39:09 +0000 (UTC) Received: from neon.ruby-lang.org (localhost [IPv6:::1]) by neon.ruby-lang.org (Postfix) with ESMTP id 449E012091D; Wed, 30 Oct 2019 05:38:58 +0900 (JST) Received: from o1678948x4.outbound-mail.sendgrid.net (o1678948x4.outbound-mail.sendgrid.net [167.89.48.4]) by neon.ruby-lang.org (Postfix) with ESMTPS id 35634120922 for ; Wed, 30 Oct 2019 05:38:55 +0900 (JST) Received: by filter0060p3iad2.sendgrid.net with SMTP id filter0060p3iad2-9511-5DB8A360-44 2019-10-29 20:38:56.405559378 +0000 UTC m=+77440.618535900 Received: from herokuapp.com (unknown [34.229.123.158]) by ismtpd0045p1iad2.sendgrid.net (SG) with ESMTP id MmE1X0_gR0yfjDU580UpBw for ; Tue, 29 Oct 2019 20:38:56.251 +0000 (UTC) Date: Tue, 29 Oct 2019 20:38:56 +0000 (UTC) From: ahodgkin@rowing.org.uk Message-ID: References: Mime-Version: 1.0 X-Redmine-MailingListIntegration-Message-Ids: 71175 X-Redmine-Project: ruby-trunk X-Redmine-Issue-Id: 16276 X-Redmine-Issue-Author: adh1003 X-Redmine-Sender: adh1003 X-Mailer: Redmine X-Redmine-Host: bugs.ruby-lang.org X-Redmine-Site: Ruby Issue Tracking System X-Auto-Response-Suppress: All Auto-Submitted: auto-generated X-SG-EID: =?us-ascii?Q?C43Yqc2nKZQxJ=2FCf0+wAnm6F7Sl5KchIsIzDQOCy9K47iodPmjPeGany8Tn5h+?= =?us-ascii?Q?g6kmR3lhDJuU4NV3XkCdcn9fF=2FePg1AVqC6NjDQ?= =?us-ascii?Q?dZoy911BC9OQ+iqWuucWi1=2FD+zwv5=2FL1=2FA3YGR=2F?= =?us-ascii?Q?+fpUstCYPkACQShZNN2FLTVNvSpwIWaJMvmmnWK?= =?us-ascii?Q?B8qlQvoFg14STcw6G8hZi7NQl+BNccZGZDA=3D=3D?= To: ruby-core@ruby-lang.org X-ML-Name: ruby-core X-Mail-Count: 95582 Subject: [ruby-core:95582] [Ruby master Feature#16276] For consideration: "private do...end" / "protected do...end" X-BeenThere: ruby-core@ruby-lang.org X-Mailman-Version: 2.1.15 Precedence: list Reply-To: Ruby developers List-Id: Ruby developers List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Errors-To: ruby-core-bounces@ruby-lang.org Sender: "ruby-core" 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 ar= ound > > the special syntax needed for "private constants", too. > = > I have no problem either way but I think "constants" is a bit of a misnom= er > in general. The ruby philosophy here is more that ruby allows you to chan= ge > 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 convent= ional syntax, and constants pretty much are constants; attempts to redefine= them raise warnings, so although it's possible it is, again, inadvisable a= nd 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 w= hich clients of that class or module must adhere. Public things are for any= one; protected things for subclasses; private things are implementation. Th= is is vital - no mere decoration - it goes to the very core of OOP and soft= ware engineering. Calling `send`=A0 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 i= ts private implementation at any time. duerst (Martin D=FCrst) 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 m= uch 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 t= he behaviour of the public/protected/private declarations using block-like = syntax in a manner that would be 100% backwards compatible with all existin= g code (since the no-block syntax would still be there and not be deprecate= d). 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 t= here 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 ref= lection 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 thos= e languages it's impossible (or again extremely difficult) to redefine a co= nstant, but in Ruby you can do so easily (`const_defined?`, `remove_const`,= `const_set`) - again, not that you should. All of those languages are stat= ically, 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. Ru= by is typically far simpler and clearer; that's part of the reason why it w= as made in the first place. Ruby is its own language. Just because other languages don't do it, does no= t mean Ruby would not benefit. And again, this is an _extension_ to the exi= sting 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 sing= le, standalone `public`, `private` or `protected` statements cause all foll= owing methods - *except* "private" class methods, notably - to have that pr= otection level. It is not idiomatic in Ruby to indent method definitions af= ter such declarations, so it becomes at a glance very hard to see what a me= thod's protection level is when just diving into a piece of source code. On= e 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 thi= s). Forcibly indenting code after declarations helps, but most Ruby develop= ers find this unfamiliar and most auto-formatters/linters will reset it or,= at best, complain. Further, the difficulty in defining private *class* met= hods or constants tells us that perhaps there's more we should do here - bu= t 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`, `p= rivate` or `protected` declarations to - *optionally* - support a block-lik= e 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 =3D "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 se= mantics apply, allowing one to add new block-based protection-enclosed meth= od declarations inside any existing code base without fear of accidentally = changing the protection level of any methods defined below the new block. A= s 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=EFve - for example, a= rising unanswered questions include: * Is the use of a block-like syntax making unwarranted assumptions about wh= at the Ruby compiler can do during its various parsing phases? * Does the use of a block-like syntax imply we should support things like P= rocs too? (I *think* probably not - I see this as just syntax sugar to prov= ide a new feature reusing a familiar idiom but without diving down any othe= r 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 coul= d be sketched out, then I might be able to have a go at implementation myse= lf and submit a PR - assuming anyone is keen on the idea in the first place= `:-)` -- = https://bugs.ruby-lang.org/ Unsubscribe: