bar_1

contents_map

2010年12月24日金曜日

Rubyにおける代入・参照・参照渡しと、メソッドの仮引数・ローカル変数・グローバル変数

ひさびさにRubyを触って、思い出すまでハマったのでメモっておく。



「Rubyには参照渡ししかない」とだけ覚えていたことから、生じていた思い込み:
×メソッドの引数を介して、グローバル変数の値は変えられる

これは間違い。



以下が正しい:

  • 代入演算子= は、参照先を変更する(だけの)ためのものである

  • メソッドは、オブジェクトに対するメッセージである

  • メソッドの機能の一つには、オブジェクト内部のフィールドの値を変更することがある

  • メソッド定義の仮引数は、メソッドのスコープのローカル変数である







実験



以下のようなt_f, t_f2, t_f3 のメソッドがあるとする:
irb(main):022:0> def t_f( a )
irb(main):023:1>  a='t_f'
irb(main):024:1> end
=> nil

irb(main):029:0> def t_f2( a )
irb(main):030:1> a.push('bar')
irb(main):031:1> end
=> nil

irb(main):036:0> def t_f3( a )
irb(main):037:1> b=a
irb(main):038:1> b.push('t_f3')
irb(main):039:1> end
=> nil









メソッド t_f のテスト



irb(main):025:0> a="boo"
=> "boo"
irb(main):026:0> t_f( a )
=> "t_f"
irb(main):027:0> a
=> "boo"





  1. グローバル・スコープの変数 a の参照が、メソッド t_f の仮引数 a にコピーされる
     (この時点で t_f の仮引数a の参照先は、オブジェクト"boo"である)


  2. メソッド t_f の仮引数 a の参照先が、文字列オブジェクト "t_f" に、変更される


  3. メソッド t_f を抜けたので、メソッド t_f の仮引数 a は破棄される
    ��グローバル・スコープの変数 a の値=参照先は、 "boo" のままであることが、確認される


メソッド t_f2 のテスト



irb(main):028:0> b=['boo']
=> ["boo"]
irb(main):033:0> t_f2( b )
=> ["boo", "bar"]
irb(main):034:0> b
=> ["boo", "bar"]





  1. グローバル・スコープの変数b の参照が、メソッドt_f2の仮引数a にコピーされる(この時点でt_fの仮引数a の参照先は、オブジェクト["boo"]である)


  2. メソッドt_f2の仮引数a に、メッセージpush("bar")が渡され、仮引数a の参照先のオブジェクトは["boo", "bar"]に、変更される


  3. メソッドt_f2 を抜けたので、メソッドt_f2 の仮引数a は破棄される
    ��グローバル・スコープの変数b の値=参照先のオブジェクトの値は、["boo", "bar"]と変更されていることが、確認される


メソッド t_f3 のテスト



irb(main):042:0> b=["boo", "bar", "bar"]
=> ["boo", "bar", "bar"]
irb(main):043:0> t_f3( b )
=> ["boo", "bar", "bar", "t_f3"]
irb(main):044:0> b
=> ["boo", "bar", "bar", "t_f3"]





  1. グローバル・スコープの変数b の参照が、メソッドt_f3の仮引数a にコピーされる
     (この時点でt_fの仮引数a の参照先は、オブジェクト["boo", "bar", "bar"]である)


  2. メソッドt_f2のローカル変数b の参照先は、仮引数a の参照先に設定される


  3. メソッドt_f2のローカル変数b の参照先に、"t_f3"がpushされ、オブジェクト["boo", "bar", "bar", "t_f3"]に、変更される


  4. メソッドt_f2 を抜けたので、メソッドt_f2 の仮引数a 、ローカル変数b は、ともに破棄される
    ��グローバル・スコープの変数b の値=参照先のオブジェクトの値は、["boo", "bar", "bar", "t_f3"]と変更されていることが、確認される

2010年12月2日木曜日

Cygwin上のruby環境でgithubとgist, gistyの環境を整えてみた


■問題点
例によって、躓きまくりました。
  • nokogiriのgemインストールができない。
  • gistyのgemインストールができない。

