Ruby 初心者スレッド ..
[2ch|▼Menu]
49:デフォルトの名無しさん
09/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:デフォルトの名無しさん
09/07/04 19:39:58
>>49
Rubyではすべてがオブジェクトであるという文言が
気になった次第です。

>>48
Classクラスのインスタンスはクラスオブジェクト(Object、Fooなど)
ということになるんですね。

クラス(Class)のインスタンスがクラスオブジェクト(Foo)で、
クラスオブジェクトFooもまたインスタンスを生成してと。。

やはり必要時以外は考えないようにします。

51:39
09/07/04 22:06:38
みなさん、ありがとうございました。
けっこう、すっきりしました。


52:デフォルトの名無しさん
09/07/04 23:11:56
その辺のぼやーんとした認識に直視せざるを得なくなる本が
プログラミング言語Ruby
凄い濃い本だが確かに初心者にはお勧め出来ない

53:デフォルトの名無しさん
09/07/04 23:38:46
まああれは
どの言語にも一冊はあるような「しっかりした本」だから・・・・・・
細かい挙動を確かめたくなった時に、手にとればいい

54:デフォルトの名無しさん
09/07/05 12:18:05
class Widget
def initialize(x, y)
@x = x
@y = y
end
end

インスタンス変数に @x = x と書くのと self.x = x は同じ意味ですか?

55:デフォルトの名無しさん
09/07/05 12:26:40
この場合のメソッド定義内で書く self.x = は インスタンスメソッド Widget#x= を起動する
インスタンスメソッド Widget#x= の内部でインスタンス変数 @x にアクセスしてるかどうかは x= の定義による

56:デフォルトの名無しさん
09/07/05 12:29:15
おそらく、自メソッドの引数 x と被るインスタンスメソッド x を起動したいんだが、
そのまま x とだけ書くと引数の変数 x にアクセスしてしまうので
それを避けるために明示的にメソッド x を指示したいのだろう

57:デフォルトの名無しさん
09/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:デフォルトの名無しさん
09/07/05 12:44:38
>>55
>>56
レスありがとうございます。

セッター(x=、attr_writer、attr_accessor) を明示的に定義しなければ、self.x は

def x=(x)
@x = x
end

が実行されたのと等価なので、結果は同じということですよね。

59:デフォルトの名無しさん
09/07/05 12:49:26
>>57
レスありがとうございます。

僕はゲッター、セッター

hoge = self.x
self.x = poge

がメソッドだというのを忘れがちです。

60:58
09/07/05 12:51:43
>>58
セッター(x=、attr_writer、attr_accessor) を明示的に定義しなければ

これはウソでした。

セッターattr_writer、attr_accessor は必要です。

61:デフォルトの名無しさん
09/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:デフォルトの名無しさん
09/07/05 13:40:03
>>61
なるほど。
だからreader、writerと呼ばれるんですかね。

63:デフォルトの名無しさん
09/07/05 14:36:28
Ruby作者ってしゃべりかたが変わっていないか?
なにか障害をもっているの?

64:デフォルトの名無しさん
09/07/05 14:38:34
早口なだけじゃね?

俺もリアル世界では早口って言われる。
相手が聞き取りやすいようにゆっくり話すように心がけているが ...orz

65:デフォルトの名無しさん
09/07/05 14:41:45
>>63
matzのことなら、最低限一般水準程度には普通に、また俺的にはとても知性的にかつ
フレンドリーに喋ったり発信しているように見受けられる
まあコミュニケーションには受け手の問題もあるのは知ってるので、>>63の見解も
頭から否定する気はないが

66:デフォルトの名無しさん
09/07/05 14:43:16
誰だったかが言うには
「頭の回転が速すぎて口が追いついてない」

67:デフォルトの名無しさん
09/07/05 14:48:42
どうしてIBMとか大企業に就職しなかったの?

68:デフォルトの名無しさん
09/07/05 14:49:37
隔離スレでやれ

69:デフォルトの名無しさん
09/07/05 14:52:51
ここだな。同意
スレリンク(tech板)

70:デフォルトの名無しさん
09/07/05 14:53:20
>>67
飼い慣らされると痛い目に遭うから、だと思う。

71:デフォルトの名無しさん
09/07/05 15:08:55
>>67
在学中に有名になってしまって、就職する必要がなくなった。

72:デフォルトの名無しさん
09/07/05 16:48:57
>>71
??
chainmail?


73:デフォルトの名無しさん
09/07/05 19:32:27
単に入社試験で落とされたとかだろ。

74:デフォルトの名無しさん
09/07/05 19:34:54
クリエイターとして生きることができた人に「どうして就職しなかったんですか」というのは単なる愚問だ
就職しなくても生きられたから就職しなかったというだけに過ぎない

75:デフォルトの名無しさん
09/07/05 20:40:04
なんか特定の条件のときに特定の TestCase クラスのユニットテストを実行しないという芸当は可能ですか

76:デフォルトの名無しさん
09/07/05 20:43:40
test_ で始まるメソッドを undef すればいいんじゃね

