トップQs
タイムライン
チャット
視点

Ruby

オブジェクト指向プログラミング言語 ウィキペディアから

Remove ads

Ruby(ルビー)は、まつもとゆきひろ(通称: Matz)により開発された、簡潔な文法が特徴的なオブジェクト指向スクリプト言語[3]

概要 パラダイム, 登場時期 ...

カテゴリ / テンプレート

日本で開発されたプログラミング言語としては初めて国際電気標準会議(IEC)で国際規格に認証された事例となった[4][5]

Remove ads

概要

Rubyは、1993年2月24日に生まれ、1995年12月にfj上で発表された。6月の誕生石Pearl(真珠)と同じ発音をするプログラミング言語 Perlに続くという意味で、7月の誕生石Ruby(ルビー)から名付けられた[6]

文字列・数値等すべてのデータをオブジェクトとして扱うオブジェクト指向プログラミング言語である。

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

2011年3月22日に、JIS規格「JIS X 3017」が制定され、その後2012年4月1日に、日本発のプログラミング言語では初めて、ISO/IEC規格「ISO/IEC 30170」に承認された。

2025年9月現在、言語仕様は明文化されていない[注釈 1]

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

Remove ads

設計思想

要約
視点

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

Ruby には Perl や Python とは決定的に違う点があり、それこそが Ruby の存在価値なのです。それは「楽しさ」です。私の知る限り、Ruby ほど「楽しさ」について焦点を当てている言語は他にありません。Ruby は純粋に楽しみのために設計され、言語を作る人、使う人、学ぶ人すべてが楽しめることを目的としています。しかし、ただ単に楽しいだけではありません。Ruby は実用性も十分です。実用性がなければ楽しめないではありませんか。まつもとゆきひろ、Ruby プログラミング入門 まえがき 監修者よりのページ

Matzは『まつもとゆきひろ コードの世界 スーパー・プログラマになる14の思考法』でもRubyの開発理由を次のように述べている。

「なぜRubyを開発したのか」。そのように問われるときに、もっとも適切な答えは、Linux開発者であるリーナス・トーバルズの言葉と同じではないかと思います。『それがぼくには楽しかったからまつもとゆきひろ コードの世界 スーパー・プログラマになる14の思考法 P.9

クラス名はアルファベットの大文字から始めるという制約があり、日本語などの非ASCII文字のみでクラス名を定義する方法がない。この件についてMatzは以下のように語っており、英語を共通言語として使うべきであるという立場を表明している[7]

2文字目以降は自由なので、もしどうしても日本語が使いたいのであれば、少々不自然にも見えますが、先頭だけ大文字の接頭辞をつけるのはどうでしょうか。しかし、私個人としては、日本語の変数名などを使うことは、そのプログラムを読む人の範囲を日本語が読める人に限定してしまうことになるので、ひどくもったいないのではないかと感じています。そこで、この点を積極的に改善する気にはなれないのです。

静的型について、Matzは「(基本設計思想である動的型付けを維持し)静的型付けを導入しない」意思を改めて示した[8]

Rubyと同様のスクリプト言語(インタープリタ型言語)であるPythonPHPPerlでは静的型を導入しており、Rubyも型を導入するべきでは、と長年言われてきました。しかしまつもとさんは「Rubyに型を取り入れたくない(DRYではないから⁠[注釈 2])⁠」⁠、「⁠型宣言することはコンピュータに使われているような気になる」と述べ、Rubyでは静的型は導入しない方針を示しました。

その代わり、静的解析を導入し、型チェックを行えるようにすることを明らかにしました。(中略)静的解析に期待してほしい、とまつもとさんは述べました。

静的解析は、Ruby 3.0.0[注釈 3] から実装された。

MINASWANMatzがniceだから俺らもniceでいよう」[9]

そしてRuby(中略)コミュニティを表現した標語に"MINASWAN"というものがあると紹介しました。これは"Matz is nice so we are nice"の略で、もめごとがあっても「matzがniceだから俺らもniceでいよう」と、なだめることが海外のメーリングリストではよく見られるそうです。(中略)今ではスローガンにまで昇華しています。(中略)日本のRubyコミュニティにこの特質を逆輸入したいと考え、講演の最初に取り上げたと述べました。

Remove ads

実装

公式

MRI

MRI(Matz Ruby Interpreter)あるいは、CRubyC言語で書かれていることに由来する)と呼ばれる。Matzが開発を始めた実装であり最も広く使われている。(狭義として)#YARVに更新される以前(1.8.x以前)のバージョンを指すこともある。

