やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

「PythonからRubyへ」を読む

 これで最後。 

情報源

PythonからRuby

  • RubyPythonよりもほんの少しだけ構文が多い

 細かい記法まで含めたらかなり多いと思う。

Pythonとの類似

 とくに気になるところはなかった。

Pythonとの違い

  • 定数をつくれます
  • 名前付けについての規約がいくつかあります
  • リストコンテナは、配列しかありません。配列は可変です
  • テキスト展開の記法が違います
  • 属性には直接アクセスできません
  • 組み込みクラスにメソッドを追加したり、書き換えたりできます
  • 一度定義した変数を未定義にする方法はありません
  • yieldキーワードの振る舞いは異なります
  • 無名関数は3種類ある

定数をつくれます

(値が変更されることを期待しない変数)

 値が変更されると警告が出るだけ。実際は変更されてしまうので定数とはとても言えない代物。

 Rubyの規約としては名前の頭文字を大文字にすると定数になる。必ずしも守る必要のない命名規則としては、見やすさをかねて全文字を大文字にするのがよい。

MAX = 100
MAX = 999
warning: already initialized constant MAX
warning: previous definition of MAX was here
> p MAX
999

 変更されてしまう。これ定数じゃないよね。警告なんて流しちゃうだろ。かといって実行時エラーにされても大事になりすぎるのかな。

テキスト展開の記法が違います

二重引用符で囲まれた文字列は、エスケープシーケンス(\tなど)や、 式展開(いちいち+で文字列連結すること無しに、 Rubyの式を評価した結果を他の文字列に挿入可能にするしくみ)を解釈します。 一重引用符で囲まれた文字列は、Pythonでいうraw文字列と同じ扱いとなります。

言語 展開しない 展開する
Ruby '' ""
Python r'', r"" '', ""

属性には直接アクセスできません

Rubyでは、属性へのアクセスはすべてメソッド経由になります

 あれ? attr_accessorがあったよね?

class C
  attr_accessor :name
  def initialize
    @name = 'ytyaru'
  end
end
p C.new.name = 'YTYARU' #=> "YTYARU"

 アクセスできちゃってますけど? それともattr_accessorってやつもメソッドなの?

 なるほど。メソッドを作る糖衣構文だったのか。attr_accessorを使わずに書くと以下のようになると。

class C
  def name; @name; end
  def name=(v); @name=v; end
  def initialize
    @name = 'ytyaru'
  end
end
p C.new.name = 'YTYARU' #=> "YTYARU"

 これでゲッター、セッターが書けるらしい。def name=(v)っていうところがセッターだね。クセのある記法だけどPythonよりはずっとマシ。できればC#くらいスマートだと嬉しかったけどね。

 ゲッターとセッターは以下の糖衣構文がある。

class C
  attr_reader :name
  attr_writer :name
end

 読取専用にしたいときはattr_readerだけセットするとか、そういった使い方になる。

一度定義した変数を未定義にする方法はありません

Pythonでいうdelのように

 ふーん、そうなんだ。

変数をnilで設定すれば、変数に入っていた値をGCできるようにはできますが、 スコープが存在する限り変数自体はシンボルテーブルに残り続けます。

 C#とかもそんな感じだったはず。

yieldキーワードの振る舞いは異なります

Pythonでは、関数呼び出しの外側のスコープへ実行結果を返します。 そのため、外側のコードは処理の再開について責任を負います。 Rubyでは、yieldは最後の引数として渡された別の関数が実行されます。 そして、実行が完了すると処理を再開します。

 最後の引数として渡された別の関数って、ブロックとかProcのことかな? そのへんよくわからない。

def get
  yield 1
  yield 2
  yield 3
end
> get {|i| p i}
1
2
3
=> 3

無名関数は3種類ある

Pythonがサポートしている無名関数はラムダ式のみですが、 Rubyはブロック、Procオブジェクト、ラムダ式といった種類の無名関数があります。

概念 概要
ブロック クロージャ。普段参照できないローカル変数を参照できる。
Proc 変数に代入できるブロック。&はブロックとオブジェクトを相互変換する。
Lambda Procとほぼ同じ。lambda?で真が返る。callreturnされてもメソッド終了しない。余分な引数があるとエラーになる。

 ProcよりもLambdaを使ったほうがバグが少なくなるはず。

所感

 無名関数のところが難しい。自分でコードを書ける自信がない。

対象環境

$ uname -a
Linux raspberrypi 5.10.52-v7l+ #1441 SMP Tue Aug 3 18:11:56 BST 2021 armv7l GNU/Linux