Issue #16276 has been updated by jeremyevans0 (Jeremy Evans).


Dan0042 (Daniel DeLorme) wrote:
> Ok, but how is this different from the regular syntax? The exact same iss=
ue applies to this:
> =

> ```ruby
> class A
> end
> =

> Thread.new do
>   class A
>     def pub; end
>   end
> end
> =

> class A
>   private
>   def priv; end
> end
> ```

Are you sure?  You can test this by using queues to synchronize:

```ruby
class A
end

Q1 =3D Queue.new
Q2 =3D Queue.new

Thread.new do
  class A
    Q2.pop
    def pub; end
    Q1.push nil
  end
end

class A
  private
  def priv; end
  Q2.push nil
  Q1.pop
end

A.public_instance_methods(false) # =3D> [:pub]
```

> If there's no problem with the above, there's no reason why the proposed =
block form would have any problem either right? In other words the thread/f=
iber issue is irrelevant to the current proposal.

There is no problem with fibers/threads currently, because the visibility i=
s stored in the scope (not in the class itself).  You stated `When the priv=
ate method toggles the visibility state of the current class/module`, imply=
ing this would implemented with a visibility flag on the class/module.  You=
 cannot have visibility stored in the class/module and handle fibers/thread=
s properly without making the class-level visibility information fiber/thre=
ad-aware.

----------------------------------------
Feature #16276: For consideration: "private do...end" / "protected do...end"
https://bugs.ruby-lang.org/issues/16276#change-82404

* 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: <mailto:ruby-core-request / ruby-lang.org?subject=3Dunsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>