Ruby

**Ruby**（ルビー）は、まつもとゆきひろ（通称: Matz）により開発された、オブジェクト指向スクリプト言語。

## 概要
Rubyは、1993年2月24日に生まれ、1995年12月にfjで発表された。

命名の一番大きな理由は、名前の短い美しい宝石だから。6月の誕生石Pearl（真珠）と同じ発音をするPerlに続くという意味で、7月の誕生石Ruby（ルビー）からも来ている。

2011年3月22日、「JIS X 3017」に制定。

2012年4月1日、「ISO/IEC 30170」に承認、日本人が開発したプログラミング言語では初めて、国際電気標準会議（IEC）に認証された。

2025年9月現在、言語仕様は明文化されていない。

文字列・数値等すべてのデータをオブジェクトとして扱う。

クラス、ガベージコレクション、例外処理、Mixin、正規表現等の基本機能に、別途機能をRubyGemsで追加可能。

バージョン1.9.3以降、BSDとのデュアルライセンスで頒布されている。

## 設計思想
なぜ、Rubyを開発したのか。

Rubyの言語仕様策定において、最も重視しているのは、ストレスなくプログラミングを楽しむことである／enjoy programming。

クラスと定数の先頭をアルファベット大文字に限定した仕様（基本設計思想）について、Matzは次のとおり説明している。

静的型について、Matzは（基本設計思想である動的型付けを維持し）『静的型付けを導入しない』意思を改めて示した。

MINASWAN「Matzがniceだから俺らもniceでいよう」

## 実装
### 公式

#### MRI
:Matzによる実装。MRI（Matz Ruby Interpreter）またはCRuby。ソースコードを構文木にコンパイルした後、evalで実行するインタプリタ。1.8以前を指すこともある。

#### YARV
:1.9で採用されたYARVは、#MRIのevalをバイトコード実行に置き換えたもの。ソースコードをバイトコードにコンパイルし実行するインタプリタ。

### その他

#### JRuby
:JRuby - Javaによる実装。Rubyと互換性が高い。インタプリタ／実行時コンパイラ／事前コンパイラがある。事前コンパイラでは（JRubyがなくても）、他のJavaプラットフォーム上で動作可能。

#### IronRuby
:IronRuby - .NET Frameworkによる実装。.NET Frameworkのライブラリと連携可能。JIT方式のバイトコードインタプリタ。共通言語基盤に準拠した実装（Monoなど）で動作するため、プラットフォーム非依存の利用も可能。ただし、.NET Frameworkのライブラリに依存している場合、Monoでの動作は不可能。

#### mruby
:mruby - 組み込みシステム向けの軽量版。家電製品、スマートフォン、コンピュータゲームなどでの使用を想定。

### 仮想マシン
仮想マシン上で動作する実装

#### GraalVM
GraalVMによる実装
*truffleruby

#### Parrot
Parrotによる実装
*Cardinal - Rubyコンパイラ

## コード例
ここでは、実用途に即したコード例を中心に記載する。クロスプラットフォームでの使用を考慮しているが、Unix系コマンドを利用できない環境では正常に動作しないことがある。なお、ウィキブックスには、より多くの基本的なコード例が記載されている。

### はじめに
#### すべてのデータがオブジェクト

```ruby
I1 = 123

p f1 = I1.to_f  #=> 123.0 浮動小数点数に変換
p i1 = I1.to_i  #=> 123   整数に変換
p s1 = I1.to_s  #=> "123" 文字列に変換

p -f1.abs       #=> 123.0
p -i1.abs       #=> 123
p s1.length     #=> 3
p s1.index("1") #=> 0
```


#### メソッドチェーン
メソッドを`.`で連結し順に処理

```ruby
p S1 = "Rubyは楽しい?"                             #=> "Rubyは楽しい?"
p S1.split(//)                                     #=> ["R", "u", "b", "y", "は", "楽", "し", "い", "?"]
p S1.split(//).map{|v| v.gsub("?", "!!")}          #=> ["R", "u", "b", "y", "は", "楽", "し", "い", "!!"]
p S1.split(//).map{|v| v.gsub("?", "!!")}.join("") #=> "Rubyは楽しい!!"
```


以下のように書くこともできる。

```ruby
p "Rubyは楽しい?"
    .split(//)
    .map{|v| v.gsub("?", "!!")}
    .join("")
#=> "Rubyは楽しい!!"
```


#### コメントアウト
`#`で始まる行は、1行コメント。

```ruby
# コメント1
  # コメント2
```


