[#47383] [ruby-trunk - Feature #8469][Open] ABI checker とか導入しませんか — "kosaki (Motohiro KOSAKI)" <kosaki.motohiro@...>

21 messages 2013/06/01
[#47394] [ruby-trunk - Feature #8469] ABI checker とか導入しませんか — "usa (Usaku NAKAMURA)" <usa@...> 2013/06/04

[#47395] Re: [ruby-trunk - Feature #8469] ABI checker とか導入しませんか — KOSAKI Motohiro <kosaki.motohiro@...> 2013/06/04

> CIに組み込んでもらえるとちょー助かる感じですぅ

[#47396] Re: [ruby-trunk - Feature #8469] ABI checker とか導入しませんか — Tanaka Akira <akr@...> 2013/06/04

2013年6月4日 14:23 KOSAKI Motohiro <kosaki.motohiro@gmail.com>:

[#47397] Re: [ruby-trunk - Feature #8469] ABI checker とか導入しませんか — KOSAKI Motohiro <kosaki.motohiro@...> 2013/06/04

>> CI って誰に相談すればいいんですかね。今のツールだと比較対象のバイナリまたは

[#47399] Re: [ruby-trunk - Feature #8469] ABI checker とか導入しませんか — Tanaka Akira <akr@...> 2013/06/05

2013年6月4日 15:26 KOSAKI Motohiro <kosaki.motohiro@gmail.com>:

[#47402] Re: [ruby-trunk - Feature #8469] ABI checker とか導入しませんか — KOSAKI Motohiro <kosaki.motohiro@...> 2013/06/05

>>> 比較対象を用意しないといけないのが面倒くさそうでほったらかしてたんですが。

[#47422] [ruby-trunk - Feature #8526][Open] Removing tk from Ruby repository — "naruse (Yui NARUSE)" <naruse@...>

26 messages 2013/06/14

[ruby-dev:47401] [ruby-trunk - Feature #8497][Open] private, protected, private_constなどがブロックを受け取るようにする

From: "kou (Kouhei Sutou)" <kou@...>
Date: 2013-06-05 14:27:21 UTC
List: ruby-dev #47401
Issue #8497 has been reported by kou (Kouhei Sutou).

----------------------------------------
Feature #8497: private, protected, private_constなどがブロックを受け取るようにする
https://bugs.ruby-lang.org/issues/8497

Author: kou (Kouhei Sutou)
Status: Open
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category: core
Target version: 


RubyKaigi 2013のときにまつもとさんと話したことをチケットにします。

先に提案を書きます。

private, protected, private_constなど可視性を変更するメソッドがブロックを受け取るようにして、そのブロック内の可視性を変更するようにしてはどうか。

例:
  private do
    def some_private_method
    end
  end

  def some_public_method
  end

  private_const do
    PRIVATE_CONSTANT = true
  end

メリットは以下のとおりです。

  * 以下のように同じ名前を2回書く必要がない

      PRIVATE_CONSTANT = true
      private_const :PRIVATE_CONSTANT

  * 可視性変更の影響をブロック内だけに抑える実装ができる
    (すでになかださんがパッチを持っているので、後でここに貼ってくれるはず。)

  * 構文に関してはまつもとさんから肯定的な意見をもらっている
    「ブロックを使った構文はよさそうに感じる。ただ、試してみないと最終的にはわからないけど。」

デメリットは以下のとおりです。

  * 前方互換ではない

    古いRubyで以下のように書くとブロックが単に無視されメソッドが定義されない。

      private do
        def some_private_method
        end
      end

背景です。

privateは以下のように現在のコンテキストの可視性を変更する

  private
  def xxx
  end

という書き方もできるのにprivate_constantは

  private_constant :XXX

という書き方しかできないことにもやっとしていたので、その理由を聞いてみました。

理由は「コンテキストの可視性を変更するとちゃんとした実装にするのが大変そうだから。試していないけど、Threadを使ったりして並行にrequireしたときにおかしなことになるかもしれないし。普通はしないと思うけど、ちゃんと動くことを期待されそうじゃん。」という感じでした。

試しにやってみましたが、問題はありませんでした。

threaded-require.rb:
  100.times do |i|
    File.open("#{i}.rb", "w") do |rb|
      rb.puts("class A")
      rb.puts("  " + ["private", "protected", "public"][i % 3])
      rb.puts("  Thread.pass")
      rb.puts("  def x#{'%02d' % i}; end; Thread.pass")
      rb.puts("end")
    end
  end

  threads = []
  50.times do |i|
    threads << Thread.new(i) do |j|
      require_relative("#{j}")
    end
  end
  threads.each(&:join)

  class A
    p [:private, private_instance_methods(false).sort]
    p [:public, public_instance_methods(false).sort]
    p [:protected, protected_instance_methods(false).sort]
  end

実行例(毎回同じ):
  % /tmp/local/bin/ruby -v threaded-require.rb
  ruby 2.1.0dev (2013-06-05 trunk 41090) [x86_64-linux]
  [:private, [:x00, :x03, :x06, :x09, :x12, :x15, :x18, :x21, :x24, :x27, :x30, :x33, :x36, :x39, :x42, :x45, :x48]]
  [:public, [:x02, :x05, :x08, :x11, :x14, :x17, :x20, :x23, :x26, :x29, :x32, :x35, :x38, :x41, :x44, :x47]]
  [:protected, [:x01, :x04, :x07, :x10, :x13, :x16, :x19, :x22, :x25, :x28, :x31, :x34, :x37, :x40, :x43, :x46, :x49]]

もうひとつ以下のような強引な例を試してみたら、こっちは実行する毎に結果が変わりました。(こんな挙動になってもしょうがないんじゃないかという気もします。)

thread-def.rb
  class A
    threads = []
    100.times do |i|
      threads << Thread.new(i) do |j|
        send([:private, :protected, :public][j % 3])
        Thread.pass
      end
    end
    Thread.pass
    def a; end; Thread.pass
    def b; end; Thread.pass
    def c; end; Thread.pass
    def d; end; Thread.pass
    def e; end; Thread.pass
    def f; end; Thread.pass
    def g; end; Thread.pass
    def h; end; Thread.pass
    def i; end; Thread.pass
    def j; end; Thread.pass
    def k; end; Thread.pass
    def l; end; Thread.pass
    def m; end; Thread.pass
    def n; end; Thread.pass
    def o; end; Thread.pass
    def p; end; Thread.pass
    def q; end; Thread.pass
    def r; end; Thread.pass
    def s; end; Thread.pass
    def t; end; Thread.pass
    def u; end; Thread.pass
    def v; end; Thread.pass
    def w; end; Thread.pass
    def x; end; Thread.pass
    def y; end; Thread.pass
    def z; end; Thread.pass
    threads.each(&:join)
    p [:private, private_instance_methods(false)]
    p [:public, public_instance_methods(false)]
    p [:protected, protected_instance_methods(false)]
  end

実行例1:
  % /tmp/local/bin/ruby -v thread-def.rb
  ruby 2.1.0dev (2013-06-05 trunk 41090) [x86_64-linux]
  [:private, [:b, :c, :d, :e, :f, :g, :h, :i, :j, :k, :l, :m, :n, :o, :p, :q, :r, :s, :t, :u, :v, :w, :x, :y, :z]]
  [:public, [:a]]
  [:protected, []]

実行例2(実行例1と結果が違っている):
  % /tmp/local/bin/ruby -v thread-def.rb
  ruby 2.1.0dev (2013-06-05 trunk 41090) [x86_64-linux]
  [:private, []]
  [:public, [:a, :b]]
  [:protected, [:c, :d, :e, :f, :g, :h, :i, :j, :k, :l, :m, :n, :o, :p, :q, :r, :s, :t, :u, :v, :w, :x, :y, :z]]

ブロックを使った書き方をサポートすると、並行に動いた時にもちゃんとした挙動になる実装にできそうな気がするのでブロックを使った書き方をサポートするのはどうでしょうか?

(「ちゃんと」とは何かをちゃんと決めないとだめそうな気がしますが。。。)

ブロックを使えるようになって、並行に動いた時にもちゃんとした挙動の実装だったら、以下のコードが毎回同じ結果になるはずです。

  File.open("thread-block-def.rb", "w") do |rb|
    rb.puts("class A")
    rb.puts("  threads = []")
    100.times do |i|
      rb.puts("  threads = Thread.new do")
      visibility = ["private", "protected", "public"][i % 3]
      rb.puts("    #{visibility} do")
      ("a".."z").each do |character|
        rb.puts("      Thread.pass")
        rb.puts("      def #{character}#{'%02d' % i}")
        rb.puts("      end")
        rb.puts("      Thread.pass")
      end
      rb.puts("    end")
      rb.puts("  end")
    end
    rb.puts("threads.join(&:each)")
    rb.puts("end")
  end

  require_relative("thread-block-def")

  class A
    p [:private, private_instance_methods(false).sort]
    p [:public, public_instance_methods(false).sort]
    p [:protected, protected_instance_methods(false).sort]
  end



-- 
http://bugs.ruby-lang.org/

In This Thread

Prev Next