YARV

YARVは、1.9で採用された#MRIのevalをバイトコードで実行するタイプに置き換えたもの。(狭義の)MRIはソースコードを構文木にコンパイルした後、構文木を解釈する仮想機械であるevalで実行するインタプリタであるが、YARVはソースコードをバイトコードにコンパイルした後、バイトコードを解釈する仮想機械であるevalで実行するインタプリタである。Javaなどのバイトコードとは違い、このバイトコードはファイルとしては生成されない(ファイルとして静的に外部化することを考慮した設計では基本的になく、シンボルを多用するなどしている)。なお「YARV」は、もともとは開発中におけるその仮想機械の名前だった。

その他

JRuby

JRubyは、JavaによるRuby実装である(プラットフォーム非依存の利用が可能)。ほとんどのRubyクラスが組み込みで提供されている。インタプリタ実行時コンパイラ事前コンパイラの3種類が用意されている。事前コンパイラでは、Javaバイトコードへ変換しJRubyが無くても他のJavaプラットフォーム上で動作させることが可能となる。

IronRuby

IronRubyは、.NET FrameworkによるRuby実装であり、.NET Frameworkのライブラリと連携させることができる。JIT方式のバイトコードインタプリタ。共通言語基盤に準拠した実装(Monoなど)で動作するため、プラットフォーム非依存の利用も可能(ただし、ソースコードが.NET Frameworkのライブラリに依存している場合、Monoでの動作は不可能)。

MacRuby

MacRubyは、macOSのRuby実装。Cocoaを含む様々なフレームワークとの連携が可能。RubyCocoaの問題点を解決するために開発されている。

Rubinius

Rubiniusは、仮想機械でRubyを実行するJIT方式のバイトコードインタプリタ。大部分がRubyで実装されている。

MagLev

MagLevは、Smalltalk 仮想機械のRuby実装 MagLev

mruby

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

仮想機械

Parrot

Parrotで動作させるための実装なども開発されている。

コード例

要約
視点

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

基本的なコード

文字列・数値等すべてのデータがオブジェクトである。

p -199.abs                                       #=> 199
p "ruby is cool".length                          #=> 12
p "Rick".index("c")                              #=> 2
p "Nice Day Isn't It?".split(//).uniq.sort.join  #=> " '?DINaceinsty"

変数と定数

ローカル変数

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

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 はすでに初期化されています

コレクション

コレクションに関する例

配列

配列の作成と使用法

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.split("\n").map{|_v| _v.strip}

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

p %w(
	A
	B\ C
	D
)
# %w記法で都道府県コードの配列を作成する例
# [1..47] = ["北海道".."沖縄県"](一部抜粋)
p A1 = [nil] + %w(北海道 青森県 岩手県 宮城県) #=> [nil, "北海道", "青森県", "岩手県", "宮城県"]
print 4, ": ", A1[4], "\n"                     #=> "4: 宮城県"

ハッシュ

ハッシュの作成と使用法

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" }

制御構造

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

条件分岐

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=>""}

ファイルの読み書き

テキストファイル
a1 = []
a2 = []

# (例1-1) メモリに余裕があるなら、全行読み込んで、配列にした方が扱いやすい。
aText = File.read(__FILE__).split("\n").map{|_s1| _s1.chomp}
aText.each do |_s1|
  a1 << _s1 if _s1.match("全行")
end

# (例1-2) メモリに余裕がないときは、1行ずつ読み込んで処理。
File.open(__FILE__, "r") do |_fs|
  _fs.each_line do |_s1|
    _s1.chomp!
    a2 << _s1 if _s1.match("1行ずつ")
  end
end

s1 = a1.join("\n") + "\n"
s2 = a2.join("\n") + "\n"

# (例2-1) output.txt に書き込む
File.write("output.txt", s1)

# (例2-2) output.txt に追記する
File.open("output.txt", "a") do |_fs|
  _fs.write s2
end

puts %x(cat output.txt)
=begin
  Windows:
    puts %x(type output.txt)
  後述「外部コマンド等の利用」に %x() の説明あり
=end
バイナリファイル

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

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

クロージャ

クロージャとなるようなブロックの引数渡し

# オブジェクトのインスタンス変数(変数名の頭に@が付く)でブロックを記憶。
def remember(&p)
  @block = p
end

# nameを受け取るブロックを引数に、上記のメソッドを呼び出す。
remember{|name| puts "Hello, #{name}!"}

# 後に必要になった時点でクロージャを呼び出す。
@block.call("Ruby") #=> "Hello, Ruby!"