`=begin ... =end`行は、複数行コメント。

```ruby
=begin
コメント1
  コメント2
=end
```


#### おまじない
ヘッダ情報の付与

```ruby
#!/usr/bin/env ruby
#coding:utf-8

puts "本コードは、これ以降に書く。"
```

:1行目：シバン行。使用するインタプリタを記述（Windows系実装では無視される）。
:2行目：使用する文字コードを記述。ここではutf-8を指定。

### 変数と定数
#### ローカル変数
小文字 または '_' で始まる識別子は ローカル変数

```ruby
var = 123
p var = 456 #=> 456
```


```ruby
_v = 123
p _v = 456 #=> 456
```


#### グローバル変数
'$' で始まる識別子は グローバル変数

```ruby
$var = 123
p $var = 456 #=> 456
```


#### 定数
アルファベット大文字 [A-Z]で始まる識別子は 定数

```ruby
Var = 123
p Var = 456 #=> 警告: 定数 Var はすでに初期化されています
```


#### 日本語による表記例

```ruby
# 変数
p 変数 = "これは変数です"
p 変数 = "変数なので代入可能です"

# グローバル変数
p $変数 = "これはグローバル変数です"
p $変数 = "グローバル変数なので代入可能です"

# 定数
p S定数 = "これは定数です"
p S定数 = "定数なのでエラーが発生します"
```


### コマンドライン引数
`ARGV`

```ruby
# 本コードを「aaa.rb」として保存し、
# $ ruby aaa.rb -help -title="Hello, Ruby!" "Ruby was born in 1993."
# を実行したとき。

p ARGV #=> ["-help", "-title=Hello, Ruby!", "Ruby was born in 1993."]

ARGV.each do |_s1|
  # オプションあり
  if _s1 =~ /^-[a-z]/
    _k, _v = _s1.split("=")
    # 引数あり
    if _v
      puts "オプションあり／引数あり：#{_k} = #{_v}"
    # 引数なし
    else
      puts "オプションあり／引数なし：#{_k}"
    end
  # オプションなし
  else
    puts "オプションなし：#{_s1}"
  end
end
#=>
# オプションあり／引数なし：-help
# オプションあり／引数あり：-title = Hello, Ruby!
# オプションなし：Ruby was born in 1993.
```


### 配列
配列の作成と使用法

```ruby
# 数値と文字列が混在する配列
A1 = [1, "UPCASE", 3.14, 1, 2, [2.0, 4], "downcase"]

# 要素を取得
p A1[2]    #=> 3.14
p A1[0..2] #=> [1, "UPCASE", 3.14]
p A1[0, 2] #=> [1, "UPCASE"]

# 大文字・小文字を区別しないソート 
p A1.sort_by{|v| v.to_s.downcase}              #=> [1, 1, 2, 3.14, [2.0, 4], "downcase", "UPCASE"]
p A1.flatten.sort_by{|v| v.to_s.downcase}      #=> [1, 1, 2, 2.0, 3.14, 4, "downcase", "UPCASE"]
p A1.flatten.uniq.sort_by{|v| v.to_s.downcase} #=> [1, 2, 2.0, 3.14, 4, "downcase", "UPCASE"]
```



```ruby
# いずれも以下を出力
#   ["A", "B C", "D"]

# 文字列を配列に変換
S1 = "A  \n  B C\nD\n"
p S1.split("\n").map{|v| v.strip}

# ヒアドキュメントを配列に変換
S2 = <<EOD
	A
	B C
	D
EOD
p S2.each_line.map{|v| v.strip}

# %w記法で配列に変換
p %w(A B\ C D)

p %w(
	A
	B\ C
	D
)
```


%w記法で都道府県コードの配列を作成する例

```ruby
# [1..47] = ["北海道".."沖縄県"]（一部抜粋）
p Apref = [nil] + %w(北海道 青森県 岩手県 宮城県) #=> [nil, "北海道", "青森県", "岩手県", "宮城県"]
printf("%02d: %s\n", 4, Apref[4])                 #=> "04: 宮城県"
```


上記コードをクラス化する例（#現実世界の情報も参照のこと）

```ruby
class Pref
  def initialize()
    @aPref = [nil] + %w(北海道 青森県 岩手県 宮城県)
  end

  def explain(id = 0)
    sprintf("%02d: %s", id, @aPref[id])
  end
end

pref = Pref.new

puts pref.explain(4) #=> "04: 宮城県"
```


### ハッシュ
ハッシュの作成と使用法

