ハロの外部記憶インターフェイス

そろそろ覚える努力が必要かも…

文法

変数の種類

  1. ローカル変数:英数字と_
  2. グローバル変数: $で始まる
  3. クラス変数: @@で始まる
  4. インスタンス変数: @で始まる
  5. 定数: 大文字で始まる

Rubyリテラル

数値、論理値、文字列、シンボル、ハッシュ、配列、範囲、正規表現、コマンド出力

数字表現

2進数:0b10 => 2
8進数:0o10 => 8
10進数:0d10 => 10
16進数:0x10 => 16

リテラルでは「_」は無視される

文字コードを返す「?」演算子

?後に文字を指定すると文字コードを返す

?\C-v #Ctrl+vの文字コード
?\M-a #Alt+aの文字コード
?\n   #改行コード

ローカル変数

変数はクラス内部の変数でもメソッドとは違うスコープになる

v1 = 1   #Objectクラスの変数
$v2 = 2
class Qux1
  p v1  #エラー
  p $v2   #2
  v2 = 2    #Qux1クラスの変数
  def method1; v1; end  #エラー:Objectの変数への接近が出来ない
  def method2; v2; end  #1エラー:Qux1の変数への接近は出来ない
end
  1. グローバル変数はどこからでも呼べる

インスタンス変数

インスタンス内部での変数、継承されず、自分のインスタンス内部でのみ存在する

@v1 = 1
class Qux1
  @v2 = 2
  def method1; @v1; end
  def method2; @v2; end
end

Qux1.new.method1  # nil
Qux1.new.method2  # nil
  1. @v1はObjectクラスのインスタンス変数であるため、Qux1クラスの@v1はnil状態
  2. @v2はQux1のインスタンス変数だが、初期化されてないためnilのまま
  3. initializeで値を初期化するかアクセッサを設定擦る必要がある

アクセッサ

attr_reader : getterメソッドを生成する
attr_writer : setterメソッドを生成する
attr_accessor : getterとsetterメソッドを生成する
attr : getterメソッドを生成する v1.9以降非推奨

def v3   #getterメソッド
  return @v3
end 
def v3=(value)  #setterメソッド
  @v3 = value
end

アクセッサ

class Qux1
  attr_accessor :v3
end

クラス変数

インスタンス変数とは違い継承されサブクラスでも参照出来る
クラス変数はクラス定義時にコードが実行されるため、初期化メソッドの中に初期化しなくても初期化される

class Qux
  @@v2 = 1
  def v2; @@v2; end
  def v2=(value); @@v2 = value; end
end
class QuxExt < Qux
end
Qux.new.v2   #1
QuxExt.new.v2   #1
QuxExt.new.v2 = 2  #2  このタイミングで全ての値が変わる
Qux.new.v2   #2
QuxExt.new.v2   #2

定数

大文字で始まる変数、2回目の設定は警告を発するが、値は更新される
※メソッドは複数回実行が前提であるため、定数の定義は出来ない

ネストした定数

class M
  A = 1
  class B
    A = 2
  end
  def method1
    p A       # 1
    p B::A   # 2
    p self::A  #エラー
    p M::B::A  #2
  end
end
M.new.method1
1
2
2
  1. MのAとMのBのAは違い定数
  2. B::A =2 とも同じ

constants

M.constants   #["B", "A"]
M::B.constants  #["A"]

定数の参照
定数はモジュールや継承チェーンを辿り、定数を探して値を返す

module M
   A = 1
   class B ; A = 2; end
end
class C
  include M
  p A
  p B::A
end
  1. モジュールのAを探して表示

const_missingメソッド

module M
  def self.const_missing(id)
    1
  end
end
  1. 定数が見つからない場合、1を返す

演算子

「<=>」UFO演算子

100 <=> 10   # 1
100 <=> 100  # 0
100 <=> 101  # -1

「+=」演算子

a = a + 2   # a + 2
a += 2      # a + 2

「**」演算子

a**= 2   # a^2

オブジェクトのクラス名

