M1 の MacBook で rbenv + Ruby 2.6.6 をビルドする

rbenv で Ruby 2.7 や 3.0 のビルドは問題なかったんですが 2.6 で失敗したのでその対処方法を書いておきます。

rbenv で 2.6.6 をインストールする

rbenv で 2.6.6 をインストールしようとしたらエラーになります。

$ rbenv install 2.6.6
Downloading openssl-1.1.1i.tar.gz...
-> https://dqw8nmjcqpjn7.cloudfront.net/e8be6a35fe41d10603c3cc635e93289ed00bf34b79671a3a4de64fcee00d5242
Installing openssl-1.1.1i...
Installed openssl-1.1.1i to /Users/anzu/.rbenv/versions/2.6.6

Downloading ruby-2.6.6.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.6/ruby-2.6.6.tar.bz2
Installing ruby-2.6.6...
ruby-build: using readline from homebrew

BUILD FAILED (macOS 11.1 using ruby-build 20201225-2-g5de6d5f)

Inspect or clean up the working tree at /var/folders/j_/4snw29l52s5g_hwy5fxbvqsw0000gp/T/ruby-build.20210102215022.60171.Wp1e2j
Results logged to /var/folders/j_/4snw29l52s5g_hwy5fxbvqsw0000gp/T/ruby-build.20210102215022.60171.log

Last 10 log lines:
compiling zlib.c
compiling normalize.c
compiling modify.c
compiling set_len.c
compiling enc_str_buf_cat.c
compiling new.c
linking shared-object -test-/string.bundle
linking shared-object date_core.bundle
linking shared-object zlib.bundle
make: *** [build-ext] Error 2

実際のコンパイルエラーは以下な感じです。

compiling nofree.c
linking shared-object -test-/wait_for_single_fd.bundle
linking shared-object -test-/vm/at_exit.bundle
compiling closure.c
compiling zlib.c
compiling ellipsize.c
installing default libraries
compiling conversions.c
closure.c:264:14: error: implicit declaration of function 'ffi_prep_closure' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
    result = ffi_prep_closure(pcl, cif, callback, (void *)self);
             ^
compiling normalize.c
1 error generated.
make[2]: *** [closure.o] Error 1
make[2]: *** Waiting for unfinished jobs....
linking shared-object date_core.bundle
compiling psych_to_ruby.c
compiling escape.c
compiling stringio.c
compiling modify.c
make[1]: *** [ext/fiddle/all] Error 2
make[1]: *** Waiting for unfinished jobs....

ffi 周りでコケてるっぽい…。

RUBY_CFLAGS=-DUSE_FFI_CLOSURE_ALLOC rbenv install 2.6.6 でインストールする

困ってたら以下の issues を教えてもらってそこに書いてあった RUBY_CFLAGS=-DUSE_FFI_CLOSURE_ALLOC rbenv install 2.6.6 で無事にインストールすることができました。

$ RUBY_CFLAGS=-DUSE_FFI_CLOSURE_ALLOC rbenv install 2.6.6
rbenv: /Users/anzu/.rbenv/versions/2.6.6 already exists
continue with installation? (y/N) y
Downloading openssl-1.1.1i.tar.gz...
-> https://dqw8nmjcqpjn7.cloudfront.net/e8be6a35fe41d10603c3cc635e93289ed00bf34b79671a3a4de64fcee00d5242
Installing openssl-1.1.1i...
Installed openssl-1.1.1i to /Users/anzu/.rbenv/versions/2.6.6

Downloading ruby-2.6.6.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.6/ruby-2.6.6.tar.bz2
Installing ruby-2.6.6...
ruby-build: using readline from homebrew
Installed ruby-2.6.6 to /Users/anzu/.rbenv/versions/2.6.6

ありがてえありがてえ…。

M1 の MacBook Air のセットアップした