```ruby
h10 = {}
  h10["water"] = "wet"
  h10["fire"]  = "hot"
h20 = {"water" => "wet", "fire" => "hot"}
h31 = {:water => "wet", :fire => "hot"}
h32 = {:"water" => "wet", :"fire" => "hot"}
h41 = {water: "wet", fire: "hot"}
h42 = {"water": "wet", "fire": "hot"}

# いずれも以下を出力
#   "hot"
p h10["fire"]
p h20["fire"]
p h31[:fire]
p h32[:"fire"]
p h41[:fire]
p h42[:"fire"]

# いずれも以下を出力
#   water: wet
#   fire: hot
h10.each { |_k, _v| print _k, ": ", _v, "\n" }
h20.each { |_k, _v| print _k, ": ", _v, "\n" }
h31.each { |_k, _v| print _k, ": ", _v, "\n" }
h32.each { |_k, _v| print _k, ": ", _v, "\n" }
h41.each { |_k, _v| print _k, ": ", _v, "\n" }
h42.each { |_k, _v| print _k, ": ", _v, "\n" }
```


### 四則演算など
*加法 +
*減法 −
*乗法 *
*除法 /
*冪乗 **

#### 数値
整数と浮動小数点数を意識して使い分ける必要がある。

```ruby
p 1 + 2   #=> 3
p 1 - 2   #=> -1
p 1 * 2   #=> 2
p 1   / 2 #=> 0   期待値は 0.5 だが？
p 1.0 / 2 #=> 0.5 期待どおり。
p 1 ** 2  #=> 1
```


#### 文字列

```ruby
p "Ru" + "by" #=> "Ruby"
```


#### 配列

```ruby
p ["Ru"] + ["by"]       #=> ["Ru", "by"]
p ["Ru", "by"] - ["Ru"] #=> ["by"]
p [1, 2, 3] * ":"       #=> "1:2:3"／[1, 2, 3].join(":") と同義
```


### 制御構造
ほかの言語でもよくみられるような制御構造を用いることができる。

#### 条件分岐
##### <code>if, case</code>

```ruby
# [Ctrl]+[C]
Signal.trap(:INT) do
  puts
  exit
end

# キー入力
print "[Y/n] ? "
p s1 = STDIN.gets.strip.upcase

print "例1-1: "
if s1 == "Y"
  puts true
elsif s1 == "N"
  puts false
else
  puts nil
end

print "例1-2: "
puts(
  if s1 == "Y"
    true
  elsif s1 == "N"
    false
  else
    nil
  end
)

print "例2:   "
puts s1 == "Y" ? true : nil

print "例3:   "
print true if s1 == "Y"
puts

print "例4:   "
puts(
  case s1
  when "Y"
    true
  when "N"
    false
  else
    nil
  end
)
```


### ブロック
ブロックは `{ ... }` または `do ... end` によって囲まれたコード列である。
一行で収まるときは `{ ... }`、複数行にまたがるときは `do ... end` が使用される。


```ruby
# { ... }
"Hello, Ruby!".split { |_s1| puts _s1 }
```



```ruby
# do ... end
"Hello, Ruby!".split do |_s1|
  puts _s1
end
```


#### <code>gsub()</code> の罠

```ruby
S1 = "ABC-ABC"

# ok
# 期待どおり => "AびC-AびC"
p S1.gsub("B", "び")

# NG
# 期待 => "AびBC-AびBC"
# 結果 => "AびC-AびC"
p S1.gsub(/(B)/, "び#{$1}")

# ok
# 期待どおり => "AびBC-AびBC"
p S1.gsub(/(B)/){ "び#{$1}" }
```


#### 繰り返し処理
##### <code>for</code>

```ruby
a1 = [1, 2, 5, 13, 21]
a2 = []
for i1 in a1
  a2 << i1 * 2
end
p a2 #=> [2, 4, 10, 26, 42]
```


##### <code>while</code>

```ruby
a1 = [1, 2, 5, 13, 21]
i1 = 0
while i1 < a1.length
  a1[i1] *= 2
  i1 += 1
end
p a1 #=> [2, 4, 10, 26, 42]
```


##### <code>each</code> メソッド

```ruby
a1 = [1, 2, 5, 13, 21]
a2 = []

a1.each { |i1| a2 << i1 * 2 }
p a1 #=> [1, 2, 5, 13, 21]
p a2 #=> [2, 4, 10, 26, 42]

a1.each.with_index(0) { |i1, i2| a1[i2] = i1 * 2 }
p a1 #=> [2, 4, 10, 26, 42]
```


