忍者ブログ

ぢみへんプログラミング日誌

[PR]

×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

ruby-1.9.3-p392とrails3.2.13 を CentOS 6.4 にインストールするまで (2)

Railsインストールを再開
前回の記事で無事、Rubyをインストールできた(と思っていた)筆者は、すかさず立て続けにrails のインストールを開始した。

> gem install rails

しかし結果は

no such file to load -- zlib (LoadError)

訳の分からんエラーが出て全く先に進まなくなってしまったではないか。なんじゃこれは?
ひとしきり焦った挙句、どうやらファイル圧縮/解凍ツールのライブラリであるzlibが呼び出せないらしいということまでは理解できた。
とりあえずyum で片っ端からzlib 関連のライブラリのインストールを試してみる。こんな当てずっぽうでこの手の問題が解決したことがないが、とにかくやってみた。

> yum list | grep zlib
zlib.x86_64 1.2.3-29.el6 @anaconda-CentOS-201303020151.x86_64/6.4
zlib-devel.x86_64 1.2.3-29.el6 base
zlib-static.x86_64 1.2.3-29.el6 base
...
...
> yum install zlib.x86_64 #既にインストール済みなので無駄
> yum install zlib-devel.x86_64
> yum install zlib-static.x86_64

やるだけやってみたが、結果は何も変わらない。経験則が正しかったと言う以外には特に得るものがなかった。
そこで一旦、考えを整理してみた。
zlibというのは、rubyの標準添付ライブラリだが、元々はrubyとは関係のないC言語で作成された外部ライブラリである。それをrubyから使えるのは、恐らくはスタティックリンクかダイナミックリンクで結合しているに違いない。従って、
no such file to load -- zlib (LoadError)
というエラーはライブラリをメモリ上にロードできなかったということを意味する。要するに、ライブラリ参照エラーだ。zlibライブラリ本体がないか、それともライブラリの存在をconfigureスクリプトが認識してないか、ということだ。もしこの推測が正しいなら他の外部ライブラリ参照系のruby側ライブラリもいくつかは構築に失敗しているはずだ。
前の記事ではlibyaml をインストールした後、そのライブラリをconfigureスクリプトに認識させるために、敢えて--with-opt-dir=というオプションをつけて、ライブラリのパスを指定していた。それならzlib本体の場所もこれと同じ方法で教えたらどうだろう? 

./configure --with-opt-dir=/usr/local --with-opt-dir=/usr/lib64 --enable-shared --enable-option-checking

すると上記の推測は見事に(?)当たり、以下のコマンドがすんなり実行されるようになった。

# gem list --remote rails
*** REMOTE GEMS ***
rails (3.2.13)
rails-3-settings (0.1.1)
rails-action-args (0.1.1)
....
....

どうやら、/usr/lib64 というディレクトリ構成をRubyのインストーラ作者がフォローしきれなかったか、CentOSが独自に作っているパスのために認識できなかったんだろう。

さてこれでようやく後はRails をインストールするだけというところまできた。だが、筆者はここまでの作業を通じてこの手のインストールトラブルの類が他にもあるのではないかという気がしていた。似たような問題で一見解決方法が分からなくなるようなトラブルに関しては事前に避けておきたいものだ。
調べてみると、open-ssl (の開発環境)の存在が webrickの動作に依存関係を持っているという記事を見つけた。[Rails]railsで、opensslのモジュールが無いと怒られたら
webrickは良く使うプログラムなので後ではまる前にopen-ssl-devel をインストール後、再度前回でのやり方を踏まえてRubyをインストールしなおした。

> yum install openssl-devel
...
...
Complete!
> cd /tmp/ruby-1.9.3-p392
> make clean
> ./configure --with-opt-dir=/usr/local/lib --with-opt-dir=/usr/lib64 --enable-shared --enable-option-checking
> make
....
....
configuring openssl
...
configuring zlib
...
...
linking shared-object openssl.so
installing default openssl libraries
...
...
compiling zlib.c
linking shared-object zlib.so
installing default zlib libraries
...
....
Files: 772

Classes: 1374 ( 708 undocumented)
Modules: 306 ( 152 undocumented)
Constants: 2258 ( 828 undocumented)
Attributes: 1020 ( 440 undocumented)
Methods: 10478 (3096 undocumented)

Total: 15436 (5224 undocumented)
66.16% documented

Elapsed: 214.8s

