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月現在、言語仕様は明文化されていない「ISO/IEC 30170」による厳密な言語仕様はない。2010年6月以降、言語仕様をテストするRubySpecという外部ライブラリの開発が行われていたが、Ruby 2.2.0リリース直後の2014年12月31日、開発が突然終了された。Ruby 2.2.0が「RubySpecのテストをパスしない」等、MRI側によるRubySpec軽視が一因とされている。。

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

クラス、ガベージコレクション、例外処理、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系コマンドを利用できない環境では正常に動作しないことがある。なお、ウィキブックスには、より多くの基本的なコード例が記載されている。

基本的なコード
すべてのデータがオブジェクト
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

p "3322211".split(//).uniq.sort.join #=> "123"

おまじない
ヘッダ情報の付与
#!/usr/bin/env ruby
#coding:utf-8

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

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

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

変数と定数
ローカル変数
小文字 または '_' で始まる識別子は ローカル変数
var = 123
p var = 456 #=> 456
_v = 123
p _v = 456 #=> 456

グローバル変数
'$' で始まる識別子は グローバル変数
$var = 123
p $var = 456 #=> 456

定数
アルファベット大文字 [A-Z]で始まる識別子は 定数
Var = 123
p Var = 456 #=> 警告: 定数 Var はすでに初期化されています

コマンドライン引数
ARGV
# 本コードを「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 "[Y] #{_k} = #{_v}"
    else
      puts "[N] #{_k}"
    end
  else
    puts "[*] #{_s1}"
  end
end
#=>
# [N] -help
# [Y] -title = Hello, Ruby!
# [*] Ruby was born in 1993.

コレクション
コレクションに関する例

配列
配列の作成と使用法
a1 = [1, "hi", 3.14, 1, 2, [4, 5]]

p a1[2]    #=> 3.14
p a1[0..2] #=> [1, "hi", 3.14]
p a1[0, 2] #=> [1, "hi"]

p a1.reverse              #=> [[4, 5], 2, 1, 3.14, "hi", 1]
p a1.reverse.flatten      #=> [4, 5, 2, 1, 3.14, "hi", 1]
p a1.reverse.flatten.uniq #=> [4, 5, 2, 1, 3.14, "hi"]

# いずれも以下を出力
#   ["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記法で都道府県コードの配列を作成する例
# [1..47] = ["北海道".."沖縄県"]（一部抜粋）
p Apref = [nil] + %w(北海道 青森県 岩手県 宮城県) #=> [nil, "北海道", "青森県", "岩手県", "宮城県"]
printf("%02d: %s\n", 4, Apref[4])                 #=> "04: 宮城県"

上記コードをクラス化する例（#現実世界の情報も参照のこと）
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: 宮城県"

ハッシュ
ハッシュの作成と使用法
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" }

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

数値
整数と浮動小数点数を意識して使い分ける必要がある。
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

文字列
p "Ru" + "by" #=> "Ruby"

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

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

条件分岐
if, case
# [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 が使用される。

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

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

gsub() の罠
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}" }

繰り返し処理
for
a1 = [1, 2, 5, 13, 21]
a2 = []
for i1 in a1
  a2 << i1 * 2
end
p a2 #=> [2, 4, 10, 26, 42]

while
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]

each メソッド
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]

map, map! メソッド
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]

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

指定した回数の繰り返し処理
# 以下、いずれも "foofoofoo" を出力。
s1 = "foo"

3.times { print s1 }
puts

print (s1 * 3), "\n"

連続する数字の繰り返し処理
# 連続する数字の配列を作成
p (1..5).to_a #=> [1, 2, 3, 4, 5]

# 断続する数字をキーにした空のハッシュを作成
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

# 上記コードをワンオフ向けに特化した例
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=>""}

ファイルの読み書き
テキストファイル
# 入力ファイル
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})

バイナリファイル
テキストファイルと異なるメソッド等
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() の罠も参照のこと）
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

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

# 検索対象文字列
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クラスのメソッドの「書き換え」と「新規追加」を行う例
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）」をクラス化する例
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は「にゃー」と鳴く。"