##### <code>map, map!</code> メソッド

```ruby
a1 = [1, 2, 5, 13, 21]

# map
a2 = a1.map { |i1| i1 * 2 }
p a1 #=> [1, 2, 5, 13, 21]
p a2 #=> [2, 4, 10, 26, 42]

# map!
a1.map! { |i1| i1 * 2 }
p a1 #=> [2, 4, 10, 26, 42]
```


##### <code>times</code> メソッド

```ruby
a1 = [1, 2, 5, 13, 21]
a1.length.times { |i1| a1[i1] *= 2 }
p a1 #=> [2, 4, 10, 26, 42]
```


##### 指定した回数の繰り返し処理

```ruby
# 以下、いずれも "foofoofoo" を出力。
s1 = "foo"

3.times { print s1 }
puts

print (s1 * 3), "\n"
```


##### 連続する数字の繰り返し処理

```ruby
# 連続する数字の配列を作成
p (1..5).to_a #=> [1, 2, 3, 4, 5]
```



```ruby
# 断続する数字をキーにした空のハッシュを作成
hi1 = {}
[0..5, 10, 20..21, 30].each do |e1|
  if e1.class == Range
    e1.each do |i1|
      hi1[i1] = ""
    end
  else
    hi1[e1] = ""
  end
end
p hi1     #=> {0=>"", 1=>"", 2=>"", 3=>"", 4=>"", 5=>"", 10=>"", 20=>"", 21=>"", 30=>""}
p hi1[0]  #=> ""
p hi1[99] #=> nil
```



```ruby
# 上記コードをワンオフ向けに特化した例
hi1 = {}
[(0..5).to_a, 10, (20..21).to_a, 30].flatten.each do |i1|
  hi1[i1] = ""
end
p hi1 #=> {0=>"", 1=>"", 2=>"", 3=>"", 4=>"", 5=>"", 10=>"", 20=>"", 21=>"", 30=>""}
```


#### ファイルの読み書き
##### テキストファイル

```ruby
# 入力ファイル
IFn = __FILE__

# 出力ファイル
OFn = "output.txt"

s1 = ""
s2 = ""

# メモリに余裕があるなら、全行読み込んで処理。
File.read(IFn).each_line do |_s1|
  if _s1.match("全行")
    s1 << _s1
  end
end

# メモリに余裕がないときは、一行ずつ読み込んで処理。
File.open(IFn, "r") do |_fs|
  _fs.each_line do |_s2|
    if _s2.match("一行ずつ")
      s2 << _s2
    end
  end
end

# 書き込み
File.write(OFn, s1)

# 追加書き込み
File.open(OFn, "a") do |_fs|
  _fs.write s2
end

# OS判定
#   Cドライブが存在すれば Windows
#   上記以外は Unix系
Cmd = Dir.exist?("c:/") ? "type" : "cat"

puts %x(#{Cmd} #{OFn})
```


##### バイナリファイル
テキストファイルと異なるメソッド等

```ruby
File.read(...       => File.binread(...
File.open(..., "r") => File.open(..., "rb")
File.open(..., "w") => File.open(..., "wb")
File.open(..., "a") => File.open(..., "ab")

その他、マルチバイト文字を扱うときは、エンコーディングが必要になる。
```


##### URL
http経由でテキストデータを読み込む例（#例外処理、#gsub() の罠も参照のこと）

```ruby
require 'open-uri'

# URL
Url = "https://ja.wikipedia.org/w/index.php?title=Ruby&action=history&offset=&limit=5"

# 検索文字列
Search = "「Ruby」の変更履歴"

begin
  # 全行をメモリに先読みした後、一行ずつ処理する。
  URI.open(Url).read.each_line.with_index(1) do |_s1, _i1|
    # 文字列検索
    if _s1.match(Search)
      _s1.strip!
      print(
        # 行番号
        "\033[94mL#{_i1}\033[0m\t",
        # 一致した文字列を色付け表示
        _s1.gsub(Search, "\033[95m#{Search}\033[0m"),
        "\n"
      )
    end
  end
rescue => e
  p e
end
```


### 正規表現
正規表現による検索例


```ruby
# 検索対象文字列
p S1 = "12345 ABCdef　あいうえおかきくけこ"

# 検索文字列（正規表現）
p Rgx1 = /(\d{3}).*?([A-z]+).*?(あ.+お)/

# 検索実行
if S1 =~ Rgx1
  # $& で結果取得
  print "全体: ", $&, "\n"      #=> "12345 ABCdef　あいうえお"
  # $~[1..] で部分一致の配列取得
  print "部分: ", $~[1..], "\n" #=> ["123", "ABCdef", "あいうえお"]
end
```


