give IT a try

プログラミング、リモートワーク、田舎暮らし、音楽、etc.

【アウトライン版】サンプルコードでわかる!Ruby 3.0の主な新機能と変更点

お知らせ

毎年恒例の(?)Rubyの新機能解説記事を公開しました。
型チェックについてまとめたPart 1と、それ以外の新機能についてまとめたPart 2があります。

qiita.com

zenn.dev

お気づきかもしれませんが、Part 2はQiitaではなくZennを使って書きました。
その理由は読者の方が記事に対してお金を振り込めるからです!・・・といっても僕がそのお金を独り占めするわけではありません。
2021年1月31日までに集まったお金はRubyの普及と発展のためにRubyアソシエーションに寄付する予定です。
また、こういった技術記事に対して、どれくらいの人が対価を支払う意思があるのかという、調査・実験の目的も兼ねています。
そんなわけで、上記の記事が良かった、役に立った、と思った人はぜひサポート(対価)の支払いをお願いします🙏

さて、それはそれとして、今回書いた記事はどちらもかなり長いので、このブログではそれぞれの記事の見出しをリストアップしておきます。
記事のアウトラインをざーっと見て面白そう、と思ったら元記事の内容をチェックしてみてください!

Part 1 - Rubyで型チェック!動かして理解するRBS入門

  • はじめに
    • 本記事の情報源
    • 動作確認したRubyのバージョン
    • フィードバックお待ちしています
  • Ruby 3.0の概要(というか、個人的な印象)
    • 後方互換性を窓から投げ捨てるような大きな変化はないが、マニアックな仕様変更がちょこちょこある
    • Rubyの未来を担う新機能が導入された
    • その他の注目ポイント
    • Ruby 2.7.2以上を使っている場合は「見えない警告」に注意!
    • 参考情報:アウトライン版もあります
  • 言語上の変更点
    • キーワード引数とハッシュオブジェクトの自動変換が廃止された(キーワード引数と通常の引数の分離)
    • Procの引数展開の仕様が少し変わった
    • ... 引数を使う際に通常の引数も併用できるようになった
    • case/inを使うパターンマッチングが正式に導入された
    • 1行パターンマッチングの構文がin=>の2種類になった(実験的機能)
    • パターンマッチングにFindパターンが追加された(実験的機能)
    • endlessメソッド定義構文が導入された(実験的機能)
    • frozen-string-literal: trueのマジックコメントが有効なとき、式展開された文字列が凍結されなくなった
    • shareable_constant_valueマジックコメントが導入された(実験的機能)
    • 静的型解析の基盤が導入された(RBS、TypeProf)
    • 非推奨警告がデフォルトで出力されなくなった(Ruby 2.7.2から導入された変更点)
    • $SAFE$KCODEがただのグローバル変数になった
    • メソッド内で特異クラスを定義する際にyieldを呼ぶことが禁止された
    • 親クラスと親モジュールで同じクラス変数を書き換えると実行時エラーが発生するようになった
    • トップレベルでクラス変数を読み書きしようとすると実行時エラーが発生するようになった
    • 変数やメソッド名に_1_2を使うと構文エラーが発生するようになった
  • 後方互換性が失われる変更点
    • 正規表現リテラルで作られた正規表現オブジェクトが凍結されるようになった
    • 範囲オブジェクト(Range)が凍結されるようになった
    • Hash#eachが必ず2要素の配列を渡すようになった
    • pipeが閉じられてSTDOUTに書き込みできない場合に、エラーメッセージが出力されなくなった
    • 定数のTRUE/FALSE/NILが削除された
    • 最適化のためInteger#zero?Numeric#zero?をオーバーライドするようになった
    • Enumerable#grepEnumerable#grep_vに正規表現オブジェクトを渡し、ブロックを使わなかった場合、Regexp.last_match/$~を変更しなくなった
    • open-uriをrequireしても、openメソッドではURLが開けなくなった
  • バックトレース出力に関する変更点
    • バックトレースがRuby 2.4以前の表示順に戻った
  • コマンドラインオプションの変更点
    • ヘルプの表示が1画面ずつ表示されるようになった
    • --backtrace-limitでエラー発生時に表示されるバックトレースの行数を制限できるようになった
  • コアライブラリの変更点
    • ArrayクラスのサブクラスもArray#flattenなどのメソッドが常にArrayクラスのインスタンスを返すようになった
    • Array#[]Enumerator::ArithmeticSequenceを受け取って要素をスライスできるようになった
    • Dir.globDir.[]がデフォルトでソートされた結果を返すようになった
    • HashとENVに指定されたキー以外の要素を返すexceptメソッドが追加された
    • WindowsでENVのキーと値がUTF-8になった
    • WindowsでEncoding.default_externalがUTF-8になった
    • Hash#transform_keysHash#transform_keys!でキーの変換ルールをハッシュで指定できるようになた
    • freeze: falseオプション付きでcloneすると、内部的に呼ばれるinitialize_cloneメソッドにもfreeze: falseオプションが渡されるようになった
    • freeze: trueオプション付きでcloneすると、cloneで得られたオブジェクトも凍結されるようになった
    • Bindingオブジェクト付きでevalを呼んだ場合、__FILE____LINE__が、それぞれ"(eval)"の文字列と、評価される文字列内での行番号を返すようになった
    • 引数1個でBinding#evalを呼び出したときの__FILE____LINE__の出力内容が変わった
    • ブロックリテラルを使わずにラムダでないprocオブジェクトをlambdaメソッドに渡すと警告が出るようになった
    • モジュールAにモジュールBをあとからinclude/prependした場合も、すでにモジュールAをincludeしているクラスにモジュールBの内容が反映されるようになった
    • public, protected, private, public_class_method, private_class_methodが引数としてメソッド名を列挙した配列を受け取れるようになった
    • attr_accessor, attr_reader, attr_writer, attrが戻り値として定義されたメソッドのシンボルの配列を返すようになった
    • alias_methodが戻り値として定義されたエイリアスメソッドのシンボルを返すようになった
    • Procクラスに==eql?メソッドが実装された
    • 並行・並列処理プログラミングをサポートする新しいライブラリ、Ractorが追加された(実験的機能)
    • Random::DEFAULTがRandomクラスオブジェクトを返すようになり、なおかつ警告対象となった
    • StringクラスのサブクラスもString#upcaseなどのメソッドが常にStringクラスのインスタンスを返すようになった
    • Symbol#to_procがラムダのProcを返すようになった
    • 凍結された文字列を返すSymbol#nameメソッドが追加された
    • Warning#warncategoryオプション付きで呼ばれるようになった
  • 標準ライブラリの主な変更点
    • OpenStructが遅延初期化されなくなった
    • OpenStructのpublicなビルトインメソッドが!付きで呼び出せるようになった
    • OpenStructのYAMLサポートが改善された
    • OpenStructはなるべく使わない方がよい、という公式見解が出された
    • SortedSetクラスがsetライブラリから削除された
    • 要素を連結して文字列を返すSet#joinが実装された
    • Set同士の大小を比較する<=>演算子が追加された
  • その他
    • ruby2_keywordsを使った場合の空のハッシュを引数に渡したときの挙動が変わった
    • 初期化されていないインスタンス変数にアクセスしても警告が出なくなった
    • マルチスレッド関連/GC関連の変更点(見出しのみ)
    • その他の細かい変更点
  • まとめ
    • お願い:サポート(対価の支払い)をぜひお願いします!

zenn.dev

まとめ

Ruby 3.0は便利な新機能の追加よりも、重箱の隅をつつくような言語仕様の変更が多かったので、NEWS.mdの説明やissueを読んでもぱっと理解できず、何がどう変わったのか、なぜその変更が必要だったのか、といった点を把握するのにとても時間がかかりました。

それだけにプログラミング言語のあるべき仕様を考え、それを実装する大変さをネット越しに感じたので、それが記事の収益を寄付しようと思った大きな理由のひとつになります。

そんなわけで、Rubyコミッタのみなさんに感謝しつつ、僕の書いた記事も参考にしつつ、まもなくやってくるRuby 3.0時代を一緒に楽しみましょう〜😄