メソッドからクロージャを返す例

def create_set_and_get(value = 0)
  return proc{|x| value = x}, proc{value}
end

setter, getter = create_set_and_get
p setter.call(21) #=> 21
p getter.call     #=> 21

正規表現

正規表現による検索例

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

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

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

クラス

次のコードはPersonという名前のクラスである。その中、まずinitializeはオブジェクトを初期化するコンストラクタである。ほかに2つのメソッドがあり、1つは比較演算子である<=>オーバーライドしておりArray#sortによりプロパティageでソートすることができる。もう1つのオーバーライド箇所のto_sメソッドは Kernel#puts での表示の形式を整える。attr_readerは Ruby におけるメタプログラミングの例であり、attr はインスタンス変数の入出力を司る、いわゆる値を取得する getter メソッドや値を設定する setter メソッド(アクセサ)を定義する。attr_readergetter メソッドのみの定義である。なおメソッド中では最後に評価された式が返り値となり、明示的なreturnは省略できる。

class Person
  def initialize(name, age)
    @name, @age = name, age
  end

  def <=>(person)
    @age <=> person.age
  end

  def to_s
    "#{@name} (#{@age})"
  end

  attr_reader :name, :age
end

group = [ Person.new("John", 20),
          Person.new("Markus", 63),
          Person.new("Ash", 16)
        ]

puts group.sort.reverse

結果は3つの名前が年の大きい順に表示される。

Markus (63)
John (20)
Ash (16)

例外処理

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

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

不向きな処理

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

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

外部コマンド等の利用

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 で並列処理する例

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

配列による実装例

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.split("\n"), in_threads: 4) do |_cmd|
  system(_cmd.strip)
end

(参考) 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.split("\n"), in_threads: 4) do |_cmd|
  _cmd.strip!
  begin
    eval(_cmd)
  rescue => e
    puts "#{_cmd} => #{e}"
  end
end

フィボナッチ数

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

# 例えば、以下のコードが、"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()
Remove ads

Rubyの周辺技術

  • 分散オブジェクトを実現する dRuby
  • Ruby スクリプトに埋め込むことができる文書形式RD
  • Ruby によるRDを採用したウィキRWiki
  • Ruby からSDLライブラリを扱えるようにするRuby/SDL
  • Ruby から Delphi を扱えるようにする Apollo
  • Ruby によるウェブアプリケーションフレームワーク Ruby on Rails
  • Ruby の処理系の一つでRuby1.9以後の処理系として採用されている YARV
  • Ruby の統合開発環境 RDE
  • Ruby のコードを Windows の実行形式ファイルに変換する Exerb
  • Ruby 用のライブラリ管理システムである RubyGems
  • Apache HTTP Server に組み込むための mod ruby
  • サーバサイドでHTMLへの埋め込み Ruby 文を実現する eRuby
  • Ruby のコードをJavaScriptへ変換するコンパイラ Opal[注釈 4]
  • Microsoft WindowsActiveX 環境で Ruby インタープリターを呼び出す ActiveScriptRubyInternet Explorer 限定だがHTMLに埋めこんでクライアント上で動かすスクリプト言語として Rubyを指定できるようになる)
  • Ruby から Win32APICOMコンポーネントを呼び出すためのライブラリー WIN32OLE
  • JavaScript や Flash 上で動く Ruby の処理系 HotRuby
  • Ruby によるビヘイビア駆動開発のためのフレームワーク RSpec
  • Ruby で書かれたビルドツール Rake
  • Ruby で書かれたmacOS パッケージ管理システム homebrew
  • Ruby からDirectXを使用するための拡張ライブラリ DXRuby
  • Ruby プログラミングを視覚的直感的に開発可能とする、Scratch (プログラミング言語)のRuby対応版(Rubyソースを生成するScratchとも言えるもの)とでも言うべきGUI型IDE Smalruby
Remove ads

Rubyで開発されたアプリケーション

[要出典]

Rubyを組み込んだアプリケーション

RPGツクールXP・RPGツクールVX
株式会社エンターブレインから発売されているRPG制作ソフトシリーズのうち、RPGツクールXPRPGツクールVXでは、Ruby をツクール専用にカスタマイズした RGSSを搭載している。同シリーズの従来ソフトではあらかじめ用意された機能しか使えなかったが、RGSSにより戦闘などのシステムを一から構築する事が出来るようになった。
RPGツクールMVからは開発言語がJavaScriptに変更になった。

エピソード

ブロック構造構文の選択理由

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

ゆかりのある地域