### クラス

#### 既存クラス
既存の`String`クラスのメソッドの「書き換え」と「新規追加」を行う例

```ruby
class String
  # 既存メソッドの書き換え／危険!!
  def to_s
    self.swapcase
  end

  # 新規メソッド追加
  def foo
    self.split(//).join(" ")
  end
end

s1 = "Hello, Ruby!"
  puts s1      #=> "Hello, Ruby!"
  puts s1.to_s #=> "hELLO, rUBY!"／本来は "Hello, Ruby!" を表示
  puts s1.foo  #=> "H e l l o ,   R u b y !"
```


#### 現実世界の情報
「動物（Animal）」の「種類（breed）」と「鳴き声（bark）」をクラス化する例

```ruby
class Animal
  def initialize(breed, bark)
    @breed, @bark = breed, bark
  end

  def explain
    "#{@breed}は「#{@bark}」と鳴く。"
  end
end

#-------------------------------------------------
#（例1）定数に格納
#   静的データ限定。
#-------------------------------------------------
Dog = Animal.new("犬", "わんわん")
Cat = Animal.new("猫", "にゃー")

puts Dog.explain #=> "犬は「わんわん」と鳴く。"
puts Cat.explain #=> "猫は「にゃー」と鳴く。"

#-------------------------------------------------
#（例2）ハッシュに格納
#   動的データを扱うとき、使い勝手がよい。
#-------------------------------------------------
List1 = <<EOD
	Dog1	犬1	わんわん
	Cat1	猫1	にゃー
EOD

hAnimal = {}

List1.each_line do |_s1|
  _key, _breed, _bark = _s1.strip.split("\t")
  hAnimal[_key] = Animal.new(_breed, _bark)
end

puts hAnimal["Dog1"].explain #=> "犬1は「わんわん」と鳴く。"
puts hAnimal["Cat1"].explain #=> "猫1は「にゃー」と鳴く。"

#-------------------------------------------------
#（例3）evalで動的に生成した定数に格納
#   参考程度。
#-------------------------------------------------
List2 = <<EOD
	Dog2	犬2	わんわん
	Cat2	猫2	にゃー
EOD

List2.each_line do |_s1|
  _key, _breed, _bark = _s1.strip.split("\t")
  eval "#{_key} = Animal.new('#{_breed}', '#{_bark}')"
end

puts Dog2.explain #=> "犬2は「わんわん」と鳴く。"
puts Cat2.explain #=> "猫2は「にゃー」と鳴く。"
```


#### 仮想データ
コマンドラインインタプリタ上のカーソル操作をクラス化する例

```ruby
class Cursor
  def up(n)
    (n - 1).times { print "*\033[1D\033[1A" }
    print "*\033[1D"
    sleep 1
  end

  def down(n)
    (n - 1).times { print "*\033[1D\033[1B" }
    print "*\033[1D"
    sleep 1
  end

  def right(n)
    n.times { print "*\033[1C" }
    print "\033[2D"
    sleep 1
  end

  def left(n)
    n.times { print "*\033[3D" }
    print "\033[2C"
    sleep 1
  end
end

cursor = Cursor.new
  cursor.down(6)
  cursor.right(6)
  cursor.up(4)
  cursor.left(4)
  cursor.down(4)
puts
```


#### インスタンス変数へアクセス
クラス内のインスタンス変数 `@foo` にアクセスするための定義例
:`attr_reader` 読込メソッド
:`attr_writer` 書込メソッド
:`attr_accessor` 読込／書込メソッド


```ruby
class Gemstone
  def initialize(id = 0, name = "")
    @id, @name = id, name
  end

  # 読込メソッド生成 @id, @name
  attr_reader :id, :name
  #   def id
  #     @id
  #   end
  #   def name
  #     @name
  #   end

  # 書込メソッド生成 @name
  attr_writer :name
  #   def name=(name)
  #     @name = name
  #   end

  # 上記は、
  #   attr_reader   :id
  #   attr_accessor :name
  # とも書ける。
end

# 初期化 @id, @name
gemstone = Gemstone.new(123, "?")
  p gemstone.id   #=> 123
  p gemstone.name #=> "?"

# データ書き換え @name
gemstone.name = "Ruby"
  p gemstone.name #=> "Ruby"
```


### 例外処理
想定外のエラーが発生したとき、エラーを分別して実行を継続する。