> ruby -v
ruby 1.9.3p392 (2013-02-22) [x86_64-linux]

が、実際にopensslが使えるかどうか、irbで試してみると駄目と言われてしまう。何かが足りないらしい。

irb(main):001:0> require 'openssl'
LoadError: cannot load such file -- openssl
from /usr/local/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
from /usr/local/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
from (irb):1
from /usr/local/bin/irb:12:in `
'
irb(main):002:0> require 'zlib'
=> true # zlibは問題ない

ここでopensslのスタティックライブラリをyumからインストールしてみる他、rubyのmake時にffi というモジュールが上手くリンクできていなかったのを思い出し、その両方を試してみることにした。確かにコンパイル後Linking という表示がでるのはスタティックリンクも想起させるので怪しいといえば怪しいし、ffiにしてもどうやらダイナミックリンクの仕組みを担う部品かもしれない。Githubを参照すると、ffi-devel というライブラリに依存関係があると記されている(https://github.com/ffi/ffi)

> yum install openssl-static.x86_64
> yum install libffi-devel.x86_64

上記インストール後、再度configure から始めてみたところ、遂に irb で require 'openssl'が通るようになった。

> irb
irb(main):001:0> require 'openssl'
=> true

ここまでくればrailsまでは一気である。

>gem install rails
....
....
> rails -v
Rails 3.2.13

どうやら上手いこと、インストールできたようだ。
PR

ruby-1.9.3-p392とrails3.2.13 を CentOS 6.4 にインストールするまで (1)

VMware Playerですら他人が用意してくれたものしか使ったことがない筆者が、必要に迫られRuby on Rails の環境を自前で用意しなければいけなくなった。
そこで今回は仮想マシン(VMware Player)をまともに動かせるようになるところから始めて、ruby-1.9.3-p392とRails3.2.13をインストールするところまでを今回の話題にしたい。


VMWare Player を入手
vmware player の入手自体はvmware社のページより簡単に行える。各自の環境に合わせたインストーラをダウンロード・実行し、手引きに沿ってインストールを進めればよい。筆者はWindows7の64bit環境を使っているので「VMware Player for Windows 32-bit and 64-bit」を選択した。Windows版は32bitでも64bitでも気にする必要はないようだ。

ゲストOSを入手
vmware player をインストールし終わったら次は、ゲストOSを作成する必要がある(ゲストOSの語義についてはこちら。OSの優劣等は詳しくないが、単純に開発プロジェクトでよく目にするという理由から筆者はCentOSを選択することにした。
CentOS: http://www.centos.org/

このOSを選ぶという単純な行為ですら、もしWindowsを使っているのだとしたら、すんなりは行かせてくれない事情がある。それはCPUだ。OSはCPUを選ぶので当然、ゲストOSにする予定のCentOSにもCPUの型によって違いがある。問題はそれが「x86/x64」なのか「i386」と呼ばれる形式のものなのか、という点にある。linuxであればコンソールに「uname -a」と入力すればすぐに分かる情報なのに、Windowsにどっぷり浸かってしまうとそんな情報の引き出し方も分からなくなってしまう。
実際、Windows7でコントロールパネルからデバイスマネージャーを開き、プロセッサと書かれた箇所をクリックしてみたとしよう。そこで見るのはせいぜい自分のPCがCeleron かそれ以外か、という程度の話で、x86なんて文字はどこにも出てこない。
筆者のような者がこんな問題を自力で解けるはずもなく、すぐにgoogleで「x86 x64 確認」とキーワードを打ち込んだ。すると実に適切な過去の質問と答えが載っているページが見つかった。
【CPUはX86であるか否かを確認する方法】http://okwave.jp/qa/q3477130.html

CPUの問題を解決するとどのOSをダウンロードすればよいかは殆ど間違いようがないので、後は安心してCentOSの最新版をダウンロードする。ダウンロードサイト一覧:http://www.centos.org/modules/tinycontent/index.php?id=30
余談だが、容量がギガバイト級のため、筆者の環境では数時間がダウンロードに費やされた。もしこれが光ファイバ等の高速環境だったらどのくらいの速さで実行できるのだろう?……やはりこれもgoogle様に聞いてみれば分かってしまうのか?

ゲストOSを作成
OSのダウンロードが済んだらいよいよゲストOSを作成する段に移る。すること自体は多いような少ないような、慣れてしまえば少ないと思える程度の作業を行う。
①VMware Playerを起動 - 「VMware Playerへようこそ」と書かれた画面が表示される
②新規仮想マシンの作成:細かい手順は省くが「後でOSをインストール」を選択すること
③②で作成した仮想マシンを左側のリストから選択すると画面右側に「仮想マシンの設定」というメニューが出てくるので、それを選択する
④「仮想マシン設定」というタイトルのウィンドウが表示されるので左側のデバイスリストから「CD/DVD」を選択し、それと同時に画面右側に表示される「接続」欄で「ISOイメージファイルを使用する」を選択する。このとき先ほどダウンロードしたOSのISOファイルを指定すること。
⑤「OK」ボタンを押すと「仮想マシン設定」が閉じるので、③で選択した仮想マシンを再選択し、今度は画面右側のメニューから「仮想マシンの再生」を選択する。
⑥CentOSのブートが始まる。途中でキーボードの設定や言語の設定、ディスクの割り当て等を聞かれるが、使用しているPCの空き容量が30GB以上あり、メモリも1から2GB積んでいる状態ならデフォルト設定のまま進んで良いと思われる。但し、最後にインストールモードについてきかれるので、そこで最終的にインストールするプログラムの大枠を選ぶことになるので、そこでは多少慎重に考えた方が良いかもしれない。この最後の部分は、人によって選択が異なるだろう。サーバー設定に慣れていれば余計なプログラムを入れたくないはずだから「minimum」を選ぶだろうし、別の理由から別のインストール設定を選択することもありうる。筆者はweb serverにしておいた。

インストールモードを選ぶとあとは基本的に待つだけでインストールは完了するが、その仮想マシンを再起動した後に、ネットワークの設定をしなければならない。
⑦ /etc/sysconfig/network の内容を以下に変更
NETWORKING=yes
GATEWAY=xxx.xxx.xxx.xxx # 自分の環境に合わせてください
⑧/etc/sysconfig/network-scripts/ifcfg-eth0 を編集
ONBOOT=yes
BOOTPROTO=dhcp # 固定IPアドレスを割り当てたい場合はこの設定では駄目
⑨一旦仮想マシンを停止し、仮想マシン設定からネットワーク設定を行う。ネットワークアダプタがNAT接続になっているはずなので、「ブリッジ接続」に変える。
⑩仮想マシン再起動

以上で仮想マシンがホストOSを介して外部ネットワークに接続できるようになる(はず)。
これ以後、ついにRuby をインストールするわけだが、どういうわけだかオープンソースの世界というかUNIXの世界というのは、ソフトウェアのインストールごときでも手間暇取らすのが好きならしい。ということを思い知らされた。恐らくWindowsやMacと異なり、ディレクトリ構成などに前提が設けられない等の不都合はあるんだろうな、などとも思いつつ。

Rubyをインストール
デフォルト環境ではCentOSにRubyはインストールされていない。CentOSのパッケージマネージャyumを使ってインストールしてもいいが、yumでサポートしているのは1.8系のみなので1.9系以降を使うなら、Ruby本家のFTPサイトよりダウンロードする必要がある。
勿論CentOS上にダウンロードする必要があるので、wget 等のツールを使う(筆者はwgetを使用)。コマンドも良し悪しあるが、この程度のことであればコマンドでサクッと済ませるのも悪くない。

cd /tmp
wget ftp://core.ring.gr.jp/pub/lang/ruby/1.9/ruby-1.9.3-p392.tar.gz
tar xzf ruby-1.9.3-p392.tar.gz # ダウンロード後にファイル解凍

次はファイルのメイク(プログラムのビルド)……といきたいところだが、実際にやってみるとできなかった。「./configure」とコマンドを実行させた直後に、gccがインストールされていないと警告が表示され処理が中断したからだ。
まぁgcc程度であればインストールすれば済む話なので、そこはyumを使ってさっさと終わらせる。

> yum list|grep gcc
gcc.x86_64 4.4.7-3.el6 base
gcc-c++.x86_64 4.4.7-3.el6 base
libgcc.x86_64 4.4.7-3.el6 base
....
> yum install gcc.x86_64
> yum install gcc-c++.x86_64

よし、じゃあビルドだーーー……

cd ruby-1.9.3-p392
./configure
make
make test
make install

ビルドそのものは実に簡単であった。実質、./configure と make だけ。この程度で済むならRubyはほぼソースから構築した方が、OSの環境に合わせたものが手に入る分、良い選択だと言えるだろう。

そしてRailsへ、のはずが……
後は gem install rails とコマンドを打てばDB構築とWebサーバー構築を除けばほとんどの作業は終わる。
はずだった。
実際にgem install rails と入力すると、libyamlがない、という意味のエラーが出てrubygemが全く動かないのである。railsに限らず全く機能しない。
調べてみて分かったのだが、libyaml というライブラリをCentOSが持っておらず、rubyよりも先にそれをインストールせねばならんということらしい。

wget http://pyyaml.org/download/libyaml/yaml-0.1.4.tar.gz
tar zxvf yaml-0.1.4.tar.gz
cd yaml-0.1.4
./configure
make
make install

libyaml をインストール終、Rubyのインストールを再度開始した。

cd ruby-1.9.3-p392
./configure --with-opt-dir=/usr/local --enable-shared --enable-option-checking
make
make test
make install

(--with-opt-dir の参照先は libyaml の配置場所であり、それは whereis コマンドで知ることができる。)
インストール後のRubyバージョーン確認は問題なし。

> ruby -v
> ruby 1.9.3p392 (2013-02-22) [x86_64-linux]

よし、これでRailsインストール再開できる。おめでとう、俺!

だが。

この後も訳の分からぬトラブルが筆者を待っていた…… 笑

(つづく)

エラー箇所を簡単に特定できるログのスマートな(?)出力方法

C言語には #define というキーワードがある。

#define ONE 1
#define TWO 2


Rubyで言えば定数の定義を行っているのに似ているが、Rubyはあくまでも頭文字が大文字で示される定数のオブジェクトに値を代入しているのにたいし、C言語ではコンパイラ処理の前にプリプロセッサというツールが「#define」の後に続く2つの文字列に対し、左側の文字列を右側の文字列にソースコード上で変換するという違いがある。

(プリプロセッサによる返還後)

#define ONE 1
....
....
a = ONE;

(プリプロセッサによる返還後)

....
....
a = 1;

見ての通り、ONEが1に置き換えられてしまう。
このようなプリプロセッサを使った文字の置き換えはC言語では一般にマクロと呼ばれ、同様の機能はRubyに存在しない。

このマクロを推し進めた特殊マクロというものがC言語にはいくつかあるのだが、その中でもRubyと同じく __FILE__ と __LINE__ というキーワードはデバッグに大変役に立つ。これらのマクロをソースコード中に埋め込むと、プリプロセッサがそのマクロの書かれたファイル名と書かれている位置(行番号)に変換してくれるからだ。

(ファイル名: abc.c)
printf("THIS IS A TEST %s line %d", __FILE__, __LINE__);

上記のコードが実行されるとコンソールには
「THIS IS A TEST abc.c line 24」
という感じの出力が行われる。
このようにしてソースコード中にログを埋め込んでおけば、どのファイルの何行目まで処理が進んだのかを知るのに大変便利だ。

さらに推し進めると、以下のようなマクロを書くことになる。

#define log( msg ) printf("%s,%d:%s", msg, __FILE__,__LINE__)


このマクロをソースコード中に埋め込み、例えば「log("ERROR");」と書いて埋め込んでおくとその該当箇所全てが、プリプロセッサによりコンパイルの直前に「printf("%s %s %d", "ERROR", __FILE__, LINE__);」という表現に置き換えられる。その結果、このマクロが埋め込まれたプログラム箇所が実行されるたび
「ERROR ファイル名 行番号」
という表示がコンソールに表示されることとなる。こんなうまい手を使わないことがあるだろうか?!
そういう性質のテクニックなので、C言語を使う者であれば比較的初級者でもこの方法を知っていることが少なくない。

ではこれを、Rubyでも行おうとしたらどうすれば良いだろうか? 前述したとおり、Rubyにプリプロセッサなどというものはない。まず安直に考えて以下のコードはとりあえず、機能はする。

print "ERROR #{__FILE__} #{__LINE__}"

__FILE__ と __LINE__ はRubyでは擬似変数とい扱いとされている。これを先ほどのC言語のように、いちいち __FILE__, __LINE__ と書かないでも出力されるようにしたい。

だが結論から言うと、__FILE__, __LINE__ をそのまま使う方法では大変厳しく、恐らく不可能に近いだろう。なぜならこの2つの擬似変数は上述したC言語のマクロのように、ソースコードに現れた箇所のファイル名と行番号をそのまま返すので、ソースコード上に直接埋め込む以外に原則、使いようがない。だからプリプロセッサのないRubyで__FILE__, __LINE__ を書かずにファイル名と行番号を出そうとしても無理だ。

そこで発想を変えてみる必要がある。Rubyにおいて実行中のファイルや行番号といった情報はどこから手に入るのか? それらの一つにKernelモジュールのcaller というメソッドがある。caller を用いて適当なメソッドを書くとすれば大概以下のようなものではないだろうか。

def print_message( msg )
p "#{msg} #{caller[0]}"
end

Kernel.#callerメソッドはその名の通り、callerメソッド自身を呼び出しているメソッドを再帰的に表現した配列を返す。言い換えればスタックトレースを入手するためのメソッドで、戻り値の配列を添え字の小さい方から大きい方へと走査することで、丁度スタックを巻き戻すように呼び出し元メソッドの情報(ファイルと呼び出し行番号)を得ることができる。

仮に以下の内容のファイル abc.rb を用意したとしよう。(※左端の数字は行番号)

1 # coding: utf-8
2
3 def aaa
4 puts caller[0]
5 end
6
7 def bbb
8 aaa
9 end
10
11 def ccc
12 puts caller[0]
13 end
14
15 def ddd
16 ccc
17 end
18
19 aaa
20
21 bbb
22
23 ccc
24
25 ddd
26

これを実行すると以下の実行結果が得られるはずだ。

> ruby abc.rb
abc.rb:19:in `
'
abc.rb:8:in `bbb'
abc.rb:23:in `
'
abc.rb:16:in `ddd'

caller[0] は「メソッド自身(caller)を呼び出しているメソッドの呼び出されている場所」を示している。だから19行目でメソッドaaa が呼び出されると、aaa内部のcaller[0]はaaaが呼び出された場所、すなわち abc.rb の19行目という情報を返す。

こうしたKernel.#callerの応用は独自定義の例外クラスを定義する際にも用いることができる。initializeメソッドの内部でcallerを使うことで例外の送出位置を知ることができれば、例外が起きたときの調査・分析にかかる時間を短縮できるだろう。

class MyException < Exception
attr_reader :raised_at
def initialize(*args)
super
@raised_at = caller[0]
end
end


全てのクラスに何らかの位置捕捉情報を持たせたければObjectクラスを再定義すればよい。

# coding: utf-8

class Object
def source_location
caller[0]
end
end


h = {a:1, b:2}
p h # => {:a=>1, :b=>2}
p h.source_location # => "aaa.rb:12:in `
'"