あけましておめでとうございます。
今年は年明けから年末に買っていた M1 の MacBook Air のセットアップをしていました。
この記事も M1 で書いています。
ぶっちゃけ発売前はネガティブな印象が強かった M1 だったんですが発売後はコスパがよかったりソフトウェアの対応なども進んで来ていて割と好印象だったのでつい勢いで買ってしまいました。
実際セットアップもそこまで手間取ることなく普通にアプリケーションなどもインストールできました。
今のところは目立ったトラブルがないのでよかったよかった。
と、言うことで覚書。

homebrew

ちょうど 12/30 に公式でサポートしたらしくていつもどおり公式に載ってるコマンドを実行すればインストールすることができます。

$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

ただし、手元だとこれだけではパスが通らす brew コマンドが使えなかったので .zshrc にパスを追加してやる必要がありました。

# .zshrc
typeset -U path PATH
path=(
    /opt/homebrew/bin(N-/)
    /usr/local/bin(N-/)
    $path
)

これで無事に brew コマンドが使えるようになりました。便利。

rbenv + ruby-build

rbenv は特に問題なく brew でインストールできました。
また ruby-buildbrew 経由でインストールすると最新版が反映されるまでにラグがあるので git から直接 clone しました。

# rbenv をインストールする
$ brew install rbenv

# 一旦消す
$ brew uninstall ruby-build

# git からインストールする
$ mkdir -p "$(rbenv root)"/plugins
$ git clone https://github.com/rbenv/ruby-build.git "$(rbenv root)"/plugins/ruby-build

また rbenvRuby 3.0 のインストールも特に問題なくできました。便利。

所感

上に書いた以外には macvim とか karabiner とか chrome とか入れたんですが今の所問題なく動いていますね。
実際の開発環境とかはこれから整える予定ですが思ったよりもスムーズにセットアップできてよかったよかった。
まだ感想をかけるほど使ってはいないんですがこれから docker とかそこら辺を試していきたいところ。
あと外観的な感想で言うと思ったよりも小さくて軽いなーっていう印象が強かったです。
まあ今まで使ってた MacBook Pro が重すぎたのかもしれませんが…。
あとベゼルが思ったよりも太い感じはしましたね。
こっちも最近のラップトップはベゼルが細いのが多いのでそれと比較して太い気がしているのかもしれませんが。
とりあえず、せっかく買ったのでもうちょいいろいろと遊んでみたいところです。

f:id:osyo-manga:20210101183023j:plain

参照

2020年を振り返って

技術的な話で振り返ろうかと思ったのですがこころつらくなっているので今年読んで面白かったマンガの紹介をします。
ってちょろっと書こうと思ったら思ったよりもボリュームが増えてしまい…。
内容は薄いですが気になったやつがあればぜひぜひ読んでもらえると〜。
ちなみに今年は kindle で 1000冊以上買っていました。

Fate/kaleid liner プリズマ☆ ドライ!!

Fate/kaleid liner プリズマ☆イリヤ ドライ!!(1) (角川コミックス・エース)

ご存知、魔法少女になるやつです。
アニメはほとんど見てません。
元々途中までは物理本で持ってたんですが kindle でまとめ買いしました。
本編よりも過去編がめっちゃ良かった…。

はしっこアンサンブル

はしっこアンサンブル(1) (アフタヌーンコミックス)