全てのオブジェクトはクラスである
数字でもクラスであり、全てクラスのインスタンスになる

1.class  -> Fixnum
1.class.superclass   -> Integer
1.class.superclass.superclass  -> Numeric

全ての演算子はそのクラスに定義されたメソッドになる

加算の場合は1クラスの+メソッドを実行しているに過ぎない

1.+(2)   # 3
1 + 2   # 3
  1. 「1」クラスの「+」メソッドは引数の値と合算した結果を返す

演算子は再定義可能であるが、例外として出来ないものもある

::,=,?:,..,...,&&,and,||,!,not

「&&」 演算子

  1. 左の式の結果がTrueの場合のみ右の結果を確認する
  2. 左と右が両方Trueの場合、右の値を返す
  3. 左がTrueで右がFalseの場合、右の値を返す
  4. 左がFalseの場合、右はチェックしないため、左の値を返す

「||」演算子は左の結果がTrueの場合、左の値を返す

左がFalseの場合、右の値を判定しTrueの場合、右の値を返す

論理演算子nilとfalse以外はTrueと認識する

「and」「or」「not」 演算子

他の演算子より優先順位が低いので注意

p 1 and 2   #結果1が出力される
p (1 and 2) #結果2が出力される

メソッド定義

  1. defで定義する。
  2. 引数には「()」を付けても付けなくても結構
  3. 最後の式がreturn扱いになる
  4. 明確にreturnを記述しても同じ

デフォルト値の指定

def foo(a, b=100)
end
  1. 引数bは未設定の場合、100になる

Boolの値は基本Falseとnil以外はTrueとみなされる

1     #true
2     #true
False #false
nil   #false
a     #true

条件分岐

if i = 1 then
elsif i=2
end
  1. 1行目のthenは省略可能

擬似変数

変数の様に使用するが、変数として新しい値が生成されるわけではなく唯一インスタンスを設定する

true trueclassのインスタンス
false falseclassのインスタンス
nil nilclassのインスタンス
self 現在のオブジェクト
__FILE__ 現在実行中のファイル名
__LINE__ 現在実行しているプログラムの行数
__ENCODING__ 現在のソースのエンコーディング(Ruby1.9)

展開式

「""」の内部には#{}で展開式が記述出来る
「''」の内部は全て文字列として表現される。展開式不可

a = "abc"
p "#{a}"   #"abc"
p '#{a}'   #"#{a}"

値変換メソッド

変換不可文字は無視される

"12.aa".to_i   # 12
"23.2.1".to_f  # 23.2
"a33".to_i     # 0
  1. to_s 文字列へ変換
  2. to_i Integerへ変換
  3. to_f Floatへ変換

エスケープ文字「\」

\x xを文字として表示
\n 改行
\r キャリッジリターン
\f 改ページ
\a ベル
\e エスケープ
\s 空白
\nnn 8進数表記  "\101"  => 8進数 結果"A"
\xnn 16進数表記  "\x41"  => 16進数  結果"A"
\C-x
\M^x
\M-\C-x

「p」「puts」「print」の違い

実際の印刷状態を観るためにはpでは無くputsやprintを使うこと
pはデバッグ用として関連情報を表示する

p "a\nb"      # "a\nb"
print "a\nb"  # "a"  改行後 "b"
puts "a\nb"   # "a"  改行後 "b" 改行

ヒアドキュメント

複数行を自然体で入力する場合使用する
前後に同じ文字列を指定する下記は「ABC」

前後に同じ文字列

a = <<ABC
  this is 
  a book
ABC

-文字列

前に「-」をつけると、閉じる部分の前に空白を設定できる

a=<<-ABC
  this is
  a book
  ABC

「""」で囲む

リテラルの""で包まれているのと同じ効果,#式展開などが利用できる

str = "DEF"
a = <<"ABC"
  this is
  a book #{str}
ABC

「''」で囲む

リテラルの''で包まれているのと同じ効果

a = <<'ABC'
  this is
  a book
ABC
  1. 3種類の表現方法が存在する
  2. 全て結果は" this is\n a book\n"となる