```ruby
begin
  # 処理
rescue error_type => e
  # error_type の例外あり
  p e
rescue => e
  # 例外あり
  p e
else
  # 例外なしのとき実行
ensure
  # 必ず実行
end
```


例外なし

```ruby
# 下記を出力
#   Hello Ruby!
#   else
#   ensure
begin
  puts "Hello Ruby!"
rescue => e
  puts "rescue", e
else
  puts "else"
ensure
  puts "ensure"
end
```


例外は `raise ...` でも発火できる。

例外あり `raise "エラー"`

```ruby
# 下記を出力
#   rescue
#   エラー
#   ensure
begin
  raise "エラー"
rescue => e
  puts "rescue", e
else
  puts "else"
ensure
  puts "ensure"
end
```


例外あり `raise ArgumentError, "Argument エラー"`

```ruby
# 下記を出力
#   ArgumentError rescue
#   Argument エラー
#   ensure
begin
  raise ArgumentError, "Argument エラー"
rescue ArgumentError => e
  puts "ArgumentError rescue", e
rescue => e
  puts "rescue", e
else
  puts "else"
ensure
  puts "ensure"
end
```


### 外部コマンド等の利用
Ruby on Railsが有名になったため、Rubyを書いたことがない人は「Rubyは敷居が高い」と敬遠するかもしれないが、それは誤解である。Rubyは「小さなことを少しの努力／Doing small things with little effort」で実装できる言語の一つであり、ちょっとしたプロトタイピング開発やシェルスクリプトの代替に向いている。

「少ない労力でより多くの成果を／Do more with less」

以下、外部コマンド等（コマンド、実行ファイル、スクリプト言語）のうち、Unix系コマンドを利用したコード例を記す。

（例1）実行／成功可否（true, false）を取得。
 bool = system("...")
falseコマンドを実行

```ruby
p b1 = system("false") #=> false
if ! b1
  STDERR.puts "FALSE"  #=> "FALSE"
end
```

（例2）実行／結果を取得。
 string = %x(...)
echoコマンドを実行

```ruby
p s1 = %x(echo)       #=> "\n"
if s1.strip.length == 0
  STDERR.puts "EMPTY" #=> "EMPTY"
end
```


実行中のRubyスクリプトのソースコード各行に連番を付与

```ruby
print %x(cat #{__FILE__} | nl -ba -w1)
```


（参考）Rubyのみで実装

```ruby
File.read(__FILE__).each_line.with_index(1) do |_s1, _i1|
  print _i1, "\t", _s1
end
```


ホームディレクトリの隠しファイルを再帰抽出し、ディレクトリとファイルを配列にする例

```ruby
a1 = []

# "~/" を絶対パス "/home/foo" に変換
sAbsPath = File.expand_path("~/")

%x(find #{sAbsPath} -type f -name ".*").each_line do |_s1|
  _s1.chomp!
  # ファイル名直前の "/" 位置
  i1 = _s1.rindex("/", -1)
  a1 << [_s1[..(i1 - 1)], _s1[(i1 + 1)..]] #=>（例）["/home/foo", ".bashrc"]
end

# ディレクトリ順にソート
a1.sort.each { |_a1| print(_a1, "\n") }
```


（参考）Rubyのみで実装

```ruby
# 直感的な理解を期待し、敢えて File.basename(), File.dirname() を使用した。
a1 = []

# "~/" を絶対パス "/home/foo" に変換
sAbsPath = File.expand_path("~/")

Dir.glob("**/*", File::FNM_DOTMATCH, base: sAbsPath).each do |_fn|
  sPath = File.join(sAbsPath, _fn)
  # ファイルか？
  if FileTest.file?(sPath)
    sFn = File.basename(sPath)
    # "." で始まるファイル名か？
    if sFn[0] == "."
      a1 << [File.dirname(sPath), sFn] #=>（例）["/home/foo", ".bashrc"]
    end
  end
end

# ディレクトリ順にソート
a1.sort.each { |_a1| print(_a1, "\n") }
```


#### 並列処理
`Parallel` gem で並列処理する例

出力結果は「処理が完了する順序で異なる」ことに注意。

配列による実装例

```ruby
require 'parallel'

CmdList = ["sleep 2", "ls -la", "sleep 8"]

# Windows版Ruby3.4現在、オプション in_processes: 未対応のようなので in_threads: を使用した。
Parallel.each(CmdList, in_threads: 4) do |_cmd|
  system(_cmd.strip)
end
```


