変数、定数、予約語、演算子関係
組み込み定数
ARGV | 起動時の引数 argument vector |
ARGF | 仮想ファイルを表すオブジェクト |
ENV | 環境変数 |
STDIN | 標準入力 |
STDOUT | 標準出力 |
STDERR | 標準エラー出力 |
DATA | __END__ 以降をgetsできたりする |
環境変数
RUBYOPT
コマンドライン起動時のオプションを指定しておける
コマンドライン起動時のオプション
ruby [オプション] -- ファイル名 [ARGV]
-c 文法チェック
$ ruby -c temp1.rb
Syntax OK
-e ワンライナー
$ ruby -e "p 2 ** 10"
1024
-W0 -W1 -W2(W) 冗長出力モード 右ほど冗長 -w1がデフォルト
-I(アイ) $LOAD_PATH 追加
$ ruby -I . temp1.rb
-r スクリプト実行前に指定されたファイルを実行する
$ ruby -r ./temp2.rb temp1.rb
-d デバックモード
# 現在の値を確認
$ echo $RUBYOPT
# cはダメっぽい そりゃそうだ
$ export RUBYOPT=-c
$ ruby temp1.rb
ruby: invalid switch in RUBYOPT: -c (RuntimeError)
RUBYLIB ライブラリ検索パス
# 現在の値を確認
$ echo $RUBYLIB
$ export RUBYLIB=/the/path/you/
$ ruby temp1.rb
特殊変数
頭が$
$: | $LOAD_PATH |
$* | ARGV |
$_ | 最後にgetsかreadlineで読み込んだ文字列 |
$~[n] | 最後に成功したマッチに対する結果 |
$` | マッチした部分より前の文字列 |
$& | マッチした部分 |
$’ | マッチした部分より後の文字列 |
$+ | マッチした最後のキャプチャ |
$1, $2.. | マッチしたn番目のキャプチャ |
$? | 最後に終了した子プロセス |
$! | 直近で補足した例外オブジェクト |
$@ | バックトレース |
$0 | 実行中のプログラムファイル名 |
ローカル変数
- /\A[a-z][a-zA-Z0-9_]*\z/
- 代入が行われた位置から、その代入を含む(ブロック定義, メソッド定義、クラス定義)の終わりまでがスコープ
- つまりメソッド外で定義されたローカル変数はメソッド内から参照できない。定義内は独立したスコープを持ち、相互に参照できない
- 同じスコープ内において、参照箇所より前に(実行の有無にかかわらず)代入文が記述してある時にはnil、記述してない場合は例外発生
グローバル変数
- /\A$[a-zA-Z0-9_]*\z/
- どこからでも参照可能!
- 初回の参照からいきなりnil
- ぶっちゃけ使わない 使うな
インスタンス変数
- /\A@@[a-zA-Z0-9_]*\z/
- そのインスタンス内で値を保持する
- メソッドのように探索されない。そのインスタンス内で完結し生成元クラスも継承チェーンも関係ない
- 初期化されていなくてもnilを返す
クラス変数
- /\A@@[a-zA-Z0-9_]*\z/
- そのクラスのインスタンス、サブクラス、サブクラスのインスタンスから参照できる
- 初期化していないのに参照すると例外発生
class Moko1
@@v1 = 1
def v1
@@v1
end
def v1=(value)
@@v1 = value
end
end
class Moko2 < Moko1
end
moko1 = Moko1.new
moko1.v1
=> 1
moko2 = Moko2.new
moko2.v1
=> 1
moko2.v1 = 100
moko1.v1 = 100
=> 100
- 継承するクラスで同盟のクラス変数を定義してしまったら、スーパークラスのクラス変数を書き換える、と言うこと
- サブクラスとスーパークラスで別々の値が保持されると判断しがちなので注意
class Moko1
@@v1 = 1
def v1
@@v1
end
end
class Moko2 < Moko1
@@v1 = 2
end
moko1 = Moko1.new
moko1.v1
=> 2
moko2 = Moko2.new
moko2.v1
=> 2
定数
- /\A[A-Z][a-zA-Z0-9_]*\z/
- 定義された(クラス, モジュール)内から参照可能
- その内部で定義された(クラス, モジュール)内から参照可能
- その(クラス, モジュール)を継承、インクルードしたモジュール内から参照可能
- (クラス, モジュール)名で修飾すれば外部からも参照可能
- 初期化していないのに参照すると例外発生
- 再定義しようとすると警告は出るがエラーにはならない
- モジュールやクラスの継承チェーンを駆け上がり探索される
再定義時の警告
A = 1
=> 1
A = 2
warning: already initialized constant A
warning: previous definition of A was here
=> 2
メソッドは複数回実行が前提なので定数の初期化、更新は許されていない
def moko
A = 3
end
#=> SyntaxError: (irb): dynamic constant assignment
- 再定義が警告になるのであって、値を変更するのは定数の知ったことではない。
- 下記の例では、定数は自分が指している文字列オブジェクトを返した。その時点で定数の仕事は終わりであり、その文字列オブジェクトの自己破壊メソッドが呼ばれたかどうかは定数が関知することではない
HAGE = 'abcde'
=> "abcde"
HAGE.upcase!
=> "ABCDE"
HAGE
=> "ABCDE"
重要なので何度でも言うぞ
- Rubyインタプリタは初出の変数への代入式を検出し
- たとえその行が実行されなくとも
- 代入式より右に記述してある内容の解釈よりも先に変数をnilにて用意する
moko
NameError: undefined local variable or method 'moko'
if false
moko = 1
end
moko
#=> nil
> hage
NameError: undefined local variable or method 'hage'
> hage.to_s
NameError: undefined local variable or method 'hage'
> hage = hage.to_s
#=> ""
疑似変数
- 厳密にはtrueやfalseはリテラルではない
- 疑似変数には代入できない
true | TrueClassクラスの唯一のインスタンス |
false | FalseClassクラスの唯一のインスタンス |
nil | NilClassクラスの唯一のインスタンス |
self | 現在のオブジェクト |
__FILE__ | 現在実行しているプログラムファイル名 $0とは微妙に違ったりする |
__LINE__ | 現在実行しているプログラムの行番号 |
__ENCODING__ | 現在のソースファイルのエンコーディング |
演算子
- プログラミングの利便性の為に、一部のメソッド呼び出しと制御構造は演算子の形式で記述できます。それを演算子と呼ぶ
- 殆どの演算子はメソッド呼び出しだが、一部は言語に組み込まれていて再定義できない
演算子の優先順位
- メモ
- ~ 単体は殆ど見ないけど、ビット演算の否定とか、/xxx/ =~ $_ の省略として ~ /xxx/ と明記するとかなんとか
:: | |||||
[] | |||||
+(単項) | ! | ~ | |||
** | |||||
-(単項) | |||||
* | / | % | |||
+ | - | ||||
<< | >> | ||||
& | |||||
| | ^ | ||||
> | >= | < | <= | ||
<=> | == | === | != | =~ | !~ |
&& | |||||
|| | |||||
.. | … | ||||
?:(条件演算子) | |||||
=(+=, -= …) | |||||
not | |||||
and | or |
再定義できる演算子
- メソッドとして定義すれば、演算子の形式で呼び出せるもの
- 違う言い方をすれば、こんな感じにメソッドとして定義すれば、こんな感じに演算子の形式で呼び出せるようになるもの
| | ^ | & | |||
<=> | == | === | =~ | ||
> | >= | < | <= | ||
<< | >> | ||||
+ | - | * | / | % | ** |
~ | +@ | -@ | |||
[] | []= | ||||
` | ! | != | !~ |
二項演算子
obj + other
def +(other)
end
単項プラス/マイナス
+obj
def +@
end
要素代入
obj.foo = value
def foo=(value)
end
[]
obj[key]
def [](key)
end
obj[key] = value
def []=(key, value)
end
obj[key, key2] = value
def []=(key, key2, value)
end
バッククォート記法
arg
または %x(arg)
def `(arg)
end
再定義できない演算子
- メソッドとして定義しても、演算子の形式で呼び出せないもの
- つまり and or not はグローバル変数、クラス変数、インスタンス変数には使える
- また、def の後やメソッド呼び出しの ピリオドの後などメソッド名であるとはっきり分かる場所ではメソッド名として使えたりする
:: | スコープ演算子 | ||||||||||||
= | 代入演算子 | ||||||||||||
? : | 条件演算子 | ||||||||||||
.. | ... | 範囲演算子 | |||||||||||
&& | || | and | or | not | 論理演算子 | ||||||||
+= | -= | *= | /= | %= | **= | &= | |= | ^= | <<= | >>= | &&= | ||= | 自己代入演算子 |
@or = 1
=> 1
@or += 1
=> 2
def and(n)
n * 2
end
p self.and('homo')
"homohomo"
=> "homohomo"
p self.and 'homo'
"homohomo"
=> "homohomo"
p self and 'homo'
main
=> "homo"
予約語
- クラス名、変数名などに使えない
- でも、グローバル変数、クラス変数、インスタンス変数には使える
- また、def の後やメソッド呼び出しの ピリオドの後などメソッド名であるとはっきり分かる場所ではメソッド名として使えたりする
BEGIN | class | ensure | nil | self | when |
END | def | false | not | super | while |
alias | defined? | for | or | then | yield |
and | do | if | redo | true | __LINE__ |
begin | else | in | rescue | undef | __FILE__ |
break | elsif | module | retry | unless | __ENCODING__ |
case | end | next | return | until |
defメソッドなんてのも作れる
def def(n)
p n * 2
end
self.def('homo')
=> "homohomo"
UFO演算子
1, 0, -1 を返すんだよね?でも、右辺、左辺どっちが大きい時に1を返すのか覚えてる?
2 <=> 1 #=> 1
1 <=> 1 #=> 0
1 <=> 2 #=> -1
左辺が大きい | 1 |
一緒 | 0 |
右辺が大きい | -1 |
左から順番に 1, 0, -1 もう覚えるしかない!