「%」パーセント記法

a = %*test*   # "test"
a = %*test"*  # "\"test\""

「*」の代わりに(),[],{}が指定出来る

a= 1
a = %q!#{ a+1}!  # "#{a+1}
a = %Q!#{a + 1}! # "2"

「%」記法

%s シンボル
%W 要素がダブルクォート文字列となる配列、要素の区切りは空白文字
%w 様相がシングルクォート文字列となる配列、要素の区切りは空白文字
%x コマンド出力
%r 正規表現

+ 文字列を連結する
*n 文字列をn回繰り返す
<, >, ==, <=> 文字列を文字コードとして数字比較結果を返す

length 文字列の長さ
size バイト長さ

sprintf フォーマット指定

sprintf("result %#b", 16)  # "result 0b10000"
sprintf("result %#o", 16)  # "result 020"
sprintf("result %#x", 16)  # "result 0x10"
sprintf("result %#X", 16)  # "result 0X10"
sprintf("result %02d", 1)  # "result 01"
sprintf("result %03d", 1)  # "result 001"
sprintf("result %05.2f", 1.111)  # "result 01.11"

シンボルリテラル

文字列の先頭に「:」を付加する

a = :"foo1"   => :foo1
  1. クォートは省略可能
 a = %s!foo1!   => :foo1

結果はシンボルクラスのインスタンスとなる
String.to_sym シンボルへ変換

※String文字列は常に新しいオブジェクトを生成する
インスタンスはobject_idで区分が出来る
但し、シンボルは新しいオブジェクトを生成しない
シンボルはメモリ節約やスピード向上に役たつがgcの対象外で有るため、使うときは慎重に擦る必要がある

破壊的メソッド

「!」が付いているメソッドの中では引数の元値も変えるものがある
例chopとchop!

v1 = "foo1"
v1.chop   => "foo"
v1    => "foo1"
v1.chop!  => "foo"
v1   => "foo"

配列

v1 = $w(hoge foo bar)  => v1 = ["hoge", "foo", "bar"]
v1.join() => "hogefoobar"
v1.join("_") => "hoge_foo_bar"

a = Array.new(5)   => [nil, nil, nil, nil, nil]
a.length => 5
Array.new(2){|index| index + 10}  => [10, 11]

初期値指定

a = Array.new(2, "a")   => ["a", "a"]

※a[0]とa[1]は同じオブジェクト
なので、a[0].replace("b") => ["b", "b"]になってしまう

同じオブジェクトにならないようにするため

a = Array.new(2){"a"}  => ["a", "a"]
a[0]とa[1]は別のオブジェクトとなる
a[0].replace("b")   => ["b", "a"]

サイズを超える配列を求めるとnilを返す

v1 = {"a", "b"]
v1.length  => 2
v1[2]   => nil

v1[4] = "c"   => ["a", "b", nil, nil, "c"]
v1.length = 5

式による代入

a = [0, 1, 2,, 3]
a[1,2] = "a", "b"     <- []は省略可能
#a配列の1番目から2個までを指定し置換している
a   => [0, "a", "b", 3]
a[1,2] = "c"
#a配列の1番目から2個目までを"c"にする
a  => [0, "c", 3]
a[1,1] = 4,5,6
#a配列の1番目の値に4,5,6挿入する
a   => [0, 4,5,6,3]   
#間に挿入される

多重代入

a, b, c = 1,2
#=> a =1, b = 2, c =nil

a, b = 1,2,3
#=> a = 1, b= 2   3番目は無視される

a, *b = 1,2,3,4,5
# 「*」が付いてる変数は残りを全て配列で取得する
#=> a = 1, b = [2,3,4,5]

配列の演算

a = [1,1,2,2]
b = [2,2,3,4]

a & b  # [2]
a | b  # [1,2,3]
  1. 「&」 両方に存在するものを返す
  2. 「|」 共通に存在するものを返す
a + b  # [1,1,2,2,2,2,3,4]
a - b  # [1,1]

演算子

