[#88240] [Ruby trunk Feature#14759] [PATCH] set M_ARENA_MAX for glibc malloc — sam.saffron@...
Issue #14759 has been updated by sam.saffron (Sam Saffron).
[#88251] Re: [ruby-alerts:8236] failure alert on trunk@P895 (NG (r64134)) — Eric Wong <normalperson@...>
ko1c-failure@atdot.net wrote:
[#88305] [Ruby trunk Bug#14968] [PATCH] io.c: make all pipes nonblocking by default — normalperson@...
Issue #14968 has been reported by normalperson (Eric Wong).
[#88331] [Ruby trunk Feature#13618] [PATCH] auto fiber schedule for rb_wait_for_single_fd and rb_waitpid — samuel@...
Issue #13618 has been updated by ioquatix (Samuel Williams).
[#88342] [Ruby trunk Feature#14955] [PATCH] gc.c: use MADV_FREE to release most of the heap page body — ko1@...
Issue #14955 has been updated by ko1 (Koichi Sasada).
[#88433] [Ruby trunk Feature#13618] [PATCH] auto fiber schedule for rb_wait_for_single_fd and rb_waitpid — ko1@...
Issue #13618 has been updated by ko1 (Koichi Sasada).
ko1@atdot.net wrote:
[#88475] [Ruby trunk Misc#14937] [PATCH] thread_pthread: lazy-spawn timer-thread only on contention — ko1@...
Issue #14937 has been updated by ko1 (Koichi Sasada).
[#88491] Re: [ruby-cvs:71466] k0kubun:r64374 (trunk): test_function.rb: skip running test — Eric Wong <normalperson@...>
k0kubun@ruby-lang.org wrote:
I see. Please remove the test if the test is unnecessary.
Takashi Kokubun <takashikkbn@gmail.com> wrote:
[#88523] [Ruby trunk Bug#14999] ConditionVariable doesn't reacquire the Mutex if Thread#kill-ed — eregontp@...
Issue #14999 has been updated by Eregon (Benoit Daloze).
eregontp@gmail.com wrote:
[#88549] [Ruby trunk Bug#14999] ConditionVariable doesn't reacquire the Mutex if Thread#kill-ed — eregontp@...
Issue #14999 has been updated by Eregon (Benoit Daloze).
[#88676] [Ruby trunk Misc#15014] thread.c: use rb_hrtime_scalar for high-resolution time operations — ko1@...
Issue #15014 has been updated by ko1 (Koichi Sasada).
ko1@atdot.net wrote:
On 2018/08/27 16:16, Eric Wong wrote:
[#88716] Re: [ruby-dev:43715] [Ruby 1.9 - Bug #595] Fiber ignores ensure clause — Eric Wong <normalperson@...>
Koichi Sasada wrote:
[#88723] [Ruby trunk Bug#15041] [PATCH] cont.c: set th->root_fiber to current fiber at fork — ko1@...
Issue #15041 has been updated by ko1 (Koichi Sasada).
[#88767] [Ruby trunk Bug#15050] GC after forking with fibers crashes — ko1@...
Issue #15050 has been updated by ko1 (Koichi Sasada).
Koichi Sasada <ko1@atdot.net> wrote:
[#88774] Re: [ruby-alerts:8955] failure alert on trunk@P895 (NG (r64594)) — Eric Wong <normalperson@...>
ko1c-failure@atdot.net wrote:
[ruby-core:88361] [Ruby trunk Feature#14869] Proposal to add Hash#===
Issue #14869 has been updated by timriley (Tim Riley).
This is looking like a really positive improvement, thank you!
Would you consider taking this one step further and supporting the explicit converter, `#to_h` instead of (or as well as, if required) the implicit `#to_hash` converter? This would allow using `Hash#===` to match against e.g. `Struct` instances (which have `#to_h` but not `#to_hash`) plus any other kind of object that doesn't want to pretend to "be" a hash, but rather provide the interface for converting to one.
There are penalties for implementing `#to_hash`, like implicit destructuring when an object is passed to a method with kwrest params, so its fair to expect that not every class would want to do it. `#to_h`, on the other hand, is much more common (just like we see in the example of Ruby's own `Struct`), so supporting that would make this matcher even more flexible, usable, and powerful.
----------------------------------------
Feature #14869: Proposal to add Hash#===
https://bugs.ruby-lang.org/issues/14869#change-73391
* Author: osyo (manga osyo)
* Status: Open
* Priority: Normal
* Assignee:
* Target version:
----------------------------------------
## 概要
`Hash#===` を追加する提案になります。
## 仕様
レシーバのキーの要素と引数のハッシュのキーの要素を `#===` で比較して、全てが真なら `true` を返し、そうでないなら `false` を返す。
また、レシーバが空のハッシュの場合、引数が空のハッシュなら `true` を返し、そうでないなら `false` を返す。
```ruby
user = { id: 1, name: "homu", age: 14 }
# name 要素が data にあるので true
p ({ name: "homu" } === user)
# => true
# 複数の要素があっても OK
p ({ id: 1, name: "homu", age: 14 } === user)
# => true
# name 要素が user にあるが、値が違うので false
p ({ name: "name" } === user)
# => false
# キーの要素が引数にないので false
p ({ number: 42 } === user)
# => false
# 1つでもキーの要素がない場合も false
p ({ id: 1, name: "homu", number: 42 } === user)
# => false
# レシーバが空のハッシュなら false
p ({} == user)
# => false
# 空のハッシュ同士なら true
p ({} == {})
# => true
# 引数がハッシュ以外なら false
p ({ id: 42 } == 42)
# => false
# #=== で比較しているのでこういうこともできる
p ({ name: /^h/ } === user)
# => true
p ({ age: (1..20) } === user)
# => true
p ({ age: Integer } === user)
# => true
```
## ユースケース
### バリデーション
case-when では `===` を使用して値を比較しているので、`Hash#===` を利用することで次のように条件分岐を行うことが出来る。
```ruby
def validation user
case user
# name に対するバリデーション
when { name: /^[a-z]/ }
raise "名前の先頭が小文字の場合は登録できません"
# age に対するバリデーション
when { age: (0..20) }
raise "0〜20歳は登録できません"
# 各要素が任意のクラスのインスタンスかどうかのバリデーション
when { id: Integer, name: String, age: Integer }
true
else
false
end
end
# 条件を満たしているので OK
mami = { id: 1, name: "Mami", age: 21 }
validation mami
# => true
# name が小文字から始まっているので NG
mado = { id: 2, name: "mado", age: 13 }
validation mado
# => 名前の先頭が小文字の場合は登録できません (RuntimeError)
# age が 0〜20歳以内なので NG
homu = { id: 3, name: "Homu", age: 14 }
validation homu
# => 0〜20歳は登録できません (RuntimeError)
```
### `Enumerable#grep`
`Enumerable#grep` は内部で `===` を使用した比較を行っているので、次のように任意の Hash のキーの要素に対して検索を行うことが出来る。
```ruby
data = [
{ id: 1, name: "Homu", age: 13 },
{ id: 2, name: "mami", age: 14 },
{ id: 3, name: "Mado", age: 21 },
{ id: 4, name: "saya", age: 14 },
]
# 特定の要素が含まれている Hash のみを絞り込む
p data.grep(name: /m/)
# => [{:id=>1, :name=>"Homu", :age=>13}, {:id=>2, :name=>"mami", :age=>14}]
p data.grep(age: (1..20))
# => [{:id=>1, :name=>"Homu", :age=>13}, {:id=>2, :name=>"mami", :age=>14}, {:id=>4, :name=>"saya", :age=>14}]
```
## 補足1: `==` ではなくて `===` で比較する理由
* `===` を使用することでより細かい・抽象的な条件を指定することが出来る
* `Class` や `Regexp`、`Proc` などで比較することが出来る
* 内部で `===` を使用している場合、 `==` で比較したい場合は `obj.method(:==)` を渡せば実現出来るが、その逆は出来ない
* 内部で `==` を使用している場合、 `===` で比較ししたくても出来ない
## 補足2: 空のハッシュの比較に関して
* `Object#===` の場合だと `{} === 42` が例外ではなくて `false` を返していたので、`Hash#===` も `false` を返すようにした
* `{} === {}` が `true` を返すのも同様の理由になります
* これにより以下のような既存のコードも互換性を壊すことなく動作するかと思います
```ruby
def check n
case n
when {}
"Empty Hash"
when []
"Empty Array"
when 0
"Zero"
else
"Not empty"
end
end
p check({}) # => "Empty Hash"
p check([]) # => "Empty Array"
p check(0) # => "Zero"
p check({ name: "mado" }) # => "Not empty"
```
以上、`Hash#===` に関する提案になります。
挙動に関して疑問点や意見などございましたらコメント頂けると助かります。
---Files--------------------------------
hash_eqq.patch (3.54 KB)
hash_eqq.patch (4.43 KB)
--
https://bugs.ruby-lang.org/
Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>