1 名前:デフォルトの名無しさん mailto:sage [2009/07/03(金) 12:55:05 ] プログラミング言語Rubyについての、初心者向けスレです。質問・要望・雑談などどうぞ。 【Ruby1.9.1 は従来版とは異なる部分も多く、書籍や解説やライブラリのサポートがまだありません】 【自力で解決できない壁で悩むことのない最新安定版の Ruby1.8.7 での学習をお勧めします】 ※1.8.7 は 1.8 系と 1.9 系の橋渡しをするためのリリースで、1.9 系 の便利新機能の一部が利用可能です 関連スレやURLは>>2-5 あたりを見てください。Ruby on Rails の質問は Webプログラミング板の Rails スレへ。 ■質問する人へ 質問する前に次の3つをすること。ここで回答を待つよりそのほうが早い。 ・モジュール名やエラーメッセージでググる ・マニュアルで引っかかったクラスの記述を探す www.ruby-lang.org/ja/man/ ・FAQを一応読む www.ruby-lang.org/ja/man/?cmd=view;name=Ruby+FAQ 質問には以下を書くこと。へたくそな質問は再提出を要求される。 ・詳しい内容(「動きません」「うまくできません」では回答しようがない) ・エラーメッセージ(自力で訳さずなるべくそのままで) ・実行環境(OS名、Rubyのバージョン(ruby -v でわかる)) ・最終的にやりたいこと(もっとよい方法がある場合が多いので) 回答してくれた人には「ありがとう」のひとことをいってあげて。 ■回答する人へ 相手は初心者、根気よく育てるつもりで。質問がへたくそなのも大目にみてあげる。 それができないならこないこと(だって初心者スレだもん)。 ・既出な質問やFAQは「XXXを読め」でいいので、叩かない&怖がらせない。 ・わけわかな質問にもエスパー発揮で。できれば質問の仕方を教えるぐらいで。 ・自信がない回答ならその旨表明すること。誤った回答は初心者じゃ見抜けない。
6 名前:デフォルトの名無しさん mailto:sage [2009/07/03(金) 13:57:32 ] instance_variable_get() instance_variable_get() instance_variable_defined?() はありますが instance_variable_delete() はないでしょうか。 あるオブジェクトからインスタンス変数を完全に取り除く方法があれば教えてください。
7 名前:デフォルトの名無しさん mailto:sage [2009/07/03(金) 14:16:18 ] 現状ではない
8 名前:デフォルトの名無しさん mailto:sage [2009/07/03(金) 14:19:45 ] というかそのへんに依存したコードは書くべきではないと思う
9 名前:デフォルトの名無しさん mailto:sage [2009/07/03(金) 15:13:57 ] >>6 remove_instance_variable ちなみに俺は>>8 の意見には反対、使っても全然OK派
10 名前:デフォルトの名無しさん mailto:sage [2009/07/03(金) 15:54:57 ] リフレクション機能を使うべき場面で使うのは全然問題ないのだが、今が使うべき場面なのかどうかは真剣に考慮しよう。
11 名前:デフォルトの名無しさん mailto:sage [2009/07/03(金) 16:18:30 ] 98パーセントくらいは使う必要ないよね
12 名前:デフォルトの名無しさん mailto:sage [2009/07/03(金) 16:23:58 ] プログラミング言語ruby読んでクラス定義とかのフックの柔軟さを知ったときは キモッって思った一方これ使ったら綺麗に書けそうなプログラムがあるなあとも思った
13 名前:デフォルトの名無しさん mailto:sage [2009/07/03(金) 16:28:20 ] 多くは「○○という機能を使ってみた」程度であるのは否定はしない ふつーに書いたほうがわかりやすいし、多くの場合動作も速い
14 名前:デフォルトの名無しさん mailto:sage [2009/07/03(金) 17:22:37 ] 普通に書けるなら普通に書くのがいい さらに特殊なケースへの対応として、 プログラマがその気になればRubyは大抵の無茶を許してくれる
15 名前:デフォルトの名無しさん mailto:sage [2009/07/03(金) 17:57:24 ] 仕事でRubyを使う場合は、どんな業務になりますか? やはりWeb系ですか?
16 名前:デフォルトの名無しさん [2009/07/03(金) 17:58:27 ] >>15 仕事でRubyを使うことはないです 強いて言うなら趣味グラマーの用途しかありません
17 名前:デフォルトの名無しさん mailto:sage [2009/07/03(金) 18:14:43 ] >>15 サーバは自前で用意するから、という案件が2年でやっと2個 Java, PHP > 量産の壁 >> Perl >> なんかシャレにならない壁 >> Ruby on Rails > Python (激レア) こんな感じ 「こんなソフト作ってという仕事取ってきたからじゃあRubyで作ろうぜ」というのはまずありえない 言語は伏せるけどシステム作るから買ってーという営業込みでないとお金にならない Rubyが社内ツールとしての地位を確立してて、 とっても便利に業務進めてる会社に心当たりがこれまた2つあるが、 じゃあこの便利なRubyでシステム作って売ろうぜという話には間違ってもなってないようだ まあ適材適所って奴だな Rubyを使えるということを評価する会社はいい会社だと思うが、Rubyしか使えない人を雇う会社は駄目会社
18 名前:デフォルトの名無しさん mailto:sage [2009/07/03(金) 18:26:58 ] >>16 なるほど、そうですか。残念ですね。 >>17 やっぱり、Java、PHPなんですね。 まだまだ普及というか認められていないんですね。 趣味でしこしこ勉強します。
19 名前:デフォルトの名無しさん [2009/07/03(金) 18:28:17 ] >>18 認めるというか、Rubyにする必要性がないといった感じ
20 名前:デフォルトの名無しさん mailto:sage [2009/07/03(金) 18:43:24 ] Webサービスを作って、ベンチャー起業で金稼ぐのならRubyでも行けるかもしれないが そもそも日本でベンチャーを興すのは難しいらしいしな
21 名前:デフォルトの名無しさん mailto:sage [2009/07/03(金) 18:55:04 ] >>19 それだと今後も期待薄ですね。 >>20 限られた人らのツールになりそう。
22 名前:デフォルトの名無しさん mailto:sage [2009/07/03(金) 22:01:18 ] >>9 >remove_instance_variable ありがとうございます。これってprivateメソッドだったんですね。 Object.new.methods.grep(/instance/) で探してたので、見つけられませんでした。 精進します。
23 名前:デフォルトの名無しさん mailto:sage [2009/07/03(金) 22:21:11 ] とりあえず、rubyの遅さとメモリ量の食い方で、自分のサーバーで適当に 遊んでるくらいしか使ってないなー。 あっ、後初期設定だるいかなー apacheにfast cgi入れてうんたらかんたらは面倒〜
24 名前:デフォルトの名無しさん mailto:sage [2009/07/03(金) 22:45:14 ] だれか RAA - net-yjwsを持ってない?もしくは配布している所知らない? raa.ruby-lang.org/project/net-yjws/ のファイル配布先であるmoonwolfのサーバが死んでるみたいで手に入らない. インターネットアーカイブで引っこ抜けるかなと思ったけどそっちでもダメでした.
25 名前:デフォルトの名無しさん mailto:sage [2009/07/03(金) 23:48:07 ] 下にある 0.0.20060523.tar.gz のリンクはruby-lang.orgに 置かれている実tar玉で、生きているようだ。 とりあえずそれで凌げるかどうか試してみては?
26 名前:24 mailto:sage [2009/07/04(土) 01:06:42 ] >>25 そっちもブラウザでやってみたんですけどFirefoxでは 内容符号化 (Content-Encoding) に問題があります IEとChromeではつながらず。 UnixからwgetではDLできたけど展開できませんでした
27 名前:デフォルトの名無しさん mailto:sage [2009/07/04(土) 01:37:19 ] リンクは...tar.gzになってるけど中身はHTMLみたい
28 名前:デフォルトの名無しさん mailto:sage [2009/07/04(土) 12:42:27 ] 質問があります $stdoutでファイルを指定し、そこに結果を入れるようにしたのですが、 できたファイルを開くと、結果の頭部分しか入っておらず、困っています エラーはでていませんし、標準出力の場合や、リダイレクトをした場合は結果の全てがきちんと出力されています プログラムは以下です sv = STDOUT.dup $stdout = File.open("ファイル名", "w") 結果を出力 $stdout = sv わかる方いましたら教えていただけないでしょうか OSはLinuxでRubyのバージョンは1.8.5です
29 名前:デフォルトの名無しさん mailto:sage [2009/07/04(土) 12:48:04 ] flushしてみたら?
30 名前:デフォルトの名無しさん mailto:sage [2009/07/04(土) 12:52:48 ] ・ ファイルに出力するよモードになったときはファイルに出力 ・ ファイルに出力するよモードじゃないときは標準出力に出力 ・ これを $stdout への代入だけで切り替えたい という処理をしたいと推測 いちいち>>29 するのはコードが面倒になると思うので、 sync=true したファイルIOオブジェクトを $stdout に指定しろ
31 名前:デフォルトの名無しさん mailto:sage [2009/07/04(土) 12:55:32 ] >>28 本筋とは関係ないけど、たぶんそれSTDOUTをdupする必要はないな $stdout = STDOUT でおk
32 名前:デフォルトの名無しさん mailto:sage [2009/07/04(土) 12:59:17 ] 元に戻すならsv = $stdoutのほうがいいような まあどちらにしてもdupは要らんね
33 名前:デフォルトの名無しさん mailto:sage [2009/07/04(土) 13:07:04 ] >>29 やってみましたが、結果は同じでした・・ >>30 下手な質問で申し訳ありません; >・ ファイルに出力するよモードになったときはファイルに出力 >・ ファイルに出力するよモードじゃないときは標準出力に出力 >・ これを $stdout への代入だけで切り替えたい で合っています が、やはりできませんでした すいません・・ >>31 >>32 わかりました やり直してみます みなさんありがとうございます
34 名前:デフォルトの名無しさん mailto:sage [2009/07/04(土) 13:29:26 ] f = File.open("ファイル名", "w") f.sync = true $stdout = f これでなんとかなんね?
35 名前:デフォルトの名無しさん mailto:sage [2009/07/04(土) 13:42:35 ] >>34 できませんね… 自分がLinux初心者のため、出来たファイルを開く際、文字コードに関する不具合(文字化けとか)によって 中身がおかしいのかもしれないです 別の方法でやってみますね 助けてくださってありがとうございました
36 名前:デフォルトの名無しさん [2009/07/04(土) 13:49:26 ] よくわからんけど、グローバルな$stdoutに代入していいのかにょ?
37 名前:デフォルトの名無しさん mailto:sage [2009/07/04(土) 13:51:54 ] 代入できるように定数とグローバルの両方が存在してる
38 名前:デフォルトの名無しさん [2009/07/04(土) 13:53:38 ] >>37 おk把握
39 名前:デフォルトの名無しさん [2009/07/04(土) 15:54:40 ] たのしいRubyを読んでいます。 クラスとモジュールの違いがよく理解きないです。 解りやすく教えてほしいです。
40 名前:デフォルトの名無しさん mailto:sage [2009/07/04(土) 16:01:27 ] 違う本よめ
41 名前:デフォルトの名無しさん mailto:sage [2009/07/04(土) 16:05:53 ] クラス 普段使うもの 処理を分類したもの(メソッド)を起動するオブジェクトの生成器 基本的にはこれだけで生きていける モジュール 普段使わない ガチ初心者のうちは自分から作らなくてもいいというかむしろ忘れろ initialize できない(そもそも作れない) クラスAとクラスBに共通メソッド群Mを持たせたいという場合、Mをモジュールにすると楽 クラスMを作って継承しても用が済むことがほとんどだが、モジュールにしたほうが本当はいい
42 名前:デフォルトの名無しさん mailto:sage [2009/07/04(土) 16:07:53 ] クラスはモジュールの一種 つまりクラスはモジュールとしての機能を全て持っていて その上で、特別にインスタンス化することができる 具体的には、あのnewってのができる
43 名前:デフォルトの名無しさん mailto:sage [2009/07/04(土) 16:09:21 ] 必ず親があるのがクラス(親を指定しなければObject)、親のないのがモジュール。 継承して使うのがクラス、includeして使うのがモジュール。 Classクラスのインスタンスなのがクラス、Moduleクラスのインスタンスなのがモジュール。 ModuleはClassのスーパークラス。
44 名前:デフォルトの名無しさん mailto:sage [2009/07/04(土) 16:18:15 ] 初心者スレ的には>>41 に一票 まーあれだ、半年くらいダラダラ使ってればある日突然わかるからあんま心配すんな 日常的には「よくわからんけど○○らしい」程度の理解で充分
45 名前:デフォルトの名無しさん mailto:sage [2009/07/04(土) 17:02:41 ] >>28 同じようなことしてるけど、 #最初 $stdout=File.open("filename""w") 出力 #最後 $stdout=STDOUT ってなってた。
46 名前:デフォルトの名無しさん mailto:sage [2009/07/04(土) 17:35:52 ] ある日突然オブジェクト脳が閃く感じか。
47 名前:デフォルトの名無しさん mailto:sage [2009/07/04(土) 18:42:42 ] すべてはClassクラスのインスタンスということで良いのでしょうか? Ruby1.9.1では、BasicObject、Object、Class、Moduleもすべて。
48 名前:デフォルトの名無しさん mailto:sage [2009/07/04(土) 19:01:08 ] …あんまそんなこと気にしないほうがええぞ
49 名前:デフォルトの名無しさん mailto:sage [2009/07/04(土) 19:17:11 ] >>48 に同意しつつも答えとく >>47 >すべてはClassクラスのインスタンス とりあえず class Foo; end は暗黙的にObjectを継承するし obj = Foo.new のobjはObjectインスタンスの性質も多く含むけど(というかこの場合そのまんま) あくまでもobjはFooのインスタンスであってObjectのインスタンスとは呼ばない という前置きをした上で 全てのクラスそのものがClassインスタンスっていうのは正しい Object.new.class #=> Object Object.class #=> Class 「インスタンスを生成する役割を持つもの」がClassクラスのインスタンスであり Rubyではそれを「クラス」と呼ぶ でもそれによって生成されたインスタンスは「クラス」ではない もちろんClassのインスタンスという特例は除く
50 名前:デフォルトの名無しさん mailto:sage [2009/07/04(土) 19:39:58 ] >>49 Rubyではすべてがオブジェクトであるという文言が 気になった次第です。 >>48 Classクラスのインスタンスはクラスオブジェクト(Object、Fooなど) ということになるんですね。 クラス(Class)のインスタンスがクラスオブジェクト(Foo)で、 クラスオブジェクトFooもまたインスタンスを生成してと。。 やはり必要時以外は考えないようにします。
51 名前:39 [2009/07/04(土) 22:06:38 ] みなさん、ありがとうございました。 けっこう、すっきりしました。
52 名前:デフォルトの名無しさん mailto:sage [2009/07/04(土) 23:11:56 ] その辺のぼやーんとした認識に直視せざるを得なくなる本が プログラミング言語Ruby 凄い濃い本だが確かに初心者にはお勧め出来ない
53 名前:デフォルトの名無しさん mailto:sage [2009/07/04(土) 23:38:46 ] まああれは どの言語にも一冊はあるような「しっかりした本」だから・・・・・・ 細かい挙動を確かめたくなった時に、手にとればいい
54 名前:デフォルトの名無しさん mailto:sage [2009/07/05(日) 12:18:05 ] class Widget def initialize(x, y) @x = x @y = y end end インスタンス変数に @x = x と書くのと self.x = x は同じ意味ですか?
55 名前:デフォルトの名無しさん mailto:sage [2009/07/05(日) 12:26:40 ] この場合のメソッド定義内で書く self.x = は インスタンスメソッド Widget#x= を起動する インスタンスメソッド Widget#x= の内部でインスタンス変数 @x にアクセスしてるかどうかは x= の定義による
56 名前:デフォルトの名無しさん mailto:sage [2009/07/05(日) 12:29:15 ] おそらく、自メソッドの引数 x と被るインスタンスメソッド x を起動したいんだが、 そのまま x とだけ書くと引数の変数 x にアクセスしてしまうので それを避けるために明示的にメソッド x を指示したいのだろう
57 名前:デフォルトの名無しさん mailto:sage [2009/07/05(日) 12:39:56 ] class C def initialize(x) puts "x は #{x} です" puts "self.x は #{self.x} です" end def x return "メソッド" end end C.new('引数') 結果 x は 引数 です self.x は メソッド です
58 名前:デフォルトの名無しさん mailto:sage [2009/07/05(日) 12:44:38 ] >>55 >>56 レスありがとうございます。 セッター(x=、attr_writer、attr_accessor) を明示的に定義しなければ、self.x は def x=(x) @x = x end が実行されたのと等価なので、結果は同じということですよね。
59 名前:デフォルトの名無しさん mailto:sage [2009/07/05(日) 12:49:26 ] >>57 レスありがとうございます。 僕はゲッター、セッター hoge = self.x self.x = poge がメソッドだというのを忘れがちです。
60 名前:58 mailto:sage [2009/07/05(日) 12:51:43 ] >>58 セッター(x=、attr_writer、attr_accessor) を明示的に定義しなければ これはウソでした。 セッターattr_writer、attr_accessor は必要です。
61 名前:デフォルトの名無しさん mailto:sage [2009/07/05(日) 13:19:27 ] 他の言語にあるセッターやゲッターというものはRubyには存在しない あれはただの値を返すメソッドで、attr* はメソッド定義を肩代わりする略記に過ぎない module AttrReader def attr_reader(arr) arr.each do |method_name| eval("def #{method_name} return @#{method_name} end") end end end class C include AttrReader attr_reader([:x]) end と class C attr_reader :x end はリクツ上おおむね同じ動作をする attr* を使う動作上のメリットというのは何もない メソッド定義書くのがちょっと短縮されるというだけだったりする
62 名前:デフォルトの名無しさん mailto:sage [2009/07/05(日) 13:40:03 ] >>61 なるほど。 だからreader、writerと呼ばれるんですかね。
63 名前:デフォルトの名無しさん [2009/07/05(日) 14:36:28 ] Ruby作者ってしゃべりかたが変わっていないか? なにか障害をもっているの?
64 名前:デフォルトの名無しさん [2009/07/05(日) 14:38:34 ] 早口なだけじゃね? 俺もリアル世界では早口って言われる。 相手が聞き取りやすいようにゆっくり話すように心がけているが ...orz
65 名前:デフォルトの名無しさん mailto:sage [2009/07/05(日) 14:41:45 ] >>63 matzのことなら、最低限一般水準程度には普通に、また俺的にはとても知性的にかつ フレンドリーに喋ったり発信しているように見受けられる まあコミュニケーションには受け手の問題もあるのは知ってるので、>>63 の見解も 頭から否定する気はないが
66 名前:デフォルトの名無しさん mailto:sage [2009/07/05(日) 14:43:16 ] 誰だったかが言うには 「頭の回転が速すぎて口が追いついてない」
67 名前:デフォルトの名無しさん [2009/07/05(日) 14:48:42 ] どうしてIBMとか大企業に就職しなかったの?
68 名前:デフォルトの名無しさん mailto:sage [2009/07/05(日) 14:49:37 ] 隔離スレでやれ
69 名前:デフォルトの名無しさん mailto:sage [2009/07/05(日) 14:52:51 ] ここだな。同意 ttp://pc12.2ch.net/test/read.cgi/tech/1246174168/
70 名前:デフォルトの名無しさん [2009/07/05(日) 14:53:20 ] >>67 飼い慣らされると痛い目に遭うから、だと思う。
71 名前:デフォルトの名無しさん mailto:sage [2009/07/05(日) 15:08:55 ] >>67 在学中に有名になってしまって、就職する必要がなくなった。
72 名前:デフォルトの名無しさん mailto:sage [2009/07/05(日) 16:48:57 ] >>71 ?? chainmail?
73 名前:デフォルトの名無しさん mailto:sage [2009/07/05(日) 19:32:27 ] 単に入社試験で落とされたとかだろ。
74 名前:デフォルトの名無しさん mailto:sage [2009/07/05(日) 19:34:54 ] クリエイターとして生きることができた人に「どうして就職しなかったんですか」というのは単なる愚問だ 就職しなくても生きられたから就職しなかったというだけに過ぎない
75 名前:デフォルトの名無しさん mailto:sage [2009/07/05(日) 20:40:04 ] なんか特定の条件のときに特定の TestCase クラスのユニットテストを実行しないという芸当は可能ですか
76 名前:デフォルトの名無しさん mailto:sage [2009/07/05(日) 20:43:40 ] test_ で始まるメソッドを undef すればいいんじゃね
77 名前:デフォルトの名無しさん mailto:sage [2009/07/05(日) 21:30:21 ] 既存のクラスのメソッド定義を、include のようなものであとから書き換えることはできますか? 対象となるクラスは既に他のクラスを継承してるので、追加メソッド群をクラスにして継承してもらうことはできません。
78 名前:デフォルトの名無しさん mailto:sage [2009/07/05(日) 21:42:39 ] 該当クラスのオブジェクトが生成されるより前に、 「該当クラス定義を再オープンしてメソッド定義を書き換える」というeval系の何かを適当に実行
79 名前:デフォルトの名無しさん mailto:sage [2009/07/05(日) 21:55:03 ] >>77 普通にdefするだけじゃだめなの? class A < S end class A def extra_method end end もしくは、単にincludeするとか
80 名前:デフォルトの名無しさん mailto:sage [2009/07/05(日) 22:06:15 ] >>79 includeでクラスのメソッド定義を上書きできるとは初耳だな
81 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 01:01:03 ] >>80 superclassよりは優先されるから一応は出来る 自身のメソッド定義は覆せないけどね 「既存のクラス」の名前を決め打ちで利用されてるのではなければ もう一度継承して(「既存のクラス」をsuperclassにして)からincludeすればいい 決め打ちされてるなら・・・>>79 の方法になるんじゃないかなぁ とてもお勧めできない方法 class Foo; end class Bar < Foo; end Foo = Bar Foo.new.class #=> Bar
82 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 01:18:46 ] >>77 の質問の意味がいまいち良くわからないんだよねえ 具体的なコード片とかが無いとどう困ってるのかわからなくて答えにくい
83 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 01:24:10 ] まあ全くお勧めしないが module Hoge def included(c) c.class_eval do alias fuga_original fuga def fuga; (処理) end end end end とかやったのをincludeすればいけるかもしれない
84 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 02:44:40 ] open-uriに関する質問です。 特定のurlで下記のスクリプトがエラーを出力します。 エラー文: `close': closed stream (IOError) ============= ここから ============ require 'open-uri' require 'zlib' header = {'accept-encoding' => 'gzip'} url = 'gimpo.2ch.net/bakery/subject.txt ' # errorが起きる url2 = 'anchorage.2ch.net/live/subject.txt ' # errorが起きない url3 = 'gimpo.2ch.net/salt/subject.txt ' # errorが起きる open(url, header) do |io| Zlib::GzipReader.wrap(io) do |gz| puts gz.read # urlの中身が出力されたあとにerrorが起きる end end ============= ここまで ============ open-uri, zlib, 2chの鯖のどこに問題があるのでしょうか? openのブロック付き呼び出しの中でさらに別のIOオブジェクトをブロック付きで呼び出していることが原因なのかと考えたのですが、 特定のurlでのみ起きる理由が分かりません・・・。
85 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 02:46:08 ] ちなみに↓のスクリプトではエラーが起きません。 ============= ここから ============ require 'open-uri' require 'zlib' header = {'accept-encoding' => 'gzip'} url = 'gimpo.2ch.net/bakery/subject.txt ' # errorが起きる url2 = 'anchorage.2ch.net/live/subject.txt ' # errorが起きない url3 = 'gimpo.2ch.net/salt/subject.txt ' # errorが起きる open(url, header) do |io| Zlib::GzipReader.wrap(io).readlines.each do |line| puts line end end ============= ここまで ============
86 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 03:27:42 ] >>84 Zlib::GzipReader.wrapが自動的にioをcloseし さらにopenのブロック実行後にioをcloseしようとするから IOErrorが出るのは正しい動作 url2でエラーが出ない方がおかしいんだけど何故かはわからん 要するにcloseが二回実行されないようにすればいいんだが それはリファレンスマニュアルでZlib::GzipReader.wrapの所を嫁
87 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 04:02:24 ] >86 レスありがとうございます。 解決策のほうも分かりました。 ところで>85の例でエラーが出なかった理由は Zlib::GzipReader.wrapがcloseされていなかったからioもcloseされず、ioがopenによって正しくcloseされたからという理解でよろしいでしょうか? IOオブジェクトを用いる場合には file = IO.open(foo) begin <処理> ensure file.close end IO.open(foo) do |io| <処理> end のどちらかで記述するというのが常識ですが、 IO.open(foo).read のような使い方をするとそのIOオブジェクトはcloseすることができなくなってしまうのでしょうか? 重ね重ねの質問ですが、長らくの疑問で調べても分からなかったのでご回答いただけるとありがたいです。
88 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 04:52:41 ] > ところで>85の例でエラーが出なかった理由は ... あってる > IO.open(foo).read ... これではIOインスタンスへの参照がないからcloseしようがない、開きっぱなし data = (io = IO.open(foo)).read とすればio.close出来るけど普通はIO.read(foo)とするな ほっとけばGCが何とかしてくれると聞いたような違ったような?
89 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 05:08:25 ] ぬ `close': closed stream (IOError) は、おーざっぱには 「閉じようと思ったIOオブジェクトが何者かによって既に閉じられてました姉さん事件です」 エラーだ Zlib の close は引数の IO オブジェクトごと close する 通常は超親切機能なんだが、引数の IO オブジェクトがブロックつきだった場合、 IO 側のメソッドのブロックの ensure で行われる io.close で「既に閉じられてた」エラーが起こる Zlib のブロックの最後で明示的に Zlib::GzipFile#finish を呼ぶと、厄介な Zlib::GzipFile#close は起動されない …というようなことが、Zlib::GzipReader の GzipReader.wrap のマニュアルのとこに書いてあるぞ ttp://www.ruby-lang.org/ja/man/html/Zlib_GzipReader.html#GzipReader.2ewrap >>84 require 'open-uri' require 'zlib' header = {'accept-encoding' => 'gzip'} url = 'gimpo.2ch.net/bakery/subject.txt ' url2 = 'anchorage.2ch.net/live/subject.txt ' url3 = 'gimpo.2ch.net/salt/subject.txt ' [url,url2,url3].each do |url| open(url, header) do |io| Zlib::GzipReader.wrap(io) do |gz| p gz.read gz.finish # ここ! end end end
90 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 09:30:36 ] UTF-8 文字列に対する NKF.guess がだいたいいい感じに動作する文字数って何文字くらい? irb> NKF.guess("ねこだいす") 5 irb> NKF.guess("ねこだいすき") 6 irb> NKF.guess("ねこだいすきっ") 5 とかいう結果でちょっとぐんにょりしてるので
91 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 09:36:09 ] これは非常に有名な話だが、読点を入れると NKF.guess の誤認識の確率が素晴らしく減る irb> NKF.guess("ねこ、だ") 6 irb> NKF.guess("ねこ、だい") 6 irb> NKF.guess("ねこ、だいす") 6 irb> NKF.guess("ねこ、だいすき") 6 irb> NKF.guess("ねこ、だいすきっ") 6 irb> NKF.guess("、") 6 ということで、読点入れた文章使え
92 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 09:37:46 ] nkfにバグのあるバージョンのrubyを使ってないか? 最近ruby-talkでそんな話題があった気がするが。
93 名前:92 mailto:sage [2009/07/06(月) 09:39:16 ] 1.8.7 patchlevel 160 ではこんな感じ irb(main):002:0> NKF.guess("ねこだいす") => 6 irb(main):003:0> NKF.guess("ねこだいすき") => 6 irb(main):004:0> NKF.guess("ねこだいすきっ") => 6
94 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 09:55:04 ] 文字列を自由に設定できるのなら読点入れるのが間違いないとは思う
95 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 09:58:22 ] それならそもそもguessする必要ないだろ
96 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 10:19:41 ] 字句解析には、まともに使えないってことだな。
97 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 10:28:41 ] 文字コード推定と字句解析の関連をkwsk
98 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 10:52:17 ] Mule や Emacs が、読み込んだファイルの文字コードを自動判定するのは ご存じだと思うが、Meadow 2 や Meadow 3は、 UTF-8 のファイルの文字コードを、けっこう間違える。 一方、秀丸はほぼ絶対間違えない。 これらの違いは何だろうかということと、同じような実装をNKF でもできないのかな?と思った。
99 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 10:55:06 ] ほうほう、つまり CP932 と UTF-8 以外の優先度を下げろと
100 名前:98 mailto:sage [2009/07/06(月) 11:05:55 ] いや、そういうつもりはない、というか秀丸とかは、内部でそういう実装になっていたのか。 知らなかったよ
101 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 11:12:29 ] 結果的に正しく判断される確率が高い方がいい
102 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 12:04:51 ] そのためには文脈情報が要るんだよ HTML だったら charset 読んでみるとか 句読点が改行文字の直前にあったら日本語だと思ってみるとか 東欧辞書にマッチするバイト列が頻出したら Latin-2 だと思ってみるとか Iconv が guess に該当する機能を一切提供してないのは手抜きじゃなくて必然 多エンコーディングに対応すればするほど指数関数的に推測のコストは上がる 日本語だけ取っても Shift_JIS と CP932 と EUC-JP と EUC-JP-MS の4つを区別するのは至難 っていうか規格をちょっとずつ混ぜるなめんどくさいから あとケータイ絵文字入り文字列をキャリア情報なし端末情報なしの素で送ってくる奴は即死刑で
103 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 12:33:21 ] 次の質問の人どうぞ
104 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 15:37:50 ] /usr/local/lib/ruby1.9/1.9.1/minitest/unit.rb:359:in `puke': incompatible character encodings: UTF-8 and ASCII-8BIT (Encoding::CompatibilityError) イライラ
105 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 15:54:27 ] rrseをUTF8で使うにはどうすればいいですか?
106 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 15:56:26 ] >>104 Ruby1.9向けテストで「なんかどっか書き間違ってる」時に出るやつだな 具体的にどのへんの行で詰まってるとかヒントぜんぜんなし かろうじて -v でテストのメソッド名が出るくらい
107 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 15:58:00 ] >>105 rdoc のファイルと同じエンコーディングを -K とかで指定すればいいんじゃね
108 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 16:09:03 ] >89 詳細な解説ありがとうございます。 ためになりました。 >88 >普通はIO.read(foo)とするな IOオブジェクトを簡単に読み取るにはこの方法を使えばいいんですね。 しかしopen-uriで拡張されたopenには同等のメソッドがありませんね。 URI.parse(foo)がIO.read(foo)と同等のことができますが、 URI.parseはHTTPリクエストのオプションをつけて動かすことができないんですよね。 URI.parse(uri, 'hogehoge' => 'foobar')のように。 アドバイスをいただき>84での問題は解決したのですが次の問題が発生してしまいました。。
109 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 16:09:48 ] 下記のスクリプトがエラーを吐きます。 エラー文: `initialize': buffer error (Zlib::BufError) 困ったことに、通ったり通らなかったりします。 原因はたぶんですが2chのサーバが出力しているgzip圧縮したsubject.txtのほうだと思います。 板内のスレいずれかにカキコミがあればsubject.txtは書き換わるため、通る場合と通らない場合があるのだと予想しています。 しかしエラー文の意味がよく分からず、どのように回避すればよいのかが分かりません。 ちなみに拾ってきたgzip化subject.txtファイルをHDDに書き込んでアーカイバで開くと正しく読み取れています。 ============= ここから ============ require 'open-uri' require 'zlib' header = {'accept-encoding' => 'gzip'} url = 'gimpo.2ch.net/bakery/subject.txt ' # errorが一度も起きていない url2 = 'gimpo.2ch.net/kagu/subject.txt ' # errorが起きたり起こらなかったりする open(url, header) do |io| Zlib::GzipReader.wrap(io) do |gz| puts gz.read # urlの中身が出力されたあとにerrorが起きる end end ============= ここまで ============
110 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 16:19:50 ] >>109 原因は一発でわかったが、そろそろあんま話したくない HTTPの知識のない状態でなに作る気なん?
111 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 16:23:31 ] 別にいいじゃん。初心者スレなんだし。 答えるのいやなら他行けば?
112 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 16:25:29 ] libwww-perlの轍踏む気にはならんね
113 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 16:29:29 ] まあサイトや回線にどんだけ負荷かけて裁判起こされようが知ったこっちゃないが、 このへんがわかんないのはそもそも辛いと思うんだがどう open-uri で open してテキストを read する以外の事をしようと思うなら、別途勉強がいると思う
114 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 16:36:36 ] 2chにアクセスするアプリケーションは自力で調べて作ってもらうというのが一応不文律だったりする
115 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 16:43:06 ] >>109 open-uriは便利に見えるけどハマると厄介、net/httpの使い方をおぼえろ res = Net::HTTP.get_response(URI(url)) txt = res.body if res['content-encoding'] =~ /gzip/ txt = Zlib::GzipReader.wrap(StringIO.new(txt)) {|gz| gz.read } end puts txt >>110 原因を教えてもらえないだろうか? うちの環境では例外が発生しないので問題がわからない
116 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 16:43:45 ] content-encoding見てないのはマズいと思うけど >>109 はHTTPレベルの問題じゃないような
117 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 16:45:14 ] 付け加えておくとgzじゃないものを食わせた時は Zlib::GzipFile::Error: not in gzip format
118 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 16:47:52 ] もなじら名乗ってない時点で問題外
119 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 16:49:01 ] >109のスクリプトを書き間違えていました。 ============= ここから ============ require 'open-uri' require 'zlib' header = {'accept-encoding' => 'gzip'} url = 'gimpo.2ch.net/bakery/subject.txt ' # errorが一度も起きていない url2 = 'gimpo.2ch.net/kagu/subject.txt ' # errorが起きたり起こらなかったりする open(url, header) do |io| Zlib::GzipReader.wrap(io) do |gz| puts gz.read # urlの中身が出力されたあとにerrorが起きる gz.finish #<= 書き忘れ end end ============= ここまで ============ >110 2chのスレのdatを収集するプログラムです。 たまに気がつくとスレが1001になってdat落ちしてしまって、最後に開いた地点までしか読めなくなるのが悲しいので、 過去に開いたことがあるスレを定期的に拾いなおしてくれるプログラムを作りたいと思いまして。 プログラム自体は完成していて意図した通りに動くのですが、 転送量を少しでも削減したくてdatだけではなくsubject.txtを拾うときにgzip化しようと欲を出したらうまくいかなくなりました。
120 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 16:54:41 ] スレ更新をせず書き込んでしまいました。 >113 一応、DLする度にsleep 1.0 を入れています。 これでは不十分でしょうか? >114 それは大変失礼しました。 今後は自力解決したいと思います。 >115 datの取得ではnet/httpを使っています。 一つのdomainから複数のファイルを拾うときにはnet/http, 1つのファイルを拾うだけならopen-uriというふうに使い分けていました。
121 名前:115 mailto:sage [2009/07/06(月) 17:17:01 ] header渡してなかった txt = URI(url).read(header) if txt.content_encoding.include?('gzip') :