ruby wayのSymbols


1 symbolsの概要
rubyのsymbolはSymbolクラスの例であり、彼の文法は簡単なコロンの後ろに声明がついている.
1つのsymbolは文字列のようなものですが、文字列とは異なり、symbolごとに1つのインスタンスしかありません.例を挙げてみましょう
array = ["foo", "foo", "foo", :foo, :foo, :foo]

この例では文字列「foo」はメモリに3つの異なるオブジェクトとして格納され、fooは1つのオブジェクトとして格納され、複数の参照にすぎない.
ruby 1.6以前のバージョンでは、symbolはfirst-classのオブジェクトではなく、Fixnumに渡されてから格納されていました.現在のバージョンでは、symbolは数値として表され、格納されます.この数字はto_iを手に入れる.
ここでsymbolと彼の名前の間には一つ一つ対応する関係があり、私たちは彼を他のものを操作するように操作しています.
Symbolがよく使用する場所は、クラス内の変数に読み書き方法を追加したい場合など、変数またはメソッドを表すことです.
class SomeClass
  attr_accessor :whatever
end

彼は次のコードと等価です.
class SomeClass
  def whatever
    @whatever
  end
  def whatever=(val)
    @whatever = val
  end
end

ここではstringではなくsymbolを使う理由を聞くかもしれません.実はここは一つの習慣です.ほとんどsymbolを使う場所は文字列で代用できます.
symbolは文字列のようなもので、symbolは可変文字列だと多くの人が言っています.この観点は非常に間違っている.SymbolはStringクラスから何も受け継いでいないからだ.多くの典型的なオペレータは文字列にのみ使用でき、symbolには使用できません.
もう一つの誤解はsymbolsが彼の識別子に直接連絡できることであり、多くの人がthe symbol tableについて議論している.しかし、symbolsは内部にtableがあるにもかかわらず、そのテーブルは外部プログラムにとって見えないので、アクセスできません.
symbolsは識別子のように見える必要はありません.

sym1 = :"This is a symbol"
sym2 = :"This is, too!"
sym3 = :")(*&^%$"            # and even this

symbolsを使用してインスタンス変数とメソッドを定義する場合はsend and instance_などの使用が必要です.variable_getのような方法で彼らを操作します.この場合、文字列を使用することはお勧めしません.
2列挙としてsymbol
pascalやcのような言語は列挙タイプを提供している.ルビーには本当の意味でのこれはありません.私はsymbolsを使ってこれをシミュレートすることができますか?
North, South, East, West = :north, :south, :east, :west

ここではstringも使えますが、symbolは変数が1つしかないので、symbolを選ぶのが合理的です.
3 symbolはMetavaluesとして
リターンコードの代わりに異常を使用することが多い.エラー時の戻り値(nilなど)としては、asc文字NULが文字ではないとみなされ、cに空のポインタがあり、pascalにもnilポインタがあり、rubyにもnilがあります.
しかし問題が来て、rubyの中でnilは1つの本当の非オブジェクトではありませんて、それは記憶して操作することができて、例えば私達はhas[key]=nilがあります.この戻りを呼び出すと、本当にnilを返すのか、それともkeyが見つからないのでnilを返すのか分かりません.
このときsymbolを使うことができます.
str = get_string
case str
  when String
    # Proceed normally
  when :eof
    # end of file, socket closed, whatever
  when :error
    # I/O or network error
  when :timeout
    # didn't get a reply
end

このコードはきっと異常を使うよりもはっきりしていて頭がいいのではないでしょうか.この方法はあなたの頭の中に保つことができるとは限らない.
4 symbol、変数と方法
最もよく知られているsymbolの使用は、クラス内で属性を定義することです.
class MyClass
  attr_reader :alpha, :beta
  attr_writer :gamma, :delta
  attr_accessor :epsilon
  # ...
end

attr_accessorはsymbolを用いてインスタンスの名前と読み書き方法の名前を表す.しかし、これはインスタンスの名前とsymbolとのつながりを意味するものではありません.例を見てください.
sym1 = :@foo
sym2 = :foo
instance_variable_set(sym1,"str")   # Works
instance_variable_set(sym2,"str")   #   

簡単に言えば、symbolはatrrのようなパラメータとして与えられる方法にすぎず、symbolの値に基づいてインスタンス変数とメソッドを作成する(書き方の末尾に=があり、インスタンス変数の前に@が加算される).したがってsymbolとその参照タグとの間には関連がある.
5 symbolsの変換
文字列とsymbols間の変換to_を使用sとto_Symメソッド:
a = "foobar"
b = :foobar
puts a == b.to_s   # true
puts b == a.to_sym    # true 

メタプログラミング(metaprogramming)を使用している場合は、次の方法が非常に役に立つ場合があります.
class Symbol
  def +(other)
    (self.to_s + other.to_s).to_sym
  end
end

+メソッドを使用すると、2つのsymbolを接続できます.次に彼を使った例です.アクセスメソッドはsymbolをパラメータとして受け入れ、読み書きメソッドが含まれているかどうかをテストします.
class Object
  def accessor?(sym)
    return (self.respond_to?(sym) and self.respond_to?(sym+"="))
  end
end

ここでsymbolを使うのが賢い例を挙げます.
mapを使用すると、複雑なblockが常に後ろに付いています.たとえ私たちが簡単に以下の操作をしていても、例えば:
list = words.map {|x| x.capitalize }

ここでは、簡単な機能のために多くのものを作ったようです.Symbolクラスを開き、to_を定義します.Procの方法は、必要に応じてsymbolをprocに変換します.しかし、私たちはどんなprocに戻るべきですか?オブジェクトコンテキストのsymbol自体である2つのパラメータがあることは明らかです.つまりsymbol自身をメッセージとして伝えた相手です.

def to_proc
  proc {|obj, *args| obj.send(self, *args) }
end

このコードは、Gavin SinclairのRuby Extensionsエンジニアリングから来ています.上のコードを書き換えることができます.

list = words.map(&:capitalize)

このコードを理解するのに時間がかかるのは意味がある.mapメソッドはブロックをパラメータとして受け入れます.ここでprocではないクラスをblockに渡すと、解釈器が自動的にto_を呼び出すprocメソッドはsymbolをblockに変換します.次にprocを返します.mapは各パラメータに呼び出します.なぜselfがメッセージとして配列に渡されるのが正しいのでしょうか.それはprocが閉じたパッケージであり、作成されたときのコンテキスト環境を記憶することができるからです.彼が作成されたときselfはto_を指していましたProcが作成されたときのsymbol.