この項目では、プログラミング言語について説明しています。「ルビー」・「ルビ」の他の使い方については「ルビー (曖昧さ回避) 」をご覧ください。
Ruby (ルビー)は、まつもとゆきひろ (通称: Matz)により開発された、簡潔な文法が特徴 的なオブジェクト指向 スクリプト言語 [ 3] 。
日本で開発されたプログラミング言語としては初めて国際電気標準会議(IEC) で国際規格に認証された事例となった[ 4] 。
概要
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とのデュアルライセンス で頒布されている。
設計思想
Matz は「Rubyの言語仕様策定において最も重視しているのはストレスなくプログラミング を楽しむことである (enjoy programming )」と述べている。
Ruby には Perl や Python とは決定的に違う点があり、それこそが Ruby の存在価値なのです。それは「楽しさ」です。私の知る限り、Ruby ほど「楽しさ」について焦点を当てている言語は他にありません。Ruby は純粋に楽しみのために設計され、言語を作る人、使う人、学ぶ人すべてが楽しめることを目的としています。しかし、ただ単に楽しいだけではありません。Ruby は実用性も十分です。実用性がなければ楽しめないではありませんか。 — まつもとゆきひろ、Ruby プログラミング入門 まえがき 監修者よりのページ
Matz は『まつもとゆきひろ コードの世界 スーパー・プログラマになる14の思考法』でもRubyの開発理由を次のように述べている。
クラス名はアルファベットの大文字から始めるという制約があり、日本語などの非ASCII文字のみでクラス名を定義する方法がない。この件についてMatz は以下のように語っており、英語を共通言語として使うべきであるという立場を表明している[ 7] 。
2文字目以降は自由なので、もしどうしても日本語が使いたいのであれば、少々不自然にも見えますが、先頭だけ大文字の接頭辞をつけるのはどうでしょうか。しかし、私個人としては、日本語の変数名などを使うことは、そのプログラムを読む人の範囲を日本語が読める人に限定してしまうことになるので、ひどくもったいないのではないかと感じています。そこで、この点を積極的に改善する気にはなれないのです。
静的型について、Matz は「(基本設計思想である動的型付け を維持し)静的型付け を導入しない」意思を改めて示した[ 8] 。
Rubyと同様のスクリプト言語(インタープリタ型言語)であるPython 、PHP 、Perl では静的型を導入しており、Rubyも型を導入するべきでは、と長年言われてきました。しかしまつもと さんは「Rubyに型を取り入れたくない(DRYではないから[ 注釈 2] )」、「型宣言することはコンピュータに使われているような気になる」と述べ、Rubyでは静的型は導入しない方針を示しました。
その代わり、静的解析を導入し、型チェックを行えるようにすることを明らかにしました。(中略)静的解析に期待してほしい、とまつもと さんは述べました。
静的解析は、Ruby 3.0.0[ 注釈 3] から実装された。
MINASWAN 「Matz がniceだから俺らもniceでいよう」[ 9]
そしてRuby(中略)コミュニティを表現した標語に"MINASWAN"というものがあると紹介しました。これは"Matz is nice so we are nice"の略で、もめごとがあっても「matzがniceだから俺らもniceでいよう」と、なだめることが海外のメーリングリストではよく見られるそうです。(中略)今ではスローガンにまで昇華しています。(中略)日本のRubyコミュニティにこの特質を逆輸入したいと考え、講演の最初に取り上げたと述べました。
実装
公式な実装
Rubyの公式な実装には、以下の二種類が存在する。
MRI (Matz' Ruby Implementation)
Matz によって開発されはじめたC言語による実装であり、最も広く使われている。狭義として、evalを中心とした部分が次で述べるYARVに更新される以前(1.8.x以前)のバージョンを指して言うこともある。JRuby などに対して CRuby と呼ばれることもある。また、JRuby などに対して、広義として YARV 以降も含んで言うこともある。
YARV
1.9で採用された、MRIのevalをバイトコードを実行するタイプに置き換えたもの。(狭義の)MRIはソースコードを構文木にコンパイルした後、構文木を解釈する仮想機械であるevalで実行するインタプリタであるが、YARVはソースコードをバイトコードにコンパイルした後、バイトコードを解釈する仮想機械であるevalで実行するインタプリタである。Java などのバイトコードとは違い、このバイトコードはファイルとしては生成されない(ファイルとして静的に外部化することを考慮した設計では基本的になく、シンボルを多用するなどしている)。なお「YARV」は、もともとは開発中におけるその仮想機械の名前だった。
その他の実装
JRuby
Java 言語による実装。純粋な Java で行われているため、プラットフォーム非依存の利用が可能。ほとんどの Ruby クラスが組み込みで提供されている。インタープリタ・実行時コンパイラ ・事前コンパイラ の3種類が用意されている。事前コンパイラでは、Java バイトコードへ変換し、JRuby が無くても他の Java プラットフォーム上で動作させることが可能となる。
IronRuby
.NET Framework 上で Ruby を動作させる実装であり、.NET Framework のライブラリと連携させることができる。JIT方式 のバイトコードインタプリタ。共通言語基盤 に準拠した実装(Mono など)で動作するため、プラットフォーム非依存の利用も可能(ただし、ソースコードが .NET Framework のライブラリに依存している場合は Mono での動作は不可能)。
MacRuby (英語版 )
macOS 上で動作する Ruby 実装。Cocoa を含む様々なフレームワークとの連携が可能。RubyCocoa の問題点を解決するために開発されている。
Rubinius (英語版 )
仮想機械 上で Ruby を実行するJIT方式 のバイトコードインタプリタ。大部分が Ruby で実装されている。
MagLev (英語版 )
smalltalk 仮想マシン上で動作する実装 MagLev 。
mruby
組み込みシステム 向けの軽量版。家電製品 の他、スマートフォン 、ゲーム などでの使用を想定している。
その他
Parrot 上で Ruby を動作させるための実装なども開発されている。
コード例
ウィキブックス には、より多くの基本的なコード例 が記載されています[ 注釈 4] 。
基本的なコード
文字列・数値等すべてのデータがオブジェクトである。
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 \n D \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: 宮城県"
ハッシュ の作成と使用法
h1 = {}
h1 [ "water" ] = "wet"
h1 [ "fire" ] = "hot"
h2 = { "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 h1 [ "fire" ]
p h2 [ "fire" ]
p h31 [ :fire ]
p h32 [ :"fire" ]
p h41 [ :fire ]
p h42 [ :"fire" ]
# いずれも以下を出力
# water: wet
# fire: hot
h1 . each { | _k , _v | print _k , ": " , _v , " \n " }
h2 . 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
# 以下、いずれも "ya" を出力。
S1 = "fablic" #=> length = 6
if S1 . length > 3
puts "ya"
else
puts "nop"
end
puts (
if S1 . length > 3
"ya"
else
"nop"
end
)
puts S1 . length > 3 ? "ya" : "nop"
puts "ya" if S1 . length > 3
puts (
case S1 . length
when .. 3
"nop"
else
"ya"
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" )
その他、マルチバイト文字を扱うときは、エンコーディングが必要になる。
クロージャ
クロージャ となるようなブロックの引数渡し
# オブジェクトのインスタンス変数(変数名の頭に@が付く)でブロックを記憶。
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
クラス
次のコードはPerson
という名前のクラスである。その中、まずinitialize
はオブジェクトを初期化するコンストラクタである。ほかに2つのメソッドがあり、1つは比較演算子である<=>
をオーバーライド しておりArray#sort
によりプロパティage
でソートすることができる。もう1つのオーバーライド箇所のto_s
メソッドは Kernel#puts
での表示の形式を整える。attr_reader
は Ruby におけるメタプログラミング の例であり、attr
はインスタンス変数の入出力を司る、いわゆる値を取得する getter
メソッドや値を設定する setter
メソッド(アクセサ )を定義する。attr_reader
は getter
メソッドのみの定義である。なおメソッド中では最後に評価された式が返り値となり、明示的な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 ()
Rubyの周辺技術
Rubyで開発されたアプリケーション
[要出典 ]
Rubyを組み込んだアプリケーション
RPGツクールXP・RPGツクールVX
株式会社エンターブレインから発売されているRPG制作ソフトシリーズのうち、RPGツクールXP とRPGツクールVX では、Ruby をツクール専用にカスタマイズした RGSS を搭載している。同シリーズの従来ソフトではあらかじめ用意された機能しか使えなかったが、RGSSにより戦闘などのシステムを一から構築する事が出来るようになった。
RPGツクールMV からは開発言語がJavaScriptに変更になった。
エピソード
ブロック構造構文の選択理由
Ruby ではブロック構造を end
で終える構文が採用されているが、Matz は他の構文が採用される可能性があったことを述べている。当時、Emacs 上で end
で終える構文をオートインデントさせた例はあまりなく、Ruby 言語用の編集モードにオートインデント機能を持たせられるかどうかが問題になっていたためである[ 注釈 6] 。実際には数日の試行でオートインデント可能であることがわかり、現在の構文になった。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] 。
言語間競争とRuby
Python に満足していれば Ruby は生まれなかった
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つの見識だと思います。
どのプログラミング言語が最もよく使われているかを判断することは難しい。 [ 注釈 8]
注釈
^ 「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日閲覧。
^ DRYは「D on't R epeat Y ourself/同じことを繰り返さない」の意。Rubyのデータ型(オブジェクト)は、動的に型変換し再利用される(同じことを繰り返す)存在であって、静的に固定型で利用される(同じことを繰り返さない)存在ではない。
^ Ruby 3.0.0 リリース
^ Ruby - Wikibooks
^ Opal: Ruby ♥︎ JavaScript
^ Matz は1988年に Emacs に触れて以来、Emacsを使い続けている[ 11] 。
^ 原文のママ。リファレンスマニュアル2.1.0ではmatz 、3.4ではMatz (2025年8月現在)。
^ TIOBE社はオランダにある会社で、同じオランダ出身のグイド・ヴァンロッサム が生みの親であるPythonは上位にランキングしている(2025年6月現在)。
出典
参考文献
関連項目
外部リンク
ウィキメディア・コモンズには、
Ruby に関連するカテゴリがあります。
ウィキブックスに
Ruby 関連の解説書・教科書があります。
低水準言語 高水準言語
1950年代 1960年代 1970年代 1980年代 1990年代 2000年代 2010年代
架空の言語