ここに挙げたコードは思いついたままのほんの一例に過ぎないが、アイディア次第ではデバッグ等に重宝するのではないだろうか。

Enumerator がなんで必要なのかようやく分かった

RubyにはEnumeratorというEnumerableモジュールのラッパークラスと呼ばれるクラスがあるのだが、これはeachメソッドを実装してないクラスにもEnumerableモジュールの機能を与えるためのインターフェイスクラスとして存在しているということを今日初めて理解した。


class Abc
def initialize
@arr = []
end

def set_num(num)
@arr << num
end

def my_each
@arr.each do |num|
yield num
end
end
end

abc = Abc.new

abc.set_num 100
abc.set_num 200
abc.set_num 300
abc.set_num 1000
abc.set_num 10000

abc.my_each { |i| p i}

enum = Enumerator.new(abc, :my_each)

m = enum.map{|i| i*i}

p m


このコードの実行結果は以下の通りとなる。

> ruby enumerator_experiment.rb
100
200
300
1000
10000
[10000, 40000, 90000, 1000000, 100000000]


見ての通り、クラスAbcはEnumerableをincludeしていないのでEnumerableで定義されているmapやsellect等のメソッドをAbcは使えない。また仮にEnumerableをincludeしていたとしても、Abcにはeachメソッドがないから機能しない。こういうクラスにEnumerableのインターフェイスを与えてやるにはどうしたらいいのか。