仮想データ
コマンドラインインタプリタ上のカーソル操作をクラス化する例
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

例外処理
想定外のエラーが発生したとき、エラーを分別して実行を継続する。
begin
  # 処理
rescue error_type => e
  # error_type の例外あり
  p e
rescue => e
  # 例外あり
  p e
else
  # 例外なしのとき実行
ensure
  # 必ず実行
end

例外なし
# 下記を出力
#   Hello Ruby!
#   else
#   ensure
begin
  puts "Hello Ruby!"
rescue => e
  puts "rescue", e
else
  puts "else"
ensure
  puts "ensure"
end

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

例外あり raise "エラー"
# 下記を出力
#   rescue
#   エラー
#   ensure
begin
  raise "エラー"
rescue => e
  puts "rescue", e
else
  puts "else"
ensure
  puts "ensure"
end

例外あり raise ArgumentError, "Argument エラー"
# 下記を出力
#   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コマンドを実行
p b1 = system("false") #=> false
if ! b1
  STDERR.puts "FALSE"  #=> "FALSE"
end
（例2）実行／結果を取得。
 string = %x(...)
echoコマンドを実行
p s1 = %x(echo)       #=> "\n"
if s1.strip.length == 0
  STDERR.puts "EMPTY" #=> "EMPTY"
end

実行中のRubyスクリプトのソースコード各行に連番を付与
print %x(cat #{__FILE__} | nl -ba -w1)

（参考）Rubyのみで実装
File.read(__FILE__).each_line.with_index(1) do |_s1, _i1|
  print _i1, "\t", _s1
end

ホームディレクトリの隠しファイルを再帰抽出し、ディレクトリとファイルを配列にする例
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のみで実装
# 直感的な理解を期待し、敢えて 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インストールは、コマンドラインから「gem install parallel」を実行。 で並列処理する例

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

配列による実装例
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

ヒアドキュメントによる実装例
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 で実装（#例外処理も参照のこと）
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

フィボナッチ数
フィボナッチ数を求める例。適正なアルゴリズムを使用することで処理速度が改善される事例は多い。
# 例えば、以下のコードが、"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()

不向きな処理
ベンチマークテストで使用される以下のようなコードを実行したとき、処理速度が著しく低下することがある。
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言語で記述した例（#外部コマンド等の利用も参照のこと）。
// 本コードを「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で開発されたアプリケーション 

tDiary
影舞
Hiki
Chef
Vagrant
Ruby on Rails
GitHub
Metasploit
Redmine
Basecamp

qwikWeb - メーリングリストとWikiの長所を合わせたようなシステム
WEBrick

Phusion Passenger
Puppet
mikutter
Serverspec - サーバーの状態、設定などのテストを自動化するツール。

 Rubyを組み込んだアプリケーション 
RPGツクールXP
RPGツクールVX
RPGツクールXP（2004年）とRPGツクールVX（2007年）に、Rubyをツクール専用にカスタマイズしたRGSSを搭載した。これにより、戦闘システム等を一から構築できたRPGツクールMV（2015年）では、開発言語がRubyからJavaScriptに変更されている。。

 エピソード 
 ブロック構造構文の選択理由 
Ruby ではブロック構造を end で終える構文が採用されているが、Matzは他の構文が採用される可能性があったことを述べている。当時、Emacs 上で end で終える構文をオートインデントさせた例はあまりなく、Ruby 言語用の編集モードにオートインデント機能を持たせられるかどうかが問題になっていたためである。実際には数日の試行でオートインデント可能であることがわかり、現在の構文になった。C言語のような{ ... }を使った構文も検討されていたが、結局これは採用されなかったまつもとゆきひろ 「探訪 Ruby 第6回」『Linux Magazine』56号、株式会社アスキー、2004年。。

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

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

 言語間競争と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 プログラム言語Ｒｕｂｙ

Category:オブジェクト指向言語
Category:オープンソースソフトウェア
Category:スクリプト言語
*
Category:1995年のソフトウェア
Category:Cでプログラムされた自由ソフトウェア
Category:日本の発明