77:デフォルトの名無しさん
09/07/05 21:30:21
既存のクラスのメソッド定義を、include のようなものであとから書き換えることはできますか?
対象となるクラスは既に他のクラスを継承してるので、追加メソッド群をクラスにして継承してもらうことはできません。

78:デフォルトの名無しさん
09/07/05 21:42:39
該当クラスのオブジェクトが生成されるより前に、
「該当クラス定義を再オープンしてメソッド定義を書き換える」というeval系の何かを適当に実行

79:デフォルトの名無しさん
09/07/05 21:55:03
>>77
普通にdefするだけじゃだめなの?

class A < S
end

class A
 def extra_method
 end
end

もしくは、単にincludeするとか

80:デフォルトの名無しさん
09/07/05 22:06:15
>>79
includeでクラスのメソッド定義を上書きできるとは初耳だな

81:デフォルトの名無しさん
09/07/06 01:01:03
>>80
superclassよりは優先されるから一応は出来る
自身のメソッド定義は覆せないけどね

「既存のクラス」の名前を決め打ちで利用されてるのではなければ
もう一度継承して(「既存のクラス」をsuperclassにして)からincludeすればいい

決め打ちされてるなら・・・>>79の方法になるんじゃないかなぁ

とてもお勧めできない方法
class Foo; end
class Bar < Foo; end
Foo = Bar
Foo.new.class #=> Bar

82:デフォルトの名無しさん
09/07/06 01:18:46
>>77の質問の意味がいまいち良くわからないんだよねえ
具体的なコード片とかが無いとどう困ってるのかわからなくて答えにくい