ヒアドキュメントによる実装例

```ruby
require 'parallel'

CmdList = <<EOD
	# Ruby
	ruby -e 'print "Hello, Ruby!\\n"'
	# Perl
	perl -e 'print "Hello, Perl!\\n";'
	# Python
	python3 -c "print('Hello, Python!')"
EOD

Parallel.each(CmdList.each_line, in_threads: 4) do |_cmd|
  system(_cmd.strip)
end
```


##### eval
Rubyスクリプトを動的に評価／実行するときは `eval` で実装（#例外処理も参照のこと）

```ruby
require 'parallel'

def SubEval(_sec = 0)
  sleep _sec # _sec 秒停止
  puts _sec  # _sec を表示
end

# 便宜上、ヒアドキュメントで記述します。
# 実用途では、標準入力／外部ファイルから読み込んだテキストデータを想定しています。
# 以下、意図的にエラーを混入しているので、実行して確認してみてください。
CmdList = <<EOD
	SubNoExist()
	SubEval("Ruby")
	SubEval(0)
	SubEval(10)
	SubEval(5)
	SubEval(1)
	SubEval(2)
EOD

# 入力データに100%の信用がないときは、例外処理を実装。
Parallel.each(CmdList.each_line, in_threads: 4) do |_cmd|
  _cmd.strip!
  begin
    eval(_cmd)
  rescue => e
    puts "#{_cmd} => #{e}"
  end
end
```


### フィボナッチ数
フィボナッチ数を求める例。適正なアルゴリズムを使用することで処理速度が改善される事例は多い。

```ruby
# 例えば、以下のコードが、"fib.rb"に保存されているとき、
# $ ruby ./fib.rb 10
# と実行。

def RtnFibIntr(num = 0)
  if num == 0
    return [1, 2]
  end

  if (num & 1) == 0
    numHalf = (num / 2).to_i
    iPm = ((numHalf & 1) == 0 ? 1 : -1)
    f1, l1 = RtnFibIntr(numHalf)
      l2 = (l1 * l1) - (2 * iPm)
      f2 = (f1 * l1) - iPm
  elsif (num % 8) == 7
    f1, l1 = RtnFibIntr(num + 1)
      f2 = (2 * f1) - l1
      l2 = (3 * f2) - f1
  else
    f1, l1 = RtnFibIntr(num - 1)
      f2 = (3 * f1) - l1
      l2 = (2 * f2) - f1
  end

  return [f2, l2]
end

def SubFib(num = 0)
  if num > 0
    print num, "\t", RtnFibIntr(num - 1)[0], "\n"
  end
end

def main()
  if ARGV.length > 0
    i1 = ARGV[0].to_i
    SubFib(i1)
  end
end

main()
```


### 不向きな処理
ベンチマークで使用される、以下のような素数判定コードを実行したとき、処理速度が著しく低下することがある。

```ruby
# 一応、ガーベージコレクトを禁止しておく。
GC.disable

i1 = 1000000
while i1 <= 1010000
  i2 = i1 - 1
  i3 = 2
  while i3 <= i1
    if (i1 % i3) == 0
      break
    elsif i3 == i2
      puts i1.to_s
      break
    end
    i3 += 1
  end
  i1 += 1
end
```


（参考）上記コードをC言語で記述した例（#外部コマンド等の利用も参照のこと）。

```c
// 本コードを「aaa.c」として保存したとき、
// コンパイル例
//   $ gcc ./aaa.c -o ./aaa.exe
// 実行例
//   $ ./aaa.exe

#include <stdio.h>

int main()
{
  unsigned int i1 = 1000000;
  while(i1 <= 1010000)
  {
    unsigned int i2 = i1 - 1;
    unsigned int i3 = 2;
    while(i3 <= i1)
    {
      if((i1 % i3) == 0)
      {
        break;
      }
      else if(i3 == i2)
      {
        printf("%u\n", i1);
        break;
      }
      i3 += 1;
    }
    i1 += 1;
  }
  return 0;
}
```


## Rubyの周辺技術

