やってみる

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

「PHPからRubyへ」を読む

 PHPもほとんど触ったことがない。

情報源

PHPからRuby

 Ruby on Railsはよく聞くけど一度も触ったことがないので気になっている。たまたま以下の記事をみつけたので書き残しておく。

PHPとの類似

  • evalもあります
  • ヒアドキュメントがあります
  • かなり膨大な標準ライブラリがあります

PHPとの違い

  • 変数は参照です
  • 抽象クラスabstractinterfaceはありません
  • ほとんどすべてのことはメソッド呼出です。raiseですら。

 Rubyinterfaceがない。多態性がない。ダッグタイピングだから同名メソッドさえあれば実行できるって感じか。型チェックではなくメソッド名を持っているかで判定する感じ? でも継承やMixinがあって型判定もあるはず。うーん、たぶん適当にMixinで追加すればいいやって感じなのかな? そもそも、いつでも定義変更できちゃうし。

evalもあります

> eval 'puts "A"'
A

 いいね。

ヒアドキュメントがあります

 書式は以下。

<<[(-|~)]["'`]識別子["'`]
   ...
識別子

 識別子は何でもいい。EOSが慣例。End Of Stringだと思われる。

 インデントを制御できる。

表記 インデント
<<EOS 書いたまま
<<-EOS 終端行のインデントを削除する
<<~EOS インデントが最少の行を基準に空白を削除する。

 識別子をクォートすることでヒアドキュメント内容を制御できる。

表記 展開 コマンド実行
'EOS'
"EOS"
`EOS`

<<EOS

def m
    doc = <<EOS
    My name is ytyaru.
    I am ytyaru.
EOS
    puts doc
end
m
    My name is ytyaru.
    I am ytyaru.

 終端行EOSは行頭に書かねばならない。さもなくば終端行と判定されずにヒアドキュメントが終了できない。

 でもこれは見づらい。終端行EOSはインデントしてdef定義のそれに合わせたい。そこで<<-EOSを使う。

<<-EOS

def m
    doc = <<-EOS
    My name is ytyaru.
    I am ytyaru.
    EOS
    puts doc
end
m
    My name is ytyaru.
    I am ytyaru.

 ところで、ドキュメントがインデントされてしまっている。このインデントはあくまでソースコードdefにあわせたインデントであって、ドキュメント自体のインデントではあってほしくない。ドキュメントの無用なインデントは消したい。そこで<<~EOSを使う。

<<~EOS

def m
    doc = <<~EOS
    My name is ytyaru.
    I am ytyaru.
    EOS
    puts doc
end
m
My name is ytyaru.
I am ytyaru.

 なお、最小インデントよりも多い分は残る。なのでドキュメント内における適切なインデントが保持される。

def m
    doc = <<~EOS
    * 1
      * 1-1
    * 2
    EOS
    puts doc
end
m
* 1
  * 1-1
* 2

 これはすばらしい! BashでもPythonでもできなくてストレスだった。なんとRubyでは<<~EOS構文によってクリアできる。最高だ。なんて素敵なんだろうか。

 さらに識別子にクォートをつければ式展開やコマンド展開さえも制御できてしまう。

<<~'EOS'リテラル

 識別子をシングルクォートすればドキュメントは文字列リテラルになる。式展開もされないし、コマンド展開もされない。

def m
    name = 'ytyaru'
    doc = <<~'EOS'
    date
    * #{name}
      * 1-1
    * 2
    EOS
    puts doc
end
m
date
* #{name}
  * 1-1
* 2

<<~"EOS"(式展開)

 識別子をダブルクォートすればドキュメントは式展開される。#{name}のところが変数nameの値ytyaruに置換される。

def m
    name = 'ytyaru'
    doc = <<~"EOS"
    date
    * #{name}
      * 1-1
    * 2
    EOS
    puts doc
end
m
date
* ytyaru
  * 1-1
* 2

<<~`EOS`(コマンド展開)

 識別子をバッククォートすればドキュメントはコマンド展開される。1行目のシェルコマンドdateだけが正しく実行された。

def m
    name = 'ytyaru'
    doc = <<~`EOS`
    date
    * #{name}
      * 1-1
    * 2
    EOS
    puts doc
end
m
sh: 2: a: not found
sh: 3: a: not found
sh: 4: a: not found
2021年 10月 22日 金曜日 13:48:03 JST

 これはつまり、<<~`EOS`の中にそのままBashのコードを書けるということだ。OS依存すぎるので微妙だが、自動化ツールをサクッと書きたいときは便利そう。標準出力の結果をRubyの変数で受け取れるし。

 つまりBashでサクッとできることはBashでやって、Bashでは難しいことはRubyでやる。そんな運用が簡単にできるってことだ。最高すぎる。これをPythonでやろうとしたらサブプロセスがどうとかで超面倒になる。Rubyいいね😀

かなり膨大な標準ライブラリがあります

 これは勉強しごたえがありそう。組込だけでも多い。

所感

 Rubyのヒアドキュメントがすばらしい。

対象環境

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