2020年1月8日水曜日

ruby2.7.0 を試してみた

概要

昨年のクリスマスに ruby2.7.0 がリリースされました
早速ですが使ってみました
とりあえず主要そうな機能と簡単に試せそうな機能について軽く触れている感じです

環境

  • macOS 10.15.2
  • rbenv 1.1.2
  • ruby 2.7.0

ruby2.7.0 の準備

まずはインストールします
執筆時点では Homebrew に 2.7.0 がなかったので rbenv を使いました
rbenv ではすでに 2.7.0 の配信が始まっているようです

まずは ruby-build と rbenv を最新版にします

  • brew upgrade ruby-build rbenv

rbenv でインストール可能なバージョンの一覧を表示すると「2.7.0」があるのが確認できると思います

  • rbenv install --list

あとはインストールします
openssl のパスを指定していますがもしかすると不要です
rbenv が自動で最新版をインストールしてくれるっぽいです

  • export LDFLAGS="-L/usr/local/opt/openssl@1.1/lib"
  • export CPPFLAGS="-I/usr/local/opt/openssl@1.1/include"
  • rbenv install 2.7.0

ビルドが完了すれば rbenv のインストールパスにバイナリが配置されます

Downloading openssl-1.1.1d.tar.gz… -> https://dqw8nmjcqpjn7.cloudfront.net/1e3a91bc1f9dfce01af26026f856e064eab4c8ee0a8f457b5ae30b40b8b711f2 Installing openssl-1.1.1d… Installed openssl-1.1.1d to /Users/hawksnowlog/.rbenv/versions/2.7.0   Downloading ruby-2.7.0.tar.bz2… -> https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.0.tar.bz2 Installing ruby-2.7.0… ruby-build: using readline from homebrew Installed ruby-2.7.0 to /Users/hawksnowlog/.rbenv/versions/2.7.0

あとはメインに設定すれば OK です

  • rbenv global 2.7.0
  • rbenv version
  • ``rbenv which ruby`` -v

=> ruby 2.7.0p0 (2019-12-25 revision 647ee6f091) [x86_64-darwin19]

これを使って試していきます

case でのパターンマッチング

オフィシャルのサンプルは以下のような感じです
JSON の文字列からハッシュを作成し、そのハッシュでパターンマッチングしています

require "json"

json = <<END
{
  "name": "Alice",
  "age": 30,
  "children": [{ "name": "Bob", "age": 2 }]
}
END

case JSON.parse(json, symbolize_names: true)
in {name: name, children: [{name: children_name, age: children_age}]}
  p name
  p children_name
  p children_age
end

case にパターンマッチさせたいオブジェクトを指定します
そして in でパターンとなる構文を指定できます

どうやらパターンマッチングにはいくつかあるようです上記はハッシュパターンというマッチングだと理解しました
例えば以下のように自分で作成したクラスでもパターンマッチングが使えます
ハッシュパターンを使って自分で作成したクラスをパターンマッチングさせたい場合は deconstruct_keys というメソッドを実装します

require "json"

class A
  def initialize
    @a = "A"
  end

  def deconstruct_keys(keys)
    {a: @a}
  end

  attr_accessor :a
end

case A.new
in {a: a}
  p a
else
  p "ng"
end

上記の場合実行するとインスタンス変数に設定した「A」が表示されます
こんな感じで自分のクラスに対してもパターンマッチングが使えます
ちなみにアレイパターンというマッチング方式もありその場合は deconstruct というメソッドを実装し配列を返却するようにすればアレイパターンを使ってパターンマッチングすることができます

require "json"

class A
  def initialize
    @a = "A"
  end

  def deconstruct
    ["C", "B", @a]
  end

  attr_accessor :a
end

case A.new
in ["C", "B", a]
  p a
else
  p "ng"
end

パターンマッチングについてはこちら が参考になりました

irb の複数行対応

例えば irb を使ってメソッドやクラスを定義した際に再度同じメソッドやクラスを定義したい場合は再度 1 行ずつ入力していました
それが 1 度の入力で済むようになっています
公式に動画あるのでそれを見るのが一番はやいと思います
以下は適当にキャプチャしたものです

rbenv でインストールした場合 irb は /Users/hawksnowlog/.rbenv/versions/2.7.0/bin/irb にありました

Compaction GC

未検証です
とりあえず GC.compact がどこでも呼べることは確認しています

キーワード引数に対してハッシュを与えると警告が表示される

これまではキーワード引数に対してハッシュでも渡すことができました
2.7.0 でも渡すことができますが警告が表示されるようになります
Ruby3.0 では正式に使えなくなるようです
具体的には以下の通りです

# coding: utf-8
def hoge(key: "default")
  p key
end

def fuga(key: "default", key2: "default2")
  p key
  p key2
end

hoge
hoge(key: "value")
hoge({key: "value"}) # これは警告
fuga
fuga(key: "value", key2: "value2")
fuga({key: "value", key2: "value2"}) # これも警告

hoge(**{key: "value"}) # double splat 演算子を付与すれば警告を回避できる
fuga(**{key: "value", key2: "value2"}) # double splat 演算子を付与すれば警告を回避できる

改めて見ると確かに単一の引数に対してハッシュが渡せてしまうのは気持ち悪い感じもします
表示される警告の内容は以下のような感じでした

test.rb:13: warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call test.rb:2: warning: The called method `hoge' is defined here

警告を回避するには double splat 演算子を付与するか ruby 実行時のオプションで -W:no-deprecated を指定しても回避できます
コード内のどこかで Warning[:deprecated] = false を指定しても回避できます

  • ``rbenv which ruby`` -W:no-deprecated test.rb

また nil や配列の引数に対する挙動も変わっているので詳細は公式を御覧ください

範囲指定で開始番号が省略可能になった

省略した場合は 0 スタートになるようです
添字の部分には使えるようですが Range クラスのオブジェクトを作成する際にはちゃんとスタートの数字を指定しないとエラーになるようです

.. もメソッドなのでレシーバとなるオブジェクトがないから?

# coding: utf-8
ary = [0, 1, 2, 3, 4]
p ary[..3] # [0, 1, 2, 3]

ary = (..4).to_a # これはダメっぽい

tally

出現回数をカウントしてくれます
injectgroup_by + map を使って自分で作る必要がなくなったのは嬉しいです

ary = ["a", "a", "b", "c", "c", "c", "c"]
p ary.tally # {"a"=>2, "b"=>1, "c"=>4}

令和対応

合字の「㋿」に対応しました

p 0x32ff.chr("utf-8")

確かに古い Ruby だと表示されませんでした

その他細かい点

公式を見てください

最後に

簡単ですが Ruby2.7.0 に触れてみました
ほんの一部しか紹介できておらずまだまだたくさんの機能が追加されたので試してみてください
細かく触っていないのであれですがインパクトがあったのは irb のアップデートだったかなという印象です

詳細はすべて Feature Request の Issue でやり取りが公開されているのでそれを確認するのが早いと思います

0 件のコメント:

コメントを投稿