そこでEnumeratorの出番というわけだ。クラス独自のイテレータメソッドを持っていれば、それをeachの代わりとみなしてEnumerableの各メソッドを実行させてしまおうという意図で使うことができる。EnumeratorクラスのメソッドインターフェイスはEnumerable互換であると考えてよい。
上記コード例で行くと、Abc#my_eachは自作のeachメソッドで内部実装自体にはArray#eachを使っている。Enumerator::new でこのメソッドを指定すると生成されたEnumeratorオブジェクトの各メソッドは、Enumerableモジュールの各メソッドがinclude元クラスのeachメソッドを基盤に動作するのと同じように、Abc#my_eachの実装を基にmapやsellectメソッドを構築する。


さて、Ruby1.9からはeachメソッドにブロックが続かなかったときは、eachメソッドの戻り値がEnumeratorとなる。そのため次のようなコードが書ける。


irb(main):003:0> [1,2,5,100,10].each
=> #
irb(main):004:0> [1,2,5,100,10].each.zip([2,4,6,8,10])
=> [[1, 2], [2, 4], [5, 6], [100, 8], [10, 10]]


これと同じ挙動を先のmy_eachに加えられるだろうか?
block_given? メソッドを使ってブロック判定を行い、ブロックがなければEnumeratorば可能だ。