■解決法
時間のない人のために、最初に、今回試した手順のまとめを示します:
  1. Cygwinのライブラリ(lib*)のインストール(gistyに必要とされるもの)
    Cygwinのインストーラ:setup.exeで、libxml2, libxslt, libiconv, (+libiconv2) をインストール。
  2. gemの設定1(環境変数GEM_HOME, APPDATA)
    export GEM_HOME="/cygdrive/your/gem/home"
    export APPDATA="${GEM_HOME}"
  3. gemの設定2(gemの取得先の設定追加)
    $ gem sources -a http://gems.github.com/
  4. gemインストール1(nokogiri)
    $ gem install nokogiri
  5. gemインストール2(gisty)
    $ gem install swdyh-gisty
  6. gistyの設定(GISTY_DIR)
    export GISTY_DIR="${HOME}/your/gisty/directory"
  7. githubの設定(SSH公開鍵の登録)
    github.comにログインし
    アカウントの設定>アカウントの概要>SSH公開鍵
    にて、登録。
  8. gitのローカル環境の設定(githubのidとAPIトークン)
    git config --global github.user your_id
    git config --global github.token your_APItoken
  9. gistyの設定(パスの通ったディレクトリにコピー)
    cd /cygdrive/${GEM_HOME}/gems/swdyh-gisty-0.0.14/bin
    cp -i gisty /usr/bin/.
以下は試したときの時系列ログ的書き物です。


●gemインストール1

$ gem install nokogiri
Building native extensions. This could take a while...
ERROR: Error installing nokogiri:
ERROR: Failed to build gem native extension.
/usr/bin/ruby.exe extconf.rb
checking for libxml/parser.h... yes
checking for libxslt/xslt.h... yes
checking for libexslt/exslt.h... yes
checking for iconv_open() in iconv.h... no
checking for iconv_open() in -liconv... yes
checking for xmlParseDoc() in -lxml2... yes
checking for xsltParseStylesheetDoc() in -lxslt... yes
checking for exsltFuncRegister() in -lexslt... yes
checking for xmlFirstElementChild()... yes
checking for xmlRelaxNGSetParserStructuredErrors()... yes
checking for xmlRelaxNGSetParserStructuredErrors()... yes
checking for xmlRelaxNGSetValidStructuredErrors()... yes
checking for xmlSchemaSetValidStructuredErrors()... yes
checking for xmlSchemaSetParserStructuredErrors()... yes
creating Makefile
/usr/lib/ruby/1.8/mkmf.rb:1322: warning: global variable `$preload' not initiali
zed
make
Makefile:119: *** target pattern contains no `%'. Stop.
Gem files will remain installed in d:/home/gems/nokogiri-1.4.4 for inspection.
Results logged to /cygdrive/d/home/gems/nokogiri-1.4.4/ext/nokogiri/gem_make.out

エラーログからは、なにが悪いのかさっぱり分からない。そこで、エラーメッセ
ージをぐぐってみる。
http://stackoverflow.com/questions/1225703/cant-build-gem-native-extension-build-fails-can-you-see-why
どうやら、Cygwin環境のライブラリを再インストールする必要があるようだ。。。
●足りないと思われるライブラリ
上記gemエラーログから、想像したライブラリ名は以下の通り:
  • ?libxml
  • libxml2
  • libxslt
  • ?libexslt
  • libiconv
  • (+iconv2)