Rubyは日本の国産言語として知られており、特にRubyとゆかりのある次の地域は "Rubyの聖地" と呼ばれている。

Matzが書いたコードの割合

当初は当然、Matzが書いたコードばかりだったが、2010年前後に主要開発者の立場からは外れ、10年ほど経過した2020年9月8日現在では、RubyのCコード509,802行のうち、Matzがコミットしたのは36,437行で1割以下という状況になっていた[15]Matzは「意外と多いなという印象です」と語った[15]。一方、Matzがプログラマーとして関わっているmrubyについて同様の方法で測定したところ、67,068行中、25,049行で、しかもmrubyでは他に代理コミットしてもらったものもあるので、「それを加えると32,653行で、約半分ってところですかね」とのことであった[15]

Remove ads

言語間競争とRuby

要約
視点
Python に満足していれば Ruby は生まれなかった

(1993年頃)PerlPython(0.9x?)は、Matzが理想とするオブジェクト指向モデルを実現するに至っていなかった。[16]
matz[注釈 6]がPythonに満足していればRubyは生まれなかったであろう」[17]

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

デイヴィッド・ハイネマイヤー・ハンソンが(2004年頃)Ruby on Railsを構築するのにPython(2.x?)を選ばなかった理由として「私の場合は、恋に落ちたのがRubyなのです。私はRubyに恋をしていますし、もう14年間もそうなのです。(中略)『最適なツール』などというものは存在しないのです。あなたの脳をちょうどいい具合に刺激するパズルがあるだけなのです。今日では、ほぼなんでも作ることができます。そして、それを使って、さらに何でも作れてしまうのです。これは素晴らしいことです。表現や言語、そして思考の多様性に乾杯しましょう!」と質問サイトのQuoraで本人が回答している[15]

「Rubyは死んだ」のか? 検索ワード頻度では分からない Ruby の生産性やビジネス上の価値

「Ruby Business Users Conference 2018 Winter」(2018年12月14日)より抜粋[18]

RubyとかRuby on Railsだと、簡単なWebアプリケーションをすぐ作ったり、あるいは、さまざまなジャンルで実際の適用例があるので、なにか困ったとき同じ問題に直面した人を探せたり、あるいはその問題を解決するRubyGemsを見つけられる。そういう点でいうと、トータルの生産性はかなり高いことがあるんですね。 なので、テクノロジーとしては、2010年代にどんどん新しく出てきた言語が持ってるあの機能がないとかこの機能がないとか、そういうカタログスペック上の欠点があるように思えても、トータルの生産性あるいは効率のよさを考えると、Ruby on Railsのビジネス上の価値は、実はそんなに下がっていないと思うんです。 先ほどのTIOBE Indexみたいなランキングは、技術者が新しいことを学ぶときに探すところで順位がついているので、ホットなトピックというんですか、新しく出てきて話題になっているものが上に来がちなんですよね。 だから、実際に仕事として、あるいは自分のプロダクトを作るときに、どんな言語を選択してどういうふうに開発したらいいのかを考えると、Rubyの持っているビジネス上の価値はそんなに下がっていないと思います。たとえ順位が下がって、表面上Rubyの人気が凋落したように見えても、ある意味「まだまだ大丈夫」が1つの見識だと思います。

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

注釈

  1. 「ISO/IEC 30170」による厳密な言語仕様はない。2010年6月以降、言語仕様をテストするRubySpecという外部ライブラリの開発が行われていたが、Ruby 2.2.0リリース直後の2014年12月31日、開発が突然終了された。Ruby 2.2.0が「RubySpecのテストをパスしない」等、MRI側によるRubySpec軽視が一因とされている。【悲報】Ruby開発者が使わないので「RubySpec」開発終了”. 2025年9月16日閲覧。
  2. DRYは「Don't Repeat Yourself/同じことを繰り返さない」の意。Rubyのデータ型(オブジェクト)は、動的に型変換し再利用される(同じことを繰り返す)存在であって、静的に固定型で利用される(同じことを繰り返さない)存在ではない。
  3. Matzは1988年に Emacs に触れて以来、Emacsを使い続けている[11]
  4. 原文のママ。リファレンスマニュアル2.1.0ではmatz、3.4ではMatz(2025年8月現在)。
  5. TIOBE社はオランダにある会社で、同じオランダ出身のグイド・ヴァンロッサムが生みの親であるPythonは上位にランキングしている(2025年6月現在)。
Remove ads

出典

参考文献

関連項目

外部リンク

Loading related searches...

Wikiwand - on

Seamless Wikipedia browsing. On steroids.

Remove ads