[1,2] * 3         # [12,12,12]
[1,2,3] * "-"     # "1-2-3"
[1,2,3].join("-") # "1-2-3"

for文

for <識別子> in <式> do
end

list = [1,2,3]
for item in list do
   p item
end

forは内部スコープが適用されない

for i in [1,2,3]
  aa = 1
end

aa # 1

eachメソッド

[2,3,4].each do
    bar = 1
end
p bar   #=> 例外が発生
  1. eachメソッドはスコープを発生させる

Hash

両側を「”」で囲む

a = { "foo1" = 1, "foo2" = 2, "foo3" =3}
a["foo2"]   #=> 2

キーは文字列を使う場合、シンボルを使う方が高速で効率

a = Hash.[:foo1. 1. :foo2, 2, :foo3, 3]

ハッシュのデフォルト値

a = Hash.new(5)
a[:foo]   #=> 5   
  1. Hashのデフォルト値を指定
  2. Hashが追加されているわけではなくnilの代わりにデフォルト値が返される

最後の引数をHashで設定する

def foo(a,b,c)
  p c
end

foo(1,2, {:foo1=>1, :foo2=>2})
foo(1,2, :foo1=>1, :foo2=>2)
  1. 最後の引数の場合のみ可能
  2. {}は省力が可能

範囲

1 .. 10  #=> 1から10まで
1 ... 10 #=> 1から9まで

include? と === で含まれているかを確認出来る

(1..5).include?(3)  #=> true
(1..5) == 3 #=> false
(1..5) === 3 #=> true
for i in "a".."z"
end

a="abcdef"
a[1]  #=> 98
a[1..1]  #=> "b"
a[1..2]  #=> "bc"
a[1...2]  #=> "b"

case式

case <式>
when <条件式1> [then]
when <条件式2> [then]
else
end

case 7
when 1...5 then; p 1    #= (1...5) === 7 を評価
when 5..10 then; p 2   #= (5..10) === 7 を評価
end

while式

条件がTrueの間繰り返される

while <条件式> do
end

無条件で1回は実行された後Trueの場合、繰り返される

begin
  i += 1
end while(1..4) === i

begin..endを省略可能

i += 1 while(0..4) === i

until式

条件がTrueになるまで繰り返される

until <条件式> do
end

正規表現

「/」で囲まれた文字列、もしくは「%r」で指定された文字列

/Ruby/
%r(Ruby)
Regexp.new "Ruby"

「=~」マッチしている場所を返す

/Ruby/ =~ "I love Ruby"  #=> 7

マッチした文字列は「$&」で取得

戦後の文字列は「$`,$'」を使用する

/bb/ =~ "aabbcc"
$`   #=> "aa"
$&   #=> "bb"
$'  #=> "cc"

^<式> 式で始まる

<式>$ 式で終わる

reg = /^(aa|bb)c$/
reg === "aac"  #=> true
reg === "bbc"  #=> true
reg === "abc"  #=> false

[<式>] 式の何れが来る

reg = /a[bcd]e[fg]h/
reg === "abegh"  #=> true
reg === "aefh"  #=> false

[<開始値>-<終了値>]

始値から終了値を含む

/a[1-5]z/  === "a2z"   #=> true
  1. 1から5を含む

正規表現記号

. 改行をのぞく任意の1文字。ただし、後述するmオプションが指定された場合は改行もマッチ
\d 数字
\D 数字以外の文字
\w 英数字とアンダースコア
\W 英数字とアンダースコア以外の文字
\s 空白文字(\t, \n, \r, \f)
\S 空白以外の文字
\A 先頭の文字。改行の有無に影響されない
\z 末尾の文字。改行の有無に影響されない
\Z 末尾の文字。改行で終わっていればその改行の直前にマッチ

/a\db/ === "a2b"  #=> true

繰り返し文字の判定

* 直前の文字の0回以上の繰り返し
+ 直前の文字の1回以上の繰り返し
{m} 直前の文字のm回繰り返し
{m,} 直前の文字の最低m回繰り返し
{m,n} 直前の文字の最低m回、最高n回の繰り返し