*ActiveScriptRuby - WindowsのActiveX環境でRubyインタプリタを呼び出す（Internet Explorer限定だがHTMLに埋め込んでクライアント上で動かすスクリプト言語としてRubyを指定できるようになる）
*Apollo - Delphiを扱えるようにする（初稿: 2004-10-16）
*dRuby - 分散オブジェクト
*DXRuby - DirectXを使用するための拡張ライブラリ
*eRuby - HTMLにRubyスクリプトの埋め込みを可能にする
*Exerb - RubyスクリプトをWindowsの実行ファイルに変換
*homebrew - macOSパッケージ管理システム
*HotRuby - JavaScriptやAdobe Flash上で動くRuby処理系 
*mod_ruby - CGIより高速なApache HTTP Serverのモジュール
*Opal - RubyスクリプトをJavaScriptへ変換するコンパイラ
*Rake - ビルドツール
*RD - Rubyスクリプトに埋め込む文書形式
*RDE - 統合開発環境（最終版: 2002-10-14）
*RSpec - ビヘイビア駆動開発のためのフレームワーク
*RubyGems - パッケージ管理システム
*Ruby on Rails - Webアプリケーションフレームワーク
*Ruby/SDL - SDLライブラリを扱えるようにする
*RWiki - RDを採用したウィキ
*Smalruby - ScratchのRuby対応版（Rubyソースを生成するScratch）とでも言うべきGUI型IDE
*YARV - 正式な処理系として採用（Ruby1.9.0以降）
*WIN32OLE - Win32APIやCOMコンポーネントを呼び出すためのライブラリ

## Rubyで開発されたアプリケーション
*Chef - 構成管理ツール
*Hiki - ウィキソフトウェア
*mikutter - Twitterクライアント
*Phusion Passenger - Apache HTTP Server／nginx用モジュール
*Puppet - 構成管理ツール
*qwikWeb - メーリングリストとWikiの長所を合わせたようなシステム
*Ruby on Rails - Webアプリケーションフレームワーク
**Basecamp - Webベースのプロジェクト管理ツール
**GitHub - ソフトウェア開発プラットフォーム
**Metasploit - コンピュータセキュリティに関するプロジェクト
**Redmine - Webベースのプロジェクト管理ソフトウェア
*Serverspec - サーバの実状をテストするツール
*tDiary - Web日記
*Vagrant - 仮想マシンを構築するためのソフトウェア
*WEBrick - Webサーバの機能を提供するライブラリ
*影舞 - Webベースのバグ管理システム

## Rubyを組み込んだアプリケーション
*RPGツクールXP
*RPGツクールVX
:RPGツクールXP（2004年）とRPGツクールVX（2007年）に、Rubyをツクール専用にカスタマイズしたRGSSを搭載した。これにより、戦闘システム等を一から構築できた。

## エピソード
### ブロック構造構文の選択理由
Ruby ではブロック構造を `end` で終える構文が採用されているが、Matzは他の構文が採用される可能性があったことを述べている。当時、Emacs 上で `end` で終える構文をオートインデントさせた例はあまりなく、Ruby 言語用の編集モードにオートインデント機能を持たせられるかどうかが問題になっていたためである。実際には数日の試行でオートインデント可能であることがわかり、現在の構文になった。C言語のような`{ ... }`を使った構文も検討されていたが、結局これは採用されなかった。

### Matzが書いたコードの割合
「Quora (2020年9月8日)」より抜粋し補足。 

### Matzとゆかりのある地域
* 静岡県浜松市 - 日本タイムシェア株式会社（現：TIS）に勤務していた1993年、開発開始。
* 愛知県名古屋市 - 株式会社トヨタケーラム（現：トヨタシステムズ）在籍時の1995年、オープンソースソフトウェアとして公開。
* 島根県松江市 - 1997年、島根県松江市へ移住。同市に本社を置くネットワーク応用通信研究所フェローとして普及に尽力。

## 言語間競争とRuby
;Python に満足していれば Ruby は生まれなかった

;Ruby on Rails が Python ではなく Ruby で作られた理由 - 開発者のハンソンがRubyに恋をしたから

;「Rubyは死んだ」のか? 検索ワード頻度では分からない Ruby の生産性やビジネス上の価値
「Ruby Business Users Conference 2018 Winter」(2018年12月14日)より抜粋。

どのプログラミング言語が最もよく使われているかを判断することは難しい。

## 注釈

## 出典

## 参考文献

* - プログラム未経験者向けの入門書。
**
**
**
**
**
*
**
**
**
**
*
*
*

## 関連項目

*Goby - Rubyに影響を受け、Goで実装したオブジェクト指向インタプリタ言語。Rubyの構文、実装、ライブラリ等と互換性はない。

## 外部リンク

*Ruby 公式ウェブサイト
*Ruby のリリース一覧
*Ruby リファレンスマニュアル
*Ruby Association
*JISC 日本産業標準調査会 - JISX3017 プログラム言語Ｒｕｂｙ