class Abc
def initialize
@arr = []
end

def set_num(num)
@arr << num
end

def my_each
if block_given?
@arr.each do |num|
yield num
end
else
Enumerator.new(self, :my_each)
end
end
end

abc = Abc.new

abc.set_num 100
abc.set_num 200
abc.set_num 300
abc.set_num 1000
abc.set_num 10000

abc.my_each { |i| p i}

enum = Enumerator.new(abc, :my_each)

m = enum.map{|i| i*i}

p m

m = abc.my_each.map{|i| i*2}

p m


実行結果:

> ruby enumerator_experiment.rb
100
200
300
1000
10000
[10000, 40000, 90000, 1000000, 100000000]
[200, 400, 600, 2000, 20000]

Rubyにおける多重代入について

Rubyの多重代入とは基本的にこういうものを指す。

a, b = *[1, 2] # a = 1, b = 2
*c = 1, 2, 3 # c = [1, 2, 3]

このように * という記号を付けることで、代入式の右辺の配列を分解して左辺に渡したり、右辺の任意数の要素を配列としてまとめて左辺に代入できる。(こういう働きをするときの * をsplat演算子とも呼ぶこともあるそうだが、実際には本物の演算子ではないと「プログラミングRuby」には書いてある。)この性質を生かして、メソッドの定義で可変引数を実現可能だ。