83:デフォルトの名無しさん
09/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:デフォルトの名無しさん
09/07/06 02:44:40
open-uriに関する質問です。
特定のurlで下記のスクリプトがエラーを出力します。
エラー文: `close': closed stream (IOError)

============= ここから ============
require 'open-uri'
require 'zlib'
header = {'accept-encoding' => 'gzip'}

url = 'URLリンク(gimpo.2ch.net)' # errorが起きる
url2 = 'URLリンク(anchorage.2ch.net)' # errorが起きない
url3 = 'URLリンク(gimpo.2ch.net)' # 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:デフォルトの名無しさん
09/07/06 02:46:08
ちなみに↓のスクリプトではエラーが起きません。

============= ここから ============
require 'open-uri'
require 'zlib'
header = {'accept-encoding' => 'gzip'}

url = 'URLリンク(gimpo.2ch.net)' # errorが起きる
url2 = 'URLリンク(anchorage.2ch.net)' # errorが起きない
url3 = 'URLリンク(gimpo.2ch.net)' # errorが起きる

open(url, header) do |io|
 Zlib::GzipReader.wrap(io).readlines.each do |line|
  puts line
 end
end
============= ここまで ============

86:デフォルトの名無しさん
09/07/06 03:27:42
>>84
Zlib::GzipReader.wrapが自動的にioをcloseし
さらにopenのブロック実行後にioをcloseしようとするから
IOErrorが出るのは正しい動作
url2でエラーが出ない方がおかしいんだけど何故かはわからん

要するにcloseが二回実行されないようにすればいいんだが
それはリファレンスマニュアルでZlib::GzipReader.wrapの所を嫁

87:デフォルトの名無しさん
09/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:デフォルトの名無しさん
09/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:デフォルトの名無しさん
09/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 のマニュアルのとこに書いてあるぞ
URLリンク(www.ruby-lang.org)

>>84
require 'open-uri'
require 'zlib'
header = {'accept-encoding' => 'gzip'}

url = 'URLリンク(gimpo.2ch.net)'
url2 = 'URLリンク(anchorage.2ch.net)'
url3 = 'URLリンク(gimpo.2ch.net)'

[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:デフォルトの名無しさん
09/07/06 09:30:36
UTF-8 文字列に対する NKF.guess がだいたいいい感じに動作する文字数って何文字くらい?

irb> NKF.guess("ねこだいす")
5
irb> NKF.guess("ねこだいすき")
6
irb> NKF.guess("ねこだいすきっ")
5

とかいう結果でちょっとぐんにょりしてるので

91:デフォルトの名無しさん
09/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:デフォルトの名無しさん
09/07/06 09:37:46
nkfにバグのあるバージョンのrubyを使ってないか?
最近ruby-talkでそんな話題があった気がするが。

93:92
09/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:デフォルトの名無しさん
09/07/06 09:55:04
文字列を自由に設定できるのなら読点入れるのが間違いないとは思う

95:デフォルトの名無しさん
09/07/06 09:58:22
それならそもそもguessする必要ないだろ

96:デフォルトの名無しさん
09/07/06 10:19:41
字句解析には、まともに使えないってことだな。

97:デフォルトの名無しさん
09/07/06 10:28:41
文字コード推定と字句解析の関連をkwsk

98:デフォルトの名無しさん
09/07/06 10:52:17
Mule や Emacs が、読み込んだファイルの文字コードを自動判定するのは
ご存じだと思うが、Meadow 2 や Meadow 3は、 UTF-8 のファイルの文字コードを、けっこう間違える。

一方、秀丸はほぼ絶対間違えない。

これらの違いは何だろうかということと、同じような実装をNKF でもできないのかな?と思った。

99:デフォルトの名無しさん
09/07/06 10:55:06
ほうほう、つまり CP932 と UTF-8 以外の優先度を下げろと

100:98
09/07/06 11:05:55
いや、そういうつもりはない、というか秀丸とかは、内部でそういう実装になっていたのか。
知らなかったよ

101:デフォルトの名無しさん
09/07/06 11:12:29
結果的に正しく判断される確率が高い方がいい

102:デフォルトの名無しさん
09/07/06 12:04:51
そのためには文脈情報が要るんだよ

HTML だったら charset 読んでみるとか
句読点が改行文字の直前にあったら日本語だと思ってみるとか
東欧辞書にマッチするバイト列が頻出したら Latin-2 だと思ってみるとか

Iconv が guess に該当する機能を一切提供してないのは手抜きじゃなくて必然
多エンコーディングに対応すればするほど指数関数的に推測のコストは上がる

日本語だけ取っても Shift_JIS と CP932 と EUC-JP と EUC-JP-MS の4つを区別するのは至難
っていうか規格をちょっとずつ混ぜるなめんどくさいから
あとケータイ絵文字入り文字列をキャリア情報なし端末情報なしの素で送ってくる奴は即死刑で

103:デフォルトの名無しさん
09/07/06 12:33:21
次の質問の人どうぞ

104:デフォルトの名無しさん
09/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:デフォルトの名無しさん
09/07/06 15:54:27
rrseをUTF8で使うにはどうすればいいですか?

106:デフォルトの名無しさん
09/07/06 15:56:26
>>104
Ruby1.9向けテストで「なんかどっか書き間違ってる」時に出るやつだな
具体的にどのへんの行で詰まってるとかヒントぜんぜんなし
かろうじて -v でテストのメソッド名が出るくらい

107:デフォルトの名無しさん
09/07/06 15:58:00
>>105
rdoc のファイルと同じエンコーディングを -K とかで指定すればいいんじゃね

108:デフォルトの名無しさん
09/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:デフォルトの名無しさん
09/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 = 'URLリンク(gimpo.2ch.net)' # errorが一度も起きていない
url2 = 'URLリンク(gimpo.2ch.net)' # errorが起きたり起こらなかったりする

open(url, header) do |io|
 Zlib::GzipReader.wrap(io) do |gz|
  puts gz.read # urlの中身が出力されたあとにerrorが起きる
 end
end
============= ここまで ============

110:デフォルトの名無しさん
09/07/06 16:19:50
>>109
原因は一発でわかったが、そろそろあんま話したくない
HTTPの知識のない状態でなに作る気なん?

111:デフォルトの名無しさん
09/07/06 16:23:31
別にいいじゃん。初心者スレなんだし。
答えるのいやなら他行けば?

112:デフォルトの名無しさん
09/07/06 16:25:29
libwww-perlの轍踏む気にはならんね

113:デフォルトの名無しさん
09/07/06 16:29:29
まあサイトや回線にどんだけ負荷かけて裁判起こされようが知ったこっちゃないが、
このへんがわかんないのはそもそも辛いと思うんだがどう
open-uri で open してテキストを read する以外の事をしようと思うなら、別途勉強がいると思う

114:デフォルトの名無しさん
09/07/06 16:36:36
2chにアクセスするアプリケーションは自力で調べて作ってもらうというのが一応不文律だったりする

115:デフォルトの名無しさん
09/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:デフォルトの名無しさん
09/07/06 16:43:45
content-encoding見てないのはマズいと思うけど
>>109はHTTPレベルの問題じゃないような


117:デフォルトの名無しさん
09/07/06 16:45:14
付け加えておくとgzじゃないものを食わせた時は
Zlib::GzipFile::Error: not in gzip format

118:デフォルトの名無しさん
09/07/06 16:47:52
もなじら名乗ってない時点で問題外

119:デフォルトの名無しさん
09/07/06 16:49:01
>109のスクリプトを書き間違えていました。
============= ここから ============
require 'open-uri'
require 'zlib'
header = {'accept-encoding' => 'gzip'}

url = 'URLリンク(gimpo.2ch.net)' # errorが一度も起きていない
url2 = 'URLリンク(gimpo.2ch.net)' # 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:デフォルトの名無しさん
09/07/06 16:54:41
スレ更新をせず書き込んでしまいました。

>113
一応、DLする度にsleep 1.0 を入れています。
これでは不十分でしょうか?

>114
それは大変失礼しました。
今後は自力解決したいと思います。

>115
datの取得ではnet/httpを使っています。
一つのdomainから複数のファイルを拾うときにはnet/http, 1つのファイルを拾うだけならopen-uriというふうに使い分けていました。

121:115
09/07/06 17:17:01
header渡してなかった
txt = URI(url).read(header)
if txt.content_encoding.include?('gzip')
 :


最新レス表示
スレッドの検索
類似スレ一覧
話題のニュース
おまかせリスト
▼オプションを表示
暇つぶし2ch

5385日前に更新/38 KB
担当:undef