��は、存在しないようだった。
Cygwinのインストーラ:setup.exe を使って、上記をReinstallした。
次に再度、gemのインストールを試す。
●再度gemインストール
また失敗。
$ gem install nokogiri
cygwin warning:
MS-DOS style path detected: C:\Documents and Settings\All Users\Application Data/gemrc
Preferred POSIX equivalent is: /cygdrive/c/Documents and Settings/All Users/Application Data/gemrc
CYGWIN environment variable option "nodosfilewarning" turns off this warning.
Consult the user's guide for more details about POSIX paths:
http://cygwin.com/cygwin-ug-net/using.html#using-pathnames
Building native extensions. This could take a while...
ERROR: Error installing nokogiri:
ERROR: Failed to build gem native extension.
/usr/bin/ruby.exe extconf.rb
checking for libxml/parser.h... yes
checking for libxslt/xslt.h... yes
checking for libexslt/exslt.h... yes
checking for iconv_open() in iconv.h... no
checking for iconv_open() in -liconv... yes
checking for xmlParseDoc() in -lxml2... yes
checking for xsltParseStylesheetDoc() in -lxslt... yes
checking for exsltFuncRegister() in -lexslt... yes
checking for xmlFirstElementChild()... yes
checking for xmlRelaxNGSetParserStructuredErrors()... yes
checking for xmlRelaxNGSetParserStructuredErrors()... yes
checking for xmlRelaxNGSetValidStructuredErrors()... yes
checking for xmlSchemaSetValidStructuredErrors()... yes
checking for xmlSchemaSetParserStructuredErrors()... yes
creating Makefile
/usr/lib/ruby/1.8/mkmf.rb:1322: warning: global variable `$preload' not initiali
zed
make
Makefile:119: *** target pattern contains no `%'. Stop.
Gem files will remain installed in d:/home/gems/nokogiri-1.4.4 for inspection.
Results logged to /cygdrive/d/home/gems/nokogiri-1.4.4/ext/nokogiri/gem_make.out

似たようなエラーメーセージだが、若干違うのは”MS-DOSスタイルのパス”が云々
というところ。知らない環境変数が参照されていると見当をつけ、
set | grep -i "パス"
してみた。すると、APPDATAという変数に上記ディレクトリが設定されている
●gemの設定(環境変数)
以前、GEM_HOMEを設定したが、ActiveScriptRubyのためであった。今設定しよう
としているのは、Cygwin上のRubyのためのものである。既存の設定だと、
GEM_HOMEは、ActiveScriptRubyのための環境変数の設定値(当然、こちらはWin 
形式のディレクトリ名)となっており、Cygwinとバッティングする。
また、環境変数APPDATAも、gemから同様な参照をされる。gemは、APPDATAの設定
値(ディレクトリ)からも、gemrcを読もうとしている。
だから、Cygwin上のRuby環境においては、Bashの環境変数:
GEM_HOME, APPDATA両方の設定を、POSIX形式で、行う必要がある;
これらの値の設定を.profileまたは.bashrcにでも書いておけばよかろう。
以下のようにした:
export GEM_HOME="/cygdrive/d/home"
export APPDATA="${GEM_HOME}"