irb(main):001:0> def func( *s )
irb(main):002:1> s
irb(main):003:1> end
=> nil
irb(main):005:0> func(1,2,3)
=> [1, 2, 3]

見ての通り、可変引数は配列として引数に渡される。

ところが話はここで終わらない。多重代入による可変引数を使うことには意外な(ある意味便利な)副作用があるからだ。以下は上記コードのfuncメソッドを引数なしで実行した例である。

irb(main):004:0> func
=> []

なんと! 引数がないから例外発生かと思いきや、空の配列として引数を受け取っているではないか。ということは多重代入引数は同時に空配列のデフォルト引数でもあるわけだ。

多重代入に関する注意点がもう一つ。単なる代入式での多重代入とメソッドの引数で扱う多重代入では挙動が異なっていることに注意しなければならない。

メソッドの引数ではなく、左辺に * をつけての単なる多重代入の場合、右辺要素が1つしかないときは、左辺の変数に配列が代入されるのではなく、単に右辺のオブジェクトがそのまま代入される。

irb(main):021:0> *a = 1
=> 1
irb(main):022:0> *a = 1, 2
=> [1, 2]

しかしメソッド引数としての多重代入の動作では、呼び出し側で用意した引数が1個のみだとしても、メソッド側では必ず配列として扱われる。

irb(main):001:0> def func( *s )
irb(main):002:1> s
irb(main):003:1> end
=> nil
irb(main):023:0> func
=> []
irb(main):024:0> func 1
=> [1]
irb(main):025:0> func 1, 2
=> [1, 2]


この挙動の違いが将来なくなるかどうかは分からないが、現状では注意するべきだろう。
  

カレンダー

04 2024/05 06
S M T W T F S
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

フリーエリア

最新CM

バーコード

ブログ内検索

Copyright ©  -- ぢみへんプログラミング日誌 --  All Rights Reserved

Design by CriCri / Material by petit sozai emi / powered by NINJA TOOLS / 忍者ブログ / [PR]