/a*b/  === "aab"
/a+b/  === "aaab"
/a{2}b/  === "aab"
/a{2,}b/  === "aaaab"
/a{2,3}b/  == "aaab"

()によりグループ化が可能

/a(bc)*d/  === "abcbcd"

$n 正規表現でマッチした値とグループ値を返す

%r|(http://www(\.)(.*)/| =~ "http://www.xyz.org/"
p $1 #=> "http://www.xyz.org/"
p $2 #=> "."   wwwの次の任意文字(\.)
p $3 #=> "xyz.org"   (.*) 任意文字の繰り返し
p $4 #=> nil   対応なし
  1. $0はスクリプト名を返す

正規表現のオプション

i 大文字と小文字を区別しない
o 一度だけ式展開を行う
x パターン中の空白と改行を無視する、また#以降をコメントとして無視する
m 正規表現記号「.」が改行にもマッチする(複数行モード)

/ruby/ === "RUBY"  #=> false
/ruby/i === "RUBY"  #=> true
/a.*b/  === "a\nb"  #=> false
/a.*b/m  === "a\nb"  #=> true

コマンド出力

「`」で囲まれた文字列はコマンド命令と認識される

puts `date`

終了ステータス参照は「$?」を利用する

1.8.7-p376 :062 > puts `date`
Tue Aug  5 22:06:10 JST 2014
 => nil 
1.8.7-p376 :063 > $?
 => #<Process::Status: pid=22231,exited(0)> 

コマンド出力は""の内部と同様に式展開、バックスラッシュ記法。パーセント記法が適用される

a = "date"
puts `#{a}`
puts %x|date|

ブロック

do - end や{} の中はブロックとなり、スコープが発生する
関数の内部のyieldはブロックが代入される

def func y
  y + yield
end
x = 2
func(1) { x+= 2}  #= 5
p x #= 4

yieldに引数が有る場合は|で囲んだ内部にコンマ区切りで設定する

def func(a ,b)
  a + yield(2, b)
end
p func(1,2) { |x, y| x+y}  #= 5
  1. yieldの引数2,bが |x, y|に代入されている

block_given?

ブロックが指定されたかを関数内部で判断する

def func
  return 1 if block_given?
2
end

func()  #= 2
func(){} #= 1

Proc

ブロックをオブジェクト化する
callメソッドで実行する

p = Proc.new{|x| p x}
p.call(1)  #= 1

Procをブロックとして渡す

def func x
  x + yield
end
p = Proc.new {2}
func(1, %p)   #= 3
  1. 引数に渡す場合は「&」を付けて渡す
def func x, &proc
  x + proc.call
end
func(1) do 
2
end

lambda

lmd = lambda{|x| p x}
lmd.call(1) #= 1

procとlambdaの違い

procは処理後、呼び元に戻らず処理を終了する
lambdaは処理後、呼び元に戻り、次に処理を行う

procの例

def func
  proc = Proc.new {return1 }
  proc.call
 p 2  #<= ここは処理されずに終わる
end

lambdaの例

def func
  lmb = lambda{ return 1}
  lmb.call
 p 2  #<= ここも実行される
end

procでは引数が足りない場合nilを返すが、lambdaではエラーとなる

p1 = Proc.new {|x,y| y}
p1.call(1)  #= nil
l1 = lambda{ |x,y| y}
l1.call(1) #<= エラーとなる

each

値の繰り返し

[1,2,3].each do |value|
 p value
end

each_with_index

インデックスが必要な場合

[1,2,3].each_with_index do |value, index|
 p value + index
end

Hashのeach

{:a => 1, :b => 2}.each do |key, value|
 p "#{key}:#{value}"
end

Hashのキーのみの繰り返し

{:a => 1, :b => 2}.each_key do |key|
 p key
end

範囲のeach

("a".."z").each do |value|
 p value
end

upto

順に値を増やしていく

2.upto(4) do |i|
 p i
end
  1. 2から4まで+1していく