ふー。
もう一度、gemのインストールから・・・(ヽ´ω`)。。。
●nokogiri のインストール
$ gem install nokogiri
Building native extensions. This could take a while...
Successfully installed nokogiri-1.4.4
1 gem installed
/usr/lib/ruby/1.8/rdoc/parsers/parse_c.rb:204: warning: method redefined; discar
ding old progress
Installing ri documentation for nokogiri-1.4.4...
No definition for get_options
No definition for set_options
No definition for parse_memory
No definition for parse_file
No definition for parse_with
Installing RDoc documentation for nokogiri-1.4.4...
No definition for get_options
No definition for set_options
No definition for parse_memory
No definition for parse_file
No definition for parse_with

インストールできたようだ。
次にgistyのgemをインストールする。
●swdyh-gisty のインストール
$ gem sources -a http://gems.github.com/
$ gem install swdyh-gisty
/usr/lib/ruby/site_ruby/1.8/rubygems/dependency.rb:88: warning: instance variable @prerelease not initialized
/usr/lib/ruby/site_ruby/1.8/rubygems/dependency.rb:88: warning: instance variable @prerelease not initialized
Successfully installed swdyh-gisty-0.0.14
1 gem installed
/usr/lib/ruby/1.8/rdoc/parsers/parse_c.rb:204: warning: method redefined; discarding old progress
Installing ri documentation for swdyh-gisty-0.0.14...
Installing RDoc documentation for swdyh-gisty-0.0.14...
/usr/lib/ruby/1.8/rdoc/generators/html_generator.rb:1103: warning: too many arguments for format string
/usr/lib/ruby/1.8/rdoc/generators/html_generator.rb:1103: warning: too many arguments for format string
/usr/lib/ruby/1.8/rdoc/generators/html_generator.rb:1103: warning: too many arguments for format string
/usr/lib/ruby/1.8/rdoc/generators/html_generator.rb:1103: warning: too many arguments for format string
/usr/lib/ruby/1.8/rdoc/generators/html_generator.rb:1103: warning: too many arguments for format string
/usr/lib/ruby/1.8/rdoc/generators/html_generator.rb:1103: warning: too many arguments for format string
/usr/lib/ruby/1.8/rdoc/generators/html_generator.rb:1103: warning: too many arguments for format string
/usr/lib/ruby/1.8/rdoc/generators/html_generator.rb:1103: warning: too many arguments for format string
/usr/lib/ruby/1.8/rdoc/generators/html_generator.rb:1103: warning: too many arguments for format string
/usr/lib/ruby/1.8/rdoc/generators/html_generator.rb:1103: warning: too many arguments for format string
/usr/lib/ruby/1.8/rdoc/generators/html_generator.rb:1103: warning: too many arguments for format string
/usr/lib/ruby/1.8/rdoc/generators/html_generator.rb:1103: warning: too many arguments for format string
/usr/lib/ruby/1.8/rdoc/generators/html_generator.rb:1103: warning: too many arguments for format string
/usr/lib/ruby/1.8/rdoc/generators/html_generator.rb:1103: warning: too many arguments for format string
/usr/lib/ruby/1.8/rdoc/generators/html_generator.rb:1103: warning: too many arguments for format string
/usr/lib/ruby/1.8/rdoc/generators/html_generator.rb:1103: warning: too many arguments for format string

ドキュメント関連のwarningが出るが、インストールできたようだ。
■gistyの設定(GISTY_DIR)
適当なディレクトリを用意しましょう。このディレクトリに、gistyは
GISTY_DIRは、.bashrcに書
いておけばよいでしょう。
export GISTY_DIR="${HOME}/your/directory"

■githubの設定(SSH公開鍵の登録)
ssh-keygenを使って、公開鍵と秘密鍵を生成する。
次に、githubに生成した公開鍵を登録する。登録は、githubにログインして、
 アカウントの設定>アカウントの概要>SSH公開鍵
から行います。
手順の詳細は、
コピペするときに、改行が入らないように気をつけること。改行が入ってしまっ
たら、消してください。
公開鍵を登録し終わったら、ちゃんと登録できたかテスト。テストは以下のよう
な感じで:
$ ssh -T git@github.com
Enter passphrase for key '/home/masa/.ssh/id_rsa':
ERROR: Hi mephistobooks! You've successfully authenticated, but GitHub does not
provide shell access

"successfully authenticated"されれば、オッケイ。
■gitの設定(idとAPIトークン)
APIトークンは、github.com/account の
アカウントの設定>アカウントの概要>アカウントの管理>APIトークン
に表示されます。
下記のコマンドで、githubのidとAPIトークンを設定しましょう。
git config --global github.user your_id
git config --global github.token your_APItoken

■gistyの設定(パスの通ったディレクトリにコピー)
なぜなんだか、gem installしても/usr/bin/に、gistyがコピーされませんでした。
なので仕方なく手で、ディレクトリ:
/cygdrive/${GEM_HOME}/gems/swdyh-gisty-0.0.14/bin から、
cp -i gisty /usr/bin/.
した。
ふー。
■References
・README.rdoc -gisty
https://github.com/swdyh/gisty
・gistコマンドよりちょっと便利なgisty
http://d.hatena.ne.jp/swdyh/20081207/1228655198
・Gistyインストールから利用までの道のりメモ
http://d.zeromemory.info/2009/01/05/install-gisty.html
・Generating SSH keys (Win/msysgit)
http://help.github.com/msysgit-key-setup/
・WindowsでのGit環境構築とその注意点
http://sourceforge.jp/magazine/09/02/12/0530242