げんしけん』の作者が描く工業高校の合唱部の青春物語。
げんしけん』もそうだけどこの手の青春者を描くうまいよねー。
個人的には『げんしけん』よりもクセがなくて万人受けするような内容になっていると思うのでおすすめです(ちょいちょい重い話が挟まっているのから目をそらしつつ。

よっけ家族

よっけ家族 1 (バンブーコミックス)

一時期『うさぎドロップ』の作者の宇仁田ゆみにハマって買い漁っていたうちの一つです。
特に大きなイベントがあるわけでもなくてただただある家族の日常が書かれており何も考えずに読むことができます。
いまの生活に疲れている人におすすめのマンガです。
このマンガが面白いと思ったら他の宇仁田ゆみマンガも読んでみるとよいです!

クミカのミカク

クミカのミカク(1) (RYU COMICS)

ただただヒロインがご飯を食べているマンガ。
読んでると無限にお腹が空いてくるのでよくない。

サチコと神ねこ様

サチコと神ねこ様【フルカラー】(1)

ねことアラサーリケジョOL とのやり取りが面白いマンガ。
ちょこちょこ入ってくる毒舌の時事ネタが好きです。
うちにも神ねこ様が来てほしい。

シャングリラ・フロンティア ~クソゲーハンター、神ゲーに挑まんとす~

シャングリラ・フロンティア ~クソゲーハンター、神ゲーに挑まんとす~(1) (週刊少年マガジンコミックス)

いわゆるなろう系マンガなんだけど内容自体は普通に面白い。
なろう系特有のご都合主義は結構強めだけどそのあたりが気にならない人は大丈夫だと思う。
まだ、2巻しか出てないのでこれからどういう展開になるのかは気になるところ。

スピリットサークル

スピリットサークル (1) (ヤングキングコミックス)

個人的に人生トップ10に入る『惑星のさみだれ』の作者の水上悟志のマンガ。
前から知り合いにおすすめされてたけどやっとよめた。よかった。
雰囲気とかは『惑星のさみだれ』に似ているけどそれよりももっと設定は複雑になっている。
どうせ読むなら一気読みしてほしいマンガ。

スペクトラルウィザード

スペクトラルウィザード

最近おすすめされて読んだマンガ。
登場キャラクターがかわいい。
一応2巻まで出ているんだけど完結しているかどうかはわからない。
2巻の最後がとてもつらいので救いを求めて続きを読みたいんだけどどうにかならんですかね…。

ダンジョン飯

ダンジョン飯 1巻 (HARTA COMIX)

これも最近読んだマンガ。
前から読みたかったけどやっと読むことができた。
もうちょっと飯中心なのかな、と思ってたけど思ったよりもダンジョンしてた。
これも読んでると腹が減るのでよくない。

ドロヘドロ

ドロヘドロ(1) (IKKI COMIX)

これも前から読みたいと思っていて(ry。
もっと殺伐としているのかと思ってたけど思ったよりもコミカルな内容だった。
キノコで無双するマンガは後にも先にもこれしかないでしょう。
結構中身が長いのと根本的な部分が最後まで引っ張られているので一気読みできてよかった。

ブルーピリオド

ブルーピリオド(1) (アフタヌーンコミックス)

高校生が 0 から美大を目指す青春物。
苦悩しながらも試行錯誤して先に進もうとしていくあたりがぐっと来ますねえ。
読んでて世界観に引き込まれていきます。

ポンコツちゃん検証中

ポンコツちゃん検証中(1) (少年サンデーコミックス)

ポンコツちゃんがかわいいだけのマンガ。
内容は王道ラブコメで久々にこういうの読んだ気がする。

ヤンキー君と白杖ガール

ヤンキー君と白杖ガール 1 (MFC)

あれ、これ去年紹介してなかったっけ?と思ったら紹介してなかった。
多分今年読んだ中で一番よかったマンガ。
内容はタイトルどおりでヤンキーな主人公と「弱視」なヒロインがいちゃつくマンガ。
と、思いきやライトな絵に反して内容はかなりヘビー、ヘビーなんだけど軽く読むことができる内容になっていてそのあたりのバランスがとてもよい。
読んでていろいろと考えさせれられるマンガです。

事情を知らない転校生がグイグイくる。

事情を知らない転校生がグイグイくる。 1巻 (デジタル版ガンガンコミックスJOKER)

グイグイくるマンガです。
夫婦やん?

兄の嫁と暮らしています。

兄の嫁と暮らしています。 1巻 (デジタル版ヤングガンガンコミックス)

共依存』っていう言葉がピッタリのマンガですね(白目。
よくある『がんばって前を向いて生きていこう』みたいなマンガかと思ったらどんどん病んでいくあたりがとてもたまりませんね。
まだまだ落ちていきそうなので続きが楽しみ。

古見さんは、コミュ症です。

古見さんは、コミュ症です。(1) (少年サンデーコミックス)

これも今年読んだマンガだったか。
ひたすら古見さんがかわいいだけのマンガです。
あと登場キャラクターのネーミングセンスが好き。

女の園の星

女の園の星(1)【電子限定特典付】 (FEEL COMICS swing)

面白い!!!以上!!!! とにかく無限に読んでいられるので早く続きが読みたい。

将棋めし

将棋めし 1 (MFコミックス フラッパーシリーズ)

タイトル通り将棋めしの話。
読んでて腹が減ります。
わたしは将棋はあんまりわからんので飯の話しか頭に入ってこなかったんですが将棋要素もあるのでそっちに興味がある人も読んでみると面白いのでは。

忍者と極道

忍者と極道(1) (コミックDAYSコミックス)

忍者と極道がヒャッハー!!するマンガです。
とにかく勢いがすごくて勢いで話が進んでいきます。

怪獣8号

怪獣8号 1 (ジャンプコミックスDIGITAL)

これはもう『面白い!!』の一言に尽きる。
内容は一言で言うと『仮面ライダー』なんですがこういう設定好きなんですよねえ。
まだ 1巻しか出てないけどすぐに続きを読みたい…。

放課後ていぼう日誌

放課後ていぼう日誌 1 (ヤングチャンピオン烈コミックス)

最近アニメを3周ぐらいしました。
いや、アニメ化する前から買ってたんですが。
内容は女子高生が釣りをするだけのマンガ。
よくよく考えると今年は釣りマンガばっかり買ってた気がする。

木曜日は君と泣きたい。

木曜日は君と泣きたい。(1)【電子限定特典付】

もうなんというか脳が混乱するマンガ。
それぞれがそれぞれに依存していいぞこれ〜〜ってなってました。
巻数が少ないのでさくっと読めますね。

波よ聞いてくれ

波よ聞いてくれ(1) (アフタヌーンコミックス)

確かアニメを1話だけ見て面白かったので衝動買いしたような記憶がある。
主人公が破天荒すぎるのが読んでて面白い。
ほとんどラジオは聞いたことないんですが読んでるとラジオを聞きたくなってきますね。
あとカレーも無限に食べたくなってくる。

無能の鷹

無能の鷹(1) (Kissコミックス)

めっちゃいい。

異種族レビュアーズ

異種族レビュアーズ (ドラゴンコミックスエイジ)

スケベが大好きなマンガです。
天原いいよね天原
アニメも好きです。

薬屋のひとりごと~猫猫の後宮謎解き手帳~

薬屋のひとりごと~猫猫の後宮謎解き手帳~(1) (サンデーGXコミックス)

薬屋のひとりごと』のコミカライズは サンデーGX 版と ガンガン 版の2種類ああるんですがわたしは サンデーGX 版の方が好きです。
いや、作画は ガンガン 版の方がいいんですが、話のつくりは サンデーGX の方がいいんですよね〜〜〜〜。
個人的には最初に サンデーGX を是非読んでもらいたいところ。

麻衣の虫ぐらし

麻衣の虫ぐらし(1) (バンブーコミックス)

タイトルに って付いているので虫要素はあるんですが、それ以上に病み要素が強すぎてな…。
むしろ はおまけ程度でヤンデレ百合マンガとして見たほうがいいと思います(こなみ感。
これも今年結構キタマンガでしたねえ。

邦画プレゼン女子高生 邦キチ! 映子さん

邦画プレゼン女子高生 邦キチ! 映子さん (マーガレットコミックスDIGITAL)

タイトル通りひたすら邦画のプレゼンをしているマンガです。
とにかくハチャメチャな邦画の紹介が面白い。
進撃の巨人の実写版ってあんな内容だったのか…。

【一人 cugs.ruby Advent Calendar 2020】[Feature #17016] Enumerable#scan_left【25日目】

一人 bugs.ruby Advent Calendar 2020 25日目の記事になります。
長かったアドベントカレンダーも今日で最後です。

[Feature #17016] Enumerable#scan_left

このチケットは Enumerable#scan_left を追加する提案です。
Enumerable#scan_leftEnumerable#inject と似たようなメソッドなのですが各ブロックの結果を配列で返します。

# inject は最後の結果だけ返す
[1, 2, 3].inject(0, &:+)
# => 6

# scan_left は各ブロックの戻り値を配列として返す
[1, 2, 3].scan_left(0, &:+)
# => [0, 1, 3, 6]

これは HaskellScala に存在する関数らしく Ruby でも欲しいそうです。
PR はちょっと前からあり、gem もあります。

ユースケースとしては累積和を求めるときに便利らしいです。
他にはコメントで以下のようなユースケーズも提示されています。

# 銀行の入出金履歴
gains = [+3000, -2000, +2000, -1000]

# 残高の履歴を計算
sums = [0]
(1..gains.length).each do |i|
  sums[i] = sums[i - 1] + gains[i - 1]
end
pp sums
# => [0, 3000, 1000, 3000, 2000]

# scan_left を使うとシュッとできる
sums = gains.scan_left(0, &:+)
pp sums
# => [0, 3000, 1000, 3000, 2000]

あとは以下のようなケースとか…。

module Enumerable
  # 疑似実装
  def scan_left(init = shift, &block)
    inject([init]) { |a, e| a << (block.call a.last, e) }
  end
end

# 4312.to_s.chars.sort.join.to_i の呼び出し過程を計算したりとか…
p [4312, :to_s, :chars, :sort, :join, :to_i].scan_left(&:send)
# => [4312, "4312", ["4", "3", "1", "2"], ["1", "2", "3", "4"], "1234", 1234]

ちなみに Enumerable#scan_left は以下のように #inject を使っても同じ値を取得する事はできます。

pp [1, 2, 3].inject([0]){ |a, e| a << a.last + e }
# => [0, 1, 3, 6]

ただし、この場合は普通には #lazy 化はできないので注意する必要があります。

# こういうような書き方はできない
(1..).lazy.inject([0]){|a, e| a << a.last + e} # => infinite loop
(1..).lazy.each_with_object([0]){|e, a| a << a.last + e} # => infinite loop
(1..).lazy.scan_left(0, &:+) # => Lazy enumerator

# がんばればできる
p (1..).lazy.enum_for(:inject, 0).map {|a, b| a + b }.take(10).force
# => [1, 3, 6, 10, 15, 21, 28, 36, 45, 55]

# もしくは
# p (1..).lazy.enum_for(:inject, 0).map {|a, b| a + b }.first(10)

#scan_left という名前はあんまりよろしくないと言うことで別の名前の提案がされいて今はそこで議論が止まっている感じです。
候補としては reflectproject interject tranject cumulative などなど…。
このあたりの名前決めは難しそうですねえ。

【Ruby 3.0 Advent Calendar 2020】Ruby 3.0 がリリースされました!!!【25日目】

Ruby 3.0 Advent Calendar 2020 25日目の記事になります。

Ruby 3.0.0 リリース

予定通り本日12月25日に無事 Ruby 3.0 がリリースされました。
開発者の皆様お疲れ様でした。
それと同時にこのアドベントカレンダーも本日で終了になります。
参加していただいた皆様ありがとうございました!! Ruby 3.0 のリリースノートは以下になります。

Ruby 3.0 では新機能はもちろん細かな変更もたくさん入っています。
具体的にどのような機能が入り、どのような機能が変更されたのかはこのアドベントカレンダーにかかれている記事が役に経つと思います。
また、12月に入ってからも Ruby の開発は行われおりアドベントカレンダーに書かれている部分が変更されている可能性もあります(主にわたしの記事とか…) なので、オフィシャルなリリースノートNEWS も合わせて参照してみるといいと思います。
いやー本当に無事にリリースされてよかったよかった…。
開発者の皆様本当にお疲れ様でした。

2020/12/17 今週の気になった bugs.ruby のチケット

内容は適当です。
今週と言っても今週みかけたチケットなだけでチケット自体は昔からあるやつもあります。
あくまでも『わたしが気になったチケット』で全ての bugs.ruby のチケットを載せているわけではありません。

[Feature #17303] Remove webrick from stdlib

[Feature #17371] Reintroduce expr in pat

  • Ruby 2.7 で入った1行 in=> に置き換わる形で一旦削除された
  • これを => とは違い真理値を返す形で復活させる提案
  • これを利用すると条件分岐などで in を使えるようになる
# version 2.7
0 in 1 #=> raise NoMatchingPatternError

# version 3.0
0 in 1 #=> false
# name が String 型で age が20以下の場合にマッチする
if user in { name: String, age: (..20) }
  puts "OK"
end
users = [
  { name: "homu", age: 14 },
  { name: "mami", age: 15 },
  { name: "mado", age: 14 },
]
# こんな感じで絞り込むことができる
pp users.select { _1 in { name: /^m/, age: (...15) } }

[Feature #17314] Provide a way to declare visibility of attributes defined by attr* methods in a single expression

  • 以前も紹介したチケット
  • 以下のような変更を行う内容
class Foo
  protected [:x, :y]
  # same as:
  protected :x, :y

  attr_accessor :foo, :bar # => [:foo, :foo=, :bar, :bar=] instead of `nil`
  attr_reader :foo, :bar # => [:foo, :bar] instead of `nil`
  attr_writer :foo, :bar # => [:foo=, :bar=] instead of `nil`

  alias_method :new_alias, :existing_method # => :new_alias instead of `Foo`
end
  • これを利用すると以下のようにかける
class Foo
  private attr_accessor :foo, :bar
end
  • これはまつもとさんが承認したので Ruby 3.0 に入りそう
    • ただし、まだマージはされていない

[Feature #8382] Format OpenStruct YAML dump and create getters and setters after load.

  • OpenStructYAML への変換をサポートしたチケット
  • すでに OpenStruct 側で取り込まれており Ruby 2.7.2 でも使えた
require "ostruct"
require "yaml"

h = { name: "John Smith", age: 70, pension: 300.0 }
os = OpenStruct.new(h)
pp os.to_yaml
# Ruby 2.7.1
# "--- !ruby/object:OpenStruct\n" +
# "table:\n" +
# "  :name: John Smith\n" +
# "  :age: 70\n" +
# "  :pension: 300.0\n"

# Ruby 2.7.2
# "--- !ruby/object:OpenStruct\n" +
# "name: John Smith\n" +
# "agf: 70\n" +
# "pension: 300.0\n"

[Feature #17384] shorthand of Hash#merge

  • Hash#merge のショートハンドの提案チケット
  • Hash#+#merge する
a = {k: 1}
b = {j: 2}
c = a.merge(b)
d = a + b # same as c
  • これは以下のチケットと重複している
  • 便利そうな気もするけどウーン

[PR #3904] Skip defined instruction in NODE_OP_ASGN_OR with ivar

$VERBOSE = true

# Ruby 2.7.2 : warning: instance variable @value not initialized
# Ruby 3.0.0 : no warning
pp @value
  • この変更で @foo ||= 123 時に不要なオーバーヘッドがあったのでそれを削除した PR
  • 背景としては元々 @foo ||= 123@foo || (@foo = 123) と展開してしまうと後者の場合、警告がでてしまっていた
$VERBOSE = true

# no warning
@foo ||= 123
# warning: instance variable @foo not initialized
@foo || (@foo = 123)
  • これを対処するために @foo ||= 123 では警告が出ないようにするための命令が追加されていた
    • 多分擬似的に @foo を定義しているような命令?
  • しかし、Ruby 3.0 で警告が出なくなった為、この命令は不要になり削除された、という経緯になる
  • 単純に @foo ||= 123 のパフォーマンスが上がったそうなので普通に便利そう

merge, fix されたチケット

2020/12/24 今週の気になった bugs.ruby のチケット

内容は適当です。
今週と言っても今週みかけたチケットなだけでチケット自体は昔からあるやつもあります。
あくまでも『わたしが気になったチケット』で全ての bugs.ruby のチケットを載せているわけではありません。

[Bug #17030] Enumerable#grep{_v} should be optimized for Regexp その後

  • 以前紹介した ary.select { |e| e.match?(reg) } と比較して ary.grep(reg) の方が遅いので最適化しよう、という提案
  • その後、議論が進んで最終的に ary.grep(reg) のようにブロック引数がない場合は MatchData を生成しないように対応された
ary = ["homu", "mami", "mado"]

reg = /.*/
ary.grep(reg)
# or Regexp.last_match
p $~
# 2.7 => #<MatchData "mado">
# 3.0 => nil

# ブロックを渡した場合は MatchData を生成する
ary.grep(reg) {}
# or Regexp.last_match
p $~
# 2.7 も 3.0 => #<MatchData "mado">
  • この挙動は非互換な変更になるので注意する必要がります

[PR #124] Add measure command

  • irbmeasure というコマンドが追加された
  • これは measure を呼び出した以降で実行時間を出力するような事を行う
irb(main):001:0> 3
 => 3
irb(main):002:0> measure
TIME is added.
 => nil
irb(main):003:0> 3
processing time: 0.000058s
 => 3
irb(main):004:0> measure :off
 => nil
irb(main):005:0> 3
 => 3
  • また以下のようにカスタマイズすることも可能です
IRB.conf[:MEASURE_PROC][:CUSTOM] = proc { |context, code, line_no, &block|
  time = Time.now
  result = block.()
  now = Time.now
  puts 'custom processing time: %fs' % (Time.now - time) if IRB.conf[:MEASURE]
  result
}
  • これは普通に便利そう

[Bug #17428] Method#inspect bad output for class methods

  • Method#inspect の内容がおかしいというバグ報告
  • 次のようにクラス名が表示されないケースがある
p String.method(:prepend)
# 2.7 => #<Method: String.prepend(*)>
# 3.0 => #<Method: #<Class:Object>(Module)#prepend(*)>
  • この問題は最新版では以下のように修正された
p String.method(:prepend)
# 2.7 => #<Method: String.prepend(*)>
# 3.0 => #<Method: #<Class:String>(Module)#prepend(*)>
  • これは気づかなかった…

[Feature #17116] raise ArgumentError in Enumerator#new in no given blocks

  • Enumerator.new(obj) みたいに .new にブロックを渡さない場合は deprecated warning が出ている
    • この警告がでているのは Ruby 2.0 の頃から
obj = Object.new
# warning: Enumerator.new without a block is deprecated; use Object#to_enum instead
Enumerator.new(obj)
  • これはもうエラーにしてしまってもいいんじゃないか、というチケット
  • これはマージされて Ruby 3.0 からはエラーになるので注意しましょう

[Bug #17423] Prepend should prepend a module before the class

  • Ruby 3.0 では以下のように prepend の挙動が変わってしまう事がある
module M; end
module A; end
class B; include A; end

A.prepend M
B.prepend M

# B.prepend M してるのに M が B よりもあとに来る
p B.ancestors
# 2.7 => [M, B, A, Object, Kernel, BasicObject]
# 3.0 => [B, M, A, Object, Kernel, BasicObject]
  • これを次のように M が重複するようにするという内容のチケット
module M; end
module A; end
class B; include A; end

A.prepend M
B.prepend M

# このように修正する
p B.ancestors
# => [M, B, M, A, Object, Kernel, BasicObject]
  • この問題は Ruby 3.0 リリース後に対応される予定です
  • ちなみにこのチケットはまつもとさん自身が建てています

[Feature #17411] Allow expressions in pattern matching

  • パターンマッチでは次のようにパターンの部分に式を書くことができません
user = { name: "homu", age: 14 }
case user
# syntax error, unexpected '+', expecting ')'
# パターンに式を記述する事ができない
in { age: (7 + 7) }
end
  • これを ^(expression) のようにかけるようにしようという提案
user = { name: "homu", age: 14 }
case user
# OK
# 式を書く場合は ^() を使う
in { age: ^(7 + 7) }
end

[Bug #17398] SyntaxError in endless method

  • Ruby 3.0 のエンドレスメソッド定義で次のような定義の場合シンタックスエラーになる、という旨のチケット
# OK
def hoge = puts("homu")

# syntax error, unexpected string literal, expecting `do' or '{' or '('
def hoge = puts "homu"