2021/01/07 今週の気になった bugs.ruby のチケット
内容は適当です。
今週と言っても今週みかけたチケットなだけでチケット自体は昔からあるやつもあります。
あくまでも『わたしが気になったチケット』で全ての bugs.ruby のチケットを載せているわけではありません。
[Feature #17471] send_if method for improved conditional chaining
- 以下のような
#send_if
を追加する提案
class Object def send_if(method, *args, proc: nil) yield(self) ? self.send(method, *args, &proc) : self end end
- これは以下のように『条件にマッチしたときのみメソッドチェーンを行う』ような場合に利用できる
puts 'Do you want a loud Merry Christmas? (y or I take it as a no)' answer = gets.chomp # 標準入力を受け取り、入力によって呼び出す処理を切り替える # 'y' が入力されたら大文字に変換して結合する puts %w(Merry Christmas).send(:map, &->(e) { answer == 'y' ? e.upcase : e }).join(' ') # 提案されている send_if ならこんな感じで記述できる puts %w(Merry Christmas).send_if(:map, proc: :upcase) { answer == 'y' }.join(' ')
- わたしもこういうのがほしいと思っていていろいろと考えているんですが今回の
#send_if
はかなりやってることが多くて個人的にはちょっと微妙- とはいえこうなってしまう理由もわかるのでうーーーーんって感じ
条件
と条件にマッチした場合の処理
の2つのブロックをメソッドに渡したいんですが Ruby でこのあたりどう表現すべきなのかが難しい
- ちなみに個人的には以下のような
tap + break
でいいじゃん、ってなっています
# Proposal puts %w(Merry Christmas).send_if(:map, proc: :upcase ) { answer == 'y' }.join(' ') # tap + break puts %w(Merry Christmas).tap { break _1.map(&:upcase) if answer == 'y' }.join(' ')
tap + break
に慣れてないとぎょっとするんですが、これはこれで Ruby としてみるとかなり素直なコードになっているので個人的には気に入っています- また似たようなチケットとしては以下のようなチケットもあるので気になる人はこちらも見てみると良いです
[Bug #17512] ostruct super regression
- 以下のように
super
を経由してOpenStruct
を参照した場合に Ruby 3.0 だと意図しない値が返ってきているというバグ報告
require 'ostruct' class Foo < OpenStruct def foo super end end p Foo.new(foo: 123).foo # Ruby 2.7 => 123 # Ruby 3.0 => nil
- この問題は
OpenStruct 0.3.2
で修正されている - 困っている人は個別に
OpenStruct
をインストールすると改善すると思います
[Misc #16436] hash missing #last method, make it not so consistent (it has #first)
Hash#first
はあるけどHash#last
はないので一貫性がないよねーっていうチケット
homu = { id: 1, name: "homu", age: 14 } pp homu.first # => [:id, 1] # error: undefined method `last' for {:id=>1, :name=>"homu", :age=>14}:Hash (NoMethodError) pp homu.last
- これは
Hash#first
はEnumerable#first
で実装されておりEnumerable#last
がないからですEnumerable#first
があってEnumerable#last
がないのは知らなかった- まあ確かにイテレーションを考えると
#first
はあっても#last
がないのはなんとなくわかるよな…?
- ちなみに以下のように
#reverse_each
を使うと終端の要素を取得することはできます
homu = { id: 1, name: "homu", age: 14 } pp homu.reverse_each.first # => [:age, 14]
- このチケット自体には強い気持ちでの要望とかはないので、もし必要な人とかがいればコメントしてみるといいと思います
[Bug #17488] Regression in Ruby 3: Hash#key? is non-deterministic when argument uses DelegateClass
- 次のように Ruby 3.0 で
Hask#key?
にDelegateClass
を渡すと意図しない結果が返ってくるというバグ報告- Ruby 3.0 では
Hask#key?
の結果が起動毎に変わることがある
- Ruby 3.0 では
puts "Running on Ruby: #{RUBY_DESCRIPTION}" program = <<~EOS require "delegate" TypeName = DelegateClass(String) hash = { "Int" => true, "Float" => true, "String" => true, "Boolean" => true, "WidgetFilter" => true, "WidgetAggregation" => true, "WidgetEdge" => true, "WidgetSortOrder" => true, "WidgetGrouping" => true, } puts hash.key?(TypeName.new("WidgetAggregation")) EOS iterations = 20 results = iterations.times.map { `ruby -e '#{program}'`.chomp }.tally # Ruby 3.0 で実行すると false が返ってくることがある puts "Results of checking `Hash#key?` #{iterations} times: #{results.inspect}" # Ruby 2.7 => Results of checking `Hash#key?` 20 times: {"true"=>20} # Ruby 3.0 => Results of checking `Hash#key?` 20 times: {"false"=>12, "true"=>8}
- この問題は開発版ではすでに修正済みです
[Bug #17481] Keyword arguments change value after calling super without arguments in Ruby 3.0
- 次のように
super
を呼び出す前と後でキーワード引数の値が変わってしまうというバグ報告
class BaseTest def call(a:, b:, **) end end class Test < BaseTest def call(a:, b:, **options) p options # => {:c=>{}} super # super を呼び出した後で options の値が変わってしまっている… p options # => {:c=>{}, :a=>1, :b=>2} end end Test.new.call(a: 1, b: 2, c: {})
- どうして…どうして…
- この問題は
Ruby 3.0
で再現しており開発版ではすでに修正済みです
[Feature #17472] HashWithIndifferentAccess like Hash extension
ActiveSupport::HashWithIndifferentAccess
をサポートする機能を Ruby で実装する?というチケット- ちょっとチケットの意図が読み取れてないので間違ってるかもしれませんが『Ruby 本体で
ActiveSupport::HashWithIndifferentAccess
を実装する(提供する)』というわけではなくて『`ActiveSupport::HashWithIndifferentAccess
を高速化できる仕組みを Ruby 側で用意する』っていうのが趣旨なのかな? - 具体的に言うと Ruby 3.0 で追加された
Symbol#name
みたいなのを Ruby 本体でActiveSupport::HashWithIndifferentAccess
を高速化できるような機能を提供する感じなんですかね- コメント読んでる限りこのあたりちょっと認識のズレがありそう
- 最初読んだ時に『
ActiveSupport::HashWithIndifferentAccess
を Ruby で提供するのはやめてくれ〜〜〜』と思っていたんですが機能提供って意味だとかなりよさそうですね
[RP] Remove deprecated URI.escape/URI.unescape
- 長らく非推奨だった
URI.escape
/URI.unescape
が Ruby 3.0 から削除された - 今後は代替として
ERB::Util.#url_encode
やCGI.escape
などを利用していく必要がある - 参照
使ってる Vim プラグインを紹介する:行番号を指定してファイルを開く
気が向いたら書いていくシリーズ。 よく考えたらアドベントカレンダーで書けばよかったのでは…?
行番号を指定してファイルを開く file-line
このプラグインを入れると vim
コマンドでファイルを開くときに
$ vim index.html:20
のように行番号を指定して開くことができるようになります。
また vim
コマンドだけではなくて『 vim
のコマンド』でも行番号を指定して開けます。
:edit index.html:20 # 新しいタブで開く :tabnew index.html:20
エラー出力のフォーマットは ファイル名:行番号
みたいになっていることが多いので、エラー出力をそのままコピペすればエラー位置を一発で開くことができるので便利。
使ってる Vim プラグインを紹介する:カーソル下の単語をハイライトする
気が向いたら書いていくシリーズ。
t9md/vim-quickhl
カーソル下の単語をハイライトするプラグインです。
ハイライトされた単語は表示されているウィンドウすべてに反映されます。
# スペース + m でカーソル下の単語をハイライトする nmap <Space>m <Plug>(quickhl-manual-this) # 選択したテキストをハイライトする xmap <Space>m <Plug>(quickhl-manual-this) # スペース + m ですべてのハイライトを無効にする nmap <Space>M <Plug>(quickhl-manual-reset) # operator として定義しておく # mi( でカッコの中をハイライトする等 nmap m <Plug>(operator-quickhl-manual-this-motion) vmap m <Plug>(operator-quickhl-manual-this-motion)
こんな感じで変数がどこで使われているのかが視覚的にわかるようになるので便利。
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-build
は brew
経由でインストールすると最新版が反映されるまでにラグがあるので 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
また rbenv
で Ruby 3.0 のインストールも特に問題なくできました。便利。
所感
上に書いた以外には macvim とか karabiner とか chrome とか入れたんですが今の所問題なく動いていますね。
実際の開発環境とかはこれから整える予定ですが思ったよりもスムーズにセットアップできてよかったよかった。
まだ感想をかけるほど使ってはいないんですがこれから docker とかそこら辺を試していきたいところ。
あと外観的な感想で言うと思ったよりも小さくて軽いなーっていう印象が強かったです。
まあ今まで使ってた MacBook Pro が重すぎたのかもしれませんが…。
あとベゼルが思ったよりも太い感じはしましたね。
こっちも最近のラップトップはベゼルが細いのが多いのでそれと比較して太い気がしているのかもしれませんが。
とりあえず、せっかく買ったのでもうちょいいろいろと遊んでみたいところです。
参照
2020年を振り返って
技術的な話で振り返ろうかと思ったのですがこころつらくなっているので今年読んで面白かったマンガの紹介をします。
ってちょろっと書こうと思ったら思ったよりもボリュームが増えてしまい…。
内容は薄いですが気になったやつがあればぜひぜひ読んでもらえると〜。
ちなみに今年は kindle で 1000冊以上買っていました。
Fate/kaleid liner プリズマ☆ ドライ!!
ご存知、魔法少女になるやつです。
アニメはほとんど見てません。
元々途中までは物理本で持ってたんですが kindle でまとめ買いしました。
本編よりも過去編がめっちゃ良かった…。
はしっこアンサンブル
『げんしけん』の作者が描く工業高校の合唱部の青春物語。
『げんしけん』もそうだけどこの手の青春者を描くうまいよねー。
個人的には『げんしけん』よりもクセがなくて万人受けするような内容になっていると思うのでおすすめです(ちょいちょい重い話が挟まっているのから目をそらしつつ。
よっけ家族
一時期『うさぎドロップ』の作者の宇仁田ゆみにハマって買い漁っていたうちの一つです。
特に大きなイベントがあるわけでもなくてただただある家族の日常が書かれており何も考えずに読むことができます。
いまの生活に疲れている人におすすめのマンガです。
このマンガが面白いと思ったら他の宇仁田ゆみマンガも読んでみるとよいです!
クミカのミカク
ただただヒロインがご飯を食べているマンガ。
読んでると無限にお腹が空いてくるのでよくない。
サチコと神ねこ様
ねことアラサーリケジョOL とのやり取りが面白いマンガ。
ちょこちょこ入ってくる毒舌の時事ネタが好きです。
うちにも神ねこ様が来てほしい。
シャングリラ・フロンティア ~クソゲーハンター、神ゲーに挑まんとす~
いわゆるなろう系マンガなんだけど内容自体は普通に面白い。
なろう系特有のご都合主義は結構強めだけどそのあたりが気にならない人は大丈夫だと思う。
まだ、2巻しか出てないのでこれからどういう展開になるのかは気になるところ。
スピリットサークル
個人的に人生トップ10に入る『惑星のさみだれ』の作者の水上悟志のマンガ。
前から知り合いにおすすめされてたけどやっとよめた。よかった。
雰囲気とかは『惑星のさみだれ』に似ているけどそれよりももっと設定は複雑になっている。
どうせ読むなら一気読みしてほしいマンガ。
スペクトラルウィザード
最近おすすめされて読んだマンガ。
登場キャラクターがかわいい。
一応2巻まで出ているんだけど完結しているかどうかはわからない。
2巻の最後がとてもつらいので救いを求めて続きを読みたいんだけどどうにかならんですかね…。
ダンジョン飯
これも最近読んだマンガ。
前から読みたかったけどやっと読むことができた。
もうちょっと飯中心なのかな、と思ってたけど思ったよりもダンジョンしてた。
これも読んでると腹が減るのでよくない。
ドロヘドロ
これも前から読みたいと思っていて(ry。
もっと殺伐としているのかと思ってたけど思ったよりもコミカルな内容だった。
キノコで無双するマンガは後にも先にもこれしかないでしょう。
結構中身が長いのと根本的な部分が最後まで引っ張られているので一気読みできてよかった。
ブルーピリオド
高校生が 0 から美大を目指す青春物。
苦悩しながらも試行錯誤して先に進もうとしていくあたりがぐっと来ますねえ。
読んでて世界観に引き込まれていきます。
ポンコツちゃん検証中
ポンコツちゃんがかわいいだけのマンガ。
内容は王道ラブコメで久々にこういうの読んだ気がする。
ヤンキー君と白杖ガール
あれ、これ去年紹介してなかったっけ?と思ったら紹介してなかった。
多分今年読んだ中で一番よかったマンガ。
内容はタイトルどおりでヤンキーな主人公と「弱視」なヒロインがいちゃつくマンガ。
と、思いきやライトな絵に反して内容はかなりヘビー、ヘビーなんだけど軽く読むことができる内容になっていてそのあたりのバランスがとてもよい。
読んでていろいろと考えさせれられるマンガです。
事情を知らない転校生がグイグイくる。
グイグイくるマンガです。
夫婦やん?
兄の嫁と暮らしています。
『共依存』っていう言葉がピッタリのマンガですね(白目。
よくある『がんばって前を向いて生きていこう』みたいなマンガかと思ったらどんどん病んでいくあたりがとてもたまりませんね。
まだまだ落ちていきそうなので続きが楽しみ。
古見さんは、コミュ症です。
これも今年読んだマンガだったか。
ひたすら古見さんがかわいいだけのマンガです。
あと登場キャラクターのネーミングセンスが好き。
女の園の星
面白い!!!以上!!!! とにかく無限に読んでいられるので早く続きが読みたい。
将棋めし
タイトル通り将棋めしの話。
読んでて腹が減ります。
わたしは将棋はあんまりわからんので飯の話しか頭に入ってこなかったんですが将棋要素もあるのでそっちに興味がある人も読んでみると面白いのでは。
忍者と極道
忍者と極道がヒャッハー!!するマンガです。
とにかく勢いがすごくて勢いで話が進んでいきます。
怪獣8号
これはもう『面白い!!』の一言に尽きる。
内容は一言で言うと『仮面ライダー』なんですがこういう設定好きなんですよねえ。
まだ 1巻しか出てないけどすぐに続きを読みたい…。
放課後ていぼう日誌
最近アニメを3周ぐらいしました。
いや、アニメ化する前から買ってたんですが。
内容は女子高生が釣りをするだけのマンガ。
よくよく考えると今年は釣りマンガばっかり買ってた気がする。
木曜日は君と泣きたい。
もうなんというか脳が混乱するマンガ。
それぞれがそれぞれに依存していいぞこれ〜〜ってなってました。
巻数が少ないのでさくっと読めますね。
波よ聞いてくれ
確かアニメを1話だけ見て面白かったので衝動買いしたような記憶がある。
主人公が破天荒すぎるのが読んでて面白い。
ほとんどラジオは聞いたことないんですが読んでるとラジオを聞きたくなってきますね。
あとカレーも無限に食べたくなってくる。
無能の鷹
めっちゃいい。
異種族レビュアーズ
スケベが大好きなマンガです。
天原いいよね天原。
アニメも好きです。
薬屋のひとりごと~猫猫の後宮謎解き手帳~
『薬屋のひとりごと』のコミカライズは サンデーGX
版と ガンガン
版の2種類ああるんですがわたしは サンデーGX
版の方が好きです。
いや、作画は ガンガン
版の方がいいんですが、話のつくりは サンデーGX
の方がいいんですよね〜〜〜〜。
個人的には最初に サンデーGX
を是非読んでもらいたいところ。
麻衣の虫ぐらし
タイトルに 虫
って付いているので虫要素はあるんですが、それ以上に病み要素が強すぎてな…。
むしろ 虫
はおまけ程度でヤンデレ百合マンガとして見たほうがいいと思います(こなみ感。
これも今年結構キタマンガでしたねえ。
邦画プレゼン女子高生 邦キチ! 映子さん
タイトル通りひたすら邦画のプレゼンをしているマンガです。
とにかくハチャメチャな邦画の紹介が面白い。
進撃の巨人の実写版ってあんな内容だったのか…。
【一人 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_left
は Enumerable#inject
と似たようなメソッドなのですが各ブロックの結果を配列で返します。
# inject は最後の結果だけ返す [1, 2, 3].inject(0, &:+) # => 6 # scan_left は各ブロックの戻り値を配列として返す [1, 2, 3].scan_left(0, &:+) # => [0, 1, 3, 6]
これは Haskell や Scala に存在する関数らしく 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
という名前はあんまりよろしくないと言うことで別の名前の提案がされいて今はそこで議論が止まっている感じです。
候補としては reflect
や project
interject
tranject
cumulative
などなど…。
このあたりの名前決めは難しそうですねえ。