トップページ⇒tech
983コメント375KB

Ruby 初心者スレッド Part 41

■ このスレッドは過去ログ倉庫に格納されています
0001京 ◆SsSSsSsSSs 2011/02/10(木) 13:47:51
プログラミング言語Rubyについての、初心者向けスレです。質問・要望・雑談などどうぞ。

★注意★ Ruby 1.9.2 は初心者には若干時期早尚です。初心者には Ruby 1.8.7 を強くお勧めします。
 文字エンコーディング等の外部基礎知識が必要な上、不完全対応の第三者ライブラリでの問題の切り分けが手間です。
 迷う点の少ない1.8.7に習熟→おもむろに1.9.2の変更点のみ重点学習、とすればスムーズに移行できるでしょう。

関連スレやURLは>>2-5あたりを見てください。Ruby on Rails の質問は Webプログラミング板の Rails スレへ。

■質問する人へ
質問する前に次の3つをすること。ここで回答を待つよりそのほうが早い。
 ・エラーメッセージの共通そうな部分やエラーの出るモジュール名でググる
 ・マニュアルで引っかかったクラスの記述を探す http://www.ruby-lang.org/ja/man/
 ・FAQを一応読む http://www.ruby-lang.org/ja/man/?cmd=view;name=Ruby+FAQ
質問には以下を書くこと。へたくそな質問は再提出を要求される。
 ・最終的にやりたいこと(もっとよい方法がある場合が多いので)
 ・エラーメッセージ(自力で訳さずなるべくそのままで)
 ・詳しい内容(「動きません」「うまくできません」では回答しようがない)
 ・実行環境(OS名、Rubyのバージョン(ruby -v でわかる))
回答してくれた人には「ありがとう」のひとことをいってあげて。

■回答する人へ
相手は初心者、根気よく育てるつもりで。質問がへたくそなのも大目にみてあげる。
それができないならこないこと(だって初心者スレだもん)。
 ・既出な質問やFAQは「XXXを読め」でいいので、叩かない&怖がらせない。
 ・わけわかな質問にもエスパー発揮で。できれば質問の仕方を教えるぐらいで。
 ・自信がない回答ならその旨表明すること。誤った回答は初心者じゃ見抜けない。
0151デフォルトの名無しさん2011/02/27(日) 19:35:05.18
>>150
おお・・・それがわかりやすいですね、ありがとう
>>149元コードがバグってました(/ω\) ハズカシー
0152デフォルトの名無しさん2011/02/27(日) 22:48:36.58
ふぅん…
each_indexはあるのにreverse_each_indexはないのか…
0153デフォルトの名無しさん2011/02/27(日) 22:54:14.49
別になくてもなんとかなるよね、と言ってしまってから需要が発覚した好例
0154デフォルトの名無しさん2011/02/28(月) 00:44:49.10
each_indexってArrayのメソッドだったのか
0155デフォルトの名無しさん2011/02/28(月) 08:32:07.09
indexがないコンテナ、というのも存在しうるからEnumerableのメソッドには出来んだろ
0156デフォルトの名無しさん2011/02/28(月) 13:15:54.56
reverse.each_index
0157デフォルトの名無しさん2011/02/28(月) 13:25:53.47
メソッドチェーンではだめなのですよ
0158デフォルトの名無しさん2011/02/28(月) 14:04:23.12
質問だよおっかさん
gem の spec/ とかのテストディレクトリは lib/ ディレクトリのネスト具合を正確に反映させるべきすかね

一身上の都合で AAA::BBB::111 という妙に深い名前の gem ライブラリスクリプトを2個ほど作ります
 lib/aaa/000.rb    # require 'aaa/000' 用
 lib/aaa/bbb/111.rb
 lib/aaa/bbb/222.rb
bbb/ には特にファイルはありません
で、spec/ ディレクトリに 111_spec.rb を作りたいのですが
 spec/aaa/bbb/111_spec.rb
 spec/111_spec.rb
 spec/aaa_bbb_111_spec.rb
どれが普通っぽいですか?
0159デフォルトの名無しさん2011/02/28(月) 14:09:05.25
IDEやらエディタマクロで、実装とspecを相互に行き来できる機能が
あるけど、その手のって、たぶん実装とspecのパスが対応している
ことを仮定していると思う。
0160デフォルトの名無しさん2011/02/28(月) 16:04:22.73
require File.expand_path(File.dirname(__FILE__) + '../../../spec_helper') とか書かないといけなくなって若干めどい
まあ既存のどれかのをコピペすればいけるが
0161デフォルトの名無しさん2011/02/28(月) 19:18:08.04
irb起動後にechoのon/offは切り替えられないのかい?
0162デフォルトの名無しさん2011/02/28(月) 19:32:21.95
echo ってなんじゃらほ

$ irb -f
irb>"string!"
=> "string!"
irb> irb_context.return_format
=> "=> %s\n"
irb> irb_context.return_format = "%s\n"
"%s\n"
irb> "string!"
"string!"

ということで、起動後の irb の設定変更は irb_context のメソッドを通じて行う
irb_context とだけ入力するとなんかいろいろ出てくる
conf. は irb_context の別名で被る可能性が大なので irb_context. で指定するのが無難
0163デフォルトの名無しさん2011/02/28(月) 19:42:22.14
できました。ありがとう。
irb> irb_context.echo=false
0164デフォルトの名無しさん2011/03/01(火) 09:21:40.09
簡易なオートロード機能を考えています。
ひとまず自分で書いたコードを載せます(1.8系です)

# グローバル定数
SCRIPT_LINES__ = { __FILE__ => File.readlines(__FILE__) }
# Moduleを拡張
class Module
def const_missing(name)
const_name = name.to_s
filename, line_no = caller(0)[1].split(":") # 呼び出し元の情報
line = SCRIPT_LINES__[filename][line_no.to_i-1] # SCRIPT_LINES__よりコード行を取得=>"t = Mobi::MobiMobi::FooBar.new"
if const_name = /([:_0-9a-zA-Z]*#{name}[:_0-9a-zA-Z]*)/.match(line) # 定数部分を抽出=>"Mobi::MobiMobi::FooBar"
const_name = const_name[1]
file = const_to_path(const_name) # 自前の別メソッドによりパスを得る=>"mobi/mobi_mobi/foo_bar"
begin
require file
const = const_get(name)
rescue LoadError # 通常の定数呼び出しだった場合に備えてLoadErrorは無視
else
return const
end
end
raise NameError, "uninitialize constant #{const_name}"
end
end
# 実行
t = Mobi::MobiMobi::FooBar.new
01651642011/03/01(火) 09:22:26.92
(続き)
これは一応うまくいくのですが、デバッグコードみたいなのを使ってるのと、
$SAFEが0じゃないとSCRIPT_LINES__を使えないので、いまいちと感じています
でも他にconst_missingで"Mobi::MobiMobi::FooBar"を得る方法がわかりません。
上のコードの場合、const_missingに送られるのは:Mobiだけなので
mobi.rbやmobi/mobi_mobi.rbが存在すれば順に読み込まれてうまくいきますが、
モジュール階層のディレクトリのみであればLoadErrorで止まってしまいます。
定義済み定数と照らしながらディレクトリ階層内を走査していくほかないでしょうか。
01661642011/03/01(火) 09:28:25.55
>>165 mobi.rbやmobi/mobi_mobi.rbが存在すれば
すいません、今すぐ確認できないんですが
これうまくいかなかったと思います。
0167デフォルトの名無しさん2011/03/01(火) 12:19:38.92
  ∩___∩ 未だ連絡ゼロクマー
  | ノ  ___ヽ
  /。・゚・(____ `・゜゚・。 いつでも連絡するクマー
  |    u( _●_)ヽ 〉
 彡、   |∪|   /  誰か助けるクマー
. /    ヽノ . /´
         .____
        / ヽ、  _ノ\
      / (○)iji(○)\    正義がキチガイ呼ばわりされたんだぞ。
     /    (__人__)   \
     |       |::::::|     |  義憤に駆られることはないのかお?
     \       l;;;;;;l    /l!| !
     /     `ー'    \ |i  Rubyistとして後ろめたさはないのかお!
   /          ヽ !l ヽi
   (   丶- 、       しE |そ  一生後悔することになるお!
    `ー、_ノ       煤@l、E ノ <
               レY^V^ヽl  そこのあなた!勇気を出すんだお。
       ____
     /      \  助けて欲しいんだお・・・
   /  _ノ  ヽ、_  \ 同じ釜の飯を食ったんだお・・・
  / o゚((●)) ((●))゚o \  いつも一人で居残り残業してたんだお・・・
  |     (__人__)    | あまりの悲しさに、むせび泣いたこともあったお
  \     ` ⌒´     / そんなやる夫を見捨てるのかお?

       ____ このままだったら一生恨むお
     /      \ たとえ誰がなんと言おうと、強烈な違和感なんだお
   /  _ノ  ヽ、_  \ 直観がモノ言ってんだお
  /  o゚⌒   ⌒゚o  \  えっぇっえ〜ん。え〜ん。
  |     (__人__)    |  えっぇっえっぇっ。うっぅっぅうー。。。
  \     ` ⌒´     / うええ〜ん。。。えぐっぇぐっうっうっううぅー。。。
0168デフォルトの名無しさん2011/03/01(火) 12:21:52.19
わけがわからないよ。
0169デフォルトの名無しさん2011/03/01(火) 12:34:54.82
>>168
ム板でスレひとつしか取得してないからそうなる
0170デフォルトの名無しさん2011/03/01(火) 12:43:13.48
新着レスの内容読まなくても複数のスレを表示しておくのは必須だよね
自衛とはいえ我ながらアホくさいとは思うんだが
0171デフォルトの名無しさん2011/03/01(火) 14:19:51.69
>>170
なんか余裕だよね。
どんな対策したの?2ch禁止令とか出したの?
なんか2chに書き込んでも駄目な気がした。
奴らが書き込むことはないんだろうね!
ましてや、メールしてくるなんてないんだろ?

もうちょっと他の手考えるわ。
こっちは必死こいて頑張ってきとんねんで

しかし、余裕の態度は気になる。
何らかの対策しやがった臭い

ま、なんにしろ、もう2chには書き込まないよ
もっと有意義なことに時間使うわ
レスあんがと
0172デフォルトの名無しさん2011/03/01(火) 15:24:26.41
>>170
マルチポストとか多い板だからな
書き込みしてからマルチだと気づいたときの虚しさったらないぞ
0173デフォルトの名無しさん2011/03/02(水) 08:50:04.70
書き込みがマルチでないことと、自分の質問がコピペされてマルチ扱いにされてないかのチェックは必ずしないといかん
めんどくさい
0174デフォルトの名無しさん2011/03/02(水) 08:58:36.37
過去に俺も何度かやられたが、
メインであろうスレに一番最初に書かれてれば本物とみなしてあまり気にしないぞ

というわけで質問どうぞ
0175デフォルトの名無しさん2011/03/02(水) 10:00:50.37
Rubyが64bitでコンパイルされているかどうか調べる方法はありますか。
今は (2**32).class が Fixnum だったら64bit、Bignumだったら32bitというふうに
判定してるんですが、もっとすまーとな方法があれば教えてください。
require 'rbconfig' してもそれらしきものはありませんでした。
0176デフォルトの名無しさん2011/03/02(水) 10:20:39.68
CONFIG["target"] とかは?
0177デフォルトの名無しさん2011/03/02(水) 11:37:16.30
>>168-174
話が見えないな。どっかのマルチが出たって話を
ここに集まってきてしゃべってるのか
0178デフォルトの名無しさん2011/03/02(水) 11:54:18.40
うわ!こんなゴミクズ言語使ってる低能たちいたいの

かわいそう かわいそう
0179デフォルトの名無しさん2011/03/02(水) 12:00:01.76
日本語もろくに使えない低能にゴミクズ言語扱いされるのって…
0180デフォルトの名無しさん2011/03/02(水) 12:07:33.29
>>177
ttp://hibari.2ch.net/test/read.cgi/tech/1295081752/255
ttp://hibari.2ch.net/test/read.cgi/tech/1200175247/933
0181デフォルトの名無しさん2011/03/02(水) 13:07:06.82
春休みか…
0182デフォルトの名無しさん2011/03/02(水) 14:34:11.66
>>176
require 'rbconfig'
puts Config::CONFIG['target'] #=> i686-apple-darwin10.6.0
だめみたいですね。
0183デフォルトの名無しさん2011/03/02(水) 14:44:36.86
pack('P') とか使えないかね
0184デフォルトの名無しさん2011/03/02(水) 14:56:38.41
StringIO に書き込んだ文字列を取得する方法って rewind とかして read しかないですか?
いちいち sio.rewind; str = sio.read って書くのめどいです
0185デフォルトの名無しさん2011/03/02(水) 15:20:00.34
>>184
sio.string は?
0186デフォルトの名無しさん2011/03/02(水) 15:20:46.14
>>184
StringIO#string
0187デフォルトの名無しさん2011/03/02(水) 16:00:44.43
>>183
どう使うんでしょうか。
0188デフォルトの名無しさん2011/03/02(水) 16:31:38.56
Windows 32bitしか知らないのでよくわかりませんが
RUBY_DESCRIPTION や RUBY_PLATFORM
で判別できないと面倒ですね

64bitのRubyだと
p [""].pack("p").size
したときに 8 になるんでしょうか?
これってポインタのサイズを見るってことですよね
0189デフォルトの名無しさん2011/03/02(水) 17:32:30.93
2011年2月のプログラミング言語インデックス

1 Java     18.482% ↑ 7ヶ月連続1位
2 C.       14.986% ↓
3 C++       8.187% ↓
4 Python     7.038% ↑ 5位から4位へ浮上。2ヶ月連続で順位を上げている。
5 PHP.      6.973% ↓ 4位から5位へ下落。下落傾向
6 C#        6.809% ↑
7 (Visual)Basic 4.924% ↓
8 Objective-C  2.571% ↑ 安定化傾向
9 JavaScript   2.558% ↑
10 Perl.       1.907% ↓
http://journal.mycom.co.jp/news/2011/03/01/064/index.html
0190デフォルトの名無しさん2011/03/02(水) 18:58:57.86
…おかしいな、朝作ったときはもっとこうシンプルなライブラリだったはずなのだが
0191デフォルトの名無しさん2011/03/02(水) 19:06:02.59
>>190
そういうときは寝て起きると不要なものが浮いてきます

64bit判定はバージョン文字列判定的にはできねーというのが定説だった気がする
実際の動作で判定するのが現状安定
もしかしたら今後なにかあるかもしれないけど、現状は無理っぽい
0192デフォルトの名無しさん2011/03/02(水) 21:30:37.16
>>188
Rubyが64bitモードでコンパイルされたかどうかってのは、ポインタサイズで判定すべきものなんでしたっけ?
intのサイズだと思ってけど、違うのかな。
(2**32).class が Fixnum なら 64bit、Bignumなら32bitだと思ってた。

0193デフォルトの名無しさん2011/03/02(水) 23:43:26.86
>>183 pack('P') とか使えないかね
とあったんで ポインタサイズでも判別できるのかな?と思っただけです
WindowsXPしかないんで、確かめようも無いのですが

intじゃなくて VALUEのサイズですね
VALUEのサイズはポインタと同じで
64bit Windowsでは unsigned long long
それ以外だとunsigned long なのかな

64bitとか未知の世界だ
0194デフォルトの名無しさん2011/03/03(木) 12:32:03.30
>>192
64ビットWindowsはLLP64だからintもlongも32ビット。
ポインタサイズじゃないと判定できないかも。
0195デフォルトの名無しさん2011/03/03(木) 17:51:59.45
>>194
そうか、自分が知りたいのは、x86_64かどうかだ。
今実行中のRubyバイナリがx86_64かどうかを調べる方法ってあります?
require 'rbconfig'
p Config::ARCHFLAGS #=> "-arch i386 -arch x86_64"
はコンパイル時のフラグであって、実行時にどっちなのかはわかんない。
0196デフォルトの名無しさん2011/03/03(木) 18:33:56.80
実行ファイル自身のマジックナンバーで分かるのだろうか。
でも、同じx86_64でもELFだったりPEだったりMach-Oだったりあるか。
0197デフォルトの名無しさん2011/03/03(木) 18:45:13.60
MacOSのことはよくわからんのでググったら
ユニバーサルバイナリなので
PowerPCのとx86のとx86-64のとがひとつの実行ファイルとかになってて
実行ファイル見ても判別付かんことがわかった

64bitかの判別なら(2**32).class が Fixnum かどうかでいいんじゃないの?
ポインタが64bitならVALUEも64bitになって
Fixnumはポインタサイズ-1 になるんじゃないのかな

PowerPC32,PowerPC64,x86,x86-64 を判別したいとかなら
C拡張作るか、OSのAPI呼ぶとかしないとだめなんじゃないの?
0198デフォルトの名無しさん2011/03/03(木) 18:50:22.52
まったく自信がないし
64bit Windowsで確かめることもできないけど
Windowsならばおそらくこんなの(XP以降)

require 'Win32API'
current_process = Win32API.new('Kernel32.dll','GetCurrentProcess',%w[v],'v').call
bIsWow64 = "\x0"*4
Win32API.new('Kernel32.dll','IsWow64Process',%w[i p],'i').call(current_process,[bIsWow64].pack('p')).zero? || raise
puts bIsWow64.unpack('l').first.zero? ? '32bit' : '64bit'

Macだとdlライブラリとかでできるのかな?
0199デフォルトの名無しさん2011/03/03(木) 18:58:05.50
おっとそういえば、WindowsにもIA64版がありました
GetNativeSystemInfo とか呼んでCPUアーキテクチャも見ないとだめかな
0200デフォルトの名無しさん2011/03/04(金) 05:49:29.71
[nil].pack("P") が一番速いと思う
(2**32).class を見る方法は、Fixnum の範囲がポインタのサイズではなく、long のサイズ依存だからダメ
もっとも、多くの場合は RUBY_PLATFORM でいい気がするけど
0201デフォルトの名無しさん2011/03/04(金) 10:40:22.34
open-uriで、タイムアウトをくらったらリトライするメソッドを作っています。
こんな感じです。
def get_html_doc(url)
trial ||= 0
open(url, 'r:binary') do |io|
return Nokogiri::HTML(io.read.toutf8, nil, 'utf-8')
end
rescue Errno::ETIMEDOUT => e
trial += 1
if trial < RETRY
retry
else
raise e, e.message, e.backtrace
end
end
これをrspecでテストしたいのですが、
タイムアウトをくらってもリトライで成功するケースが
テストできません。
1回目のトライではopenでErrno::ETIMEDOUTをraiseして、
2回目のトライではopenがraiseしないようなrspecってどう書きます?
こんな感じでできたらいいのですが、
kicked = false
should_receive(:open).exactly(2).times do
unless kicked
kicked = true
raise Errno::ETIMEDOUT
end
end
get_html_doc('/dev/null').should be_nil
should_receive節の中でraiseするとrspecに怒られてしまいます。
何かうまい方法はないでしょうか。
0202デフォルトの名無しさん2011/03/04(金) 11:49:59.64
思いつかないときは自分の知ってる分野に引きずり込んでお茶濁せってじっちゃんが言ってた

$ cat getweb_spec.rb
require 'rspec'
require 'webmock/rspec'
require 'open-uri'

def getweb(url)
t = false
begin
open(url).read
rescue Errno::ETIMEDOUT
unless t then t = !t; retry else raise end
end
end

describe "getweb" do
before do
@url = 'http://host/'
WebMock.stub_request(:get, @url).to_raise(Errno::ETIMEDOUT).to_return(:body => 'BODY')
end
it "gets a file over Error::ETIMEOUT" do
getweb(@url).should eql('BODY')
WebMock.request(:get, @url).should have_been_made.twice
end
end
# -----------------------------

$ rspec -fs getweb_spec.rb

getweb
gets a file over Error::ETIMEOUT
0203デフォルトの名無しさん2011/03/04(金) 16:00:27.82
>>200
>もっとも、多くの場合は RUBY_PLATFORM でいい気がするけど
その定数にx86_64という文字列が入ってくれるならいいんだけど、そうじゃないよね。
もしかして1.9なら入ってたりするのかな。
0204デフォルトの名無しさん2011/03/04(金) 16:06:39.81
> >>200
> >もっとも、多くの場合は RUBY_PLATFORM でいい気がするけど
> その定数にx86_64という文字列が入ってくれるならいいんだけど、そうじゃないよね。
> もしかして1.9なら入ってたりするのかな。

環境とバージョンにもよるけど、amd64とかx64とかx86_64とか。
しかしそもそも、1.8 on Windowsだとmswin64対応してませんぜ
0205デフォルトの名無しさん2011/03/04(金) 16:13:52.77
>>204
うちんところは入っとらん。
irb> RUBY_PLATFORM
=> ""i686-darwin10.6.0""
どういうときに入ってるの?linuxじゃないとだめ?
0206デフォルトの名無しさん2011/03/04(金) 16:49:53.07
>>205
それは32bit版だと思います
[nil].pack("p").sizeが4じゃないですか
0207デフォルトの名無しさん2011/03/04(金) 17:18:05.56
>>206
いやいや、そうでもないみたいよ
ttp://ktjx.blogspot.com/2009/12/mac-os-x-ruby-os.html
によると
OS付属、MacPorts、自分で入れたものでそれぞれ
ruby 1.8.7 (2008-08-11 patchlevel 72) [universal-darwin10.0]
ruby 1.8.7 (2009-06-12 patchlevel 174) [i686-darwin10]
ruby 1.8.7 (2009-12-24 patchlevel 248) [x86_64-darwin10.2.0]
みたいになるそうだ

それぞれの実行ファイルは
% file /usr/bin/ruby
/usr/bin/ruby: Mach-O universal binary with 3 architectures
/usr/bin/ruby (for architecture x86_64): Mach-O 64-bit executable x86_64
/usr/bin/ruby (for architecture i386): Mach-O executable i386
/usr/bin/ruby (for architecture ppc7400): Mach-O executable ppc

% file /opt/local/bin/ruby
/opt/local/bin/ruby: Mach-O 64-bit executable x86_64

% file ~/local/bin/ruby
/Users/katsuji/local/bin/ruby: Mach-O 64-bit executable x86_64
なんだって
0208デフォルトの名無しさん2011/03/04(金) 17:25:19.04
>>200
64bit RubyだとFixnumは63bitだと思ってたら
Windowsでは31bitなのね、とほほ
ruby.hみたら
#define FIXNUM_MAX (LONG_MAX>>1)
#define FIXNUM_MIN RSHIFT((long)LONG_MIN,1)
ってなってた
ググったら、互換性のためにlongじゃないとまずいだろってことになったみたいですね
せっかくVALUEが64bitなのに、半分しか使えないとは

PHPの文字列が2Gまでしか対応してないっていうブログ記事を思い出して
RStringを見たら、これまたサイズがlongだった
64ビットだと2G超のメモリも確保できると思うんですけど
WindowsだけStringも2G制限のままなのか
0209デフォルトの名無しさん2011/03/04(金) 17:32:01.37
ところで、Fixnum#sizeを使えばFixnumの実装上のサイズが返ってくるのでした
Windows以外の64bitRubyだと 1.size > 4 なんでしょうね
Fixnum::MAXとかFixnum::MINとかがあれば手っ取り早いのですが

WindowsXPのJRubyだと8が返ってきました……
これはもうあれだ
実行中のCPUアーキテクチャを取得する定数なんかを用意するしか
0210デフォルトの名無しさん2011/03/04(金) 18:50:44.73
instance.hoge.moge.method1()といった具合に、
クラスのインスタンスメソッドをhogeやmogeで分けたいです。

現状は、instance.method2()やinstance.method3()程度でしかできず、
深い階層を使った呼び出しができていません。

 class Testdrive
  def method2()
  end
  def hoge.moge.method1()
  end
 end
としてみましたが、undefined local variable or methodが返ります。

クラスをネストで定義して、initialize()呼び出し時に
入れ子のクラスを@hogeなどに代入するとできますが、
都度行うのは手間なので、何か慣例となっているやり方が
あるのではないかと考えています。
どのようにしたらよいでしょうか。
0211デフォルトの名無しさん2011/03/04(金) 19:32:49.11
メソッドチェーンは単なる記述じゃなくて、レシーバに対するメソッド呼び出しの連続だ
レシーバに存在しないメソッドは呼べない
0212デフォルトの名無しさん2011/03/04(金) 19:35:01.85
>>210
そんなことの前になぜ分けるのか
instance.hoge.moge.method1()ってパッと見どう考えても「instance#hogeの戻り値にその戻り値のクラスが持つmogeメソッドを実行し〜」でしょ
@ary.to_s.gsub!(/abc/, "def")
余計なことを考えてるだけにしか思えない
0213デフォルトの名無しさん2011/03/04(金) 19:38:11.38
def hoge
self
end
def moge
self
end
とかしたいのかと思ったがさすがにちがうよな。
0214デフォルトの名無しさん2011/03/04(金) 19:47:09.74
>>213
や、テクニーク的にはそうなのだろ
メソッドチェーンが繋がる外見であることが、なんだか重要らしいし

でもレシーバという概念を勉強して卒業してほしいよかん
あれって無意味ににょろにょろ繋がってるわけじゃないのよw
0215デフォルトの名無しさん2011/03/04(金) 20:22:56.72
>>211
メソッドチェーンで、hogeメソッド、mogeメソッド、
metho1メソッドと返り値を流したいわけではないです。

method1以外にもいくつかmogeに関するインスタンスメソッドがあり、
それを人間の目でまとまっているように見せておきたいのです。

現状だと、metho1を定義するのに、
def hoge_moge_method1()
end
とするか

別途クラスを定義してinitialize時に
@mogeなどに代入するしかないので不便です。

>>213
selfについて分からないので調べてみます。
0216デフォルトの名無しさん2011/03/04(金) 20:28:30.04
もしかして
instance.hoge.tap {|h| h.moge.tap {|m| m.method1 } }

※ きっと違う。

0217デフォルトの名無しさん2011/03/04(金) 20:35:07.04
 class Testdrive
  def initialize
  #@hoge = Hoge.new() #?
  end
  def medthod4()
  end
  class Hoge
  def method5()
  end
  def method6()
  end
  end
 end

これをインスタンス化して、
instance.method4()
instance.hoge.method5()
とそれぞれ呼び分けたいです。

method5とmethod6はHogeについてのメソッドなので、
Hogeについてのメソッドを呼んでいますよってことを分かり易くしたいのです。

selfについては読みました。
>>213にさらに
def method1
end
を追記しておけば
hoge.moge.medhod1()でもmoge.hoge.method1()でも何でもいけるってことで合っていますか。
0218デフォルトの名無しさん2011/03/04(金) 20:54:33.29
>>215
メソッドチェーンは単なる記述じゃなくて、レシーバに対するメソッド呼び出しの連続だ
その仕組みを勝手に変えられても、とても困る

まあそのへんの見かけ重視でメソッドの呼ばれ方を見かけ上変えたのがDSLなんだけど
0219デフォルトの名無しさん2011/03/04(金) 20:59:50.45
まあ、昔ちょっと流行ったことがある
メソッドチェーンするだけで何もしない、読み下し用メソッド

class C
def foo
puts "foo"
self
end
def bar
puts "bar"
self
end
def and
self
end
end

c = C.new
c.foo.and.bar

ただ、小手先ニヤニヤドヤ顔っぽくてあまり気持ちよくないというので最近は廃れた
0220デフォルトの名無しさん2011/03/04(金) 21:02:32.51
Rubyのやり方を理解していないということですね。
class Net
class Http
end
class Ftp
end
end
とあったときに、
Netをインスタンス化した際に、
instanceからHttpクラスのインスタンスメソッドや
Ftpクラスのインスタンスメソッドを呼び出すには、
どのようにコーディングするのがよいのでしょうか。

私よりもプログラミングに疎い者が簡単な調節で
新しい処理を作れるようにしたいので、
>>218にあるDSLはまさにうってつけなのでしょうけれど、
私にDSLを設計するほどの技量がなくできる範囲で
扱いやすいクラスを作ろうと考えています。
0221デフォルトの名無しさん2011/03/04(金) 21:10:30.32
>>220
それは Net::Http や Net::Ftp (標準クラスのじゃないよな?) を
インスタンス化するところ。
0222デフォルトの名無しさん2011/03/04(金) 21:12:58.46
wxRuby と RubyQt だとどっちが使いやすいですか?
0223デフォルトの名無しさん2011/03/04(金) 21:16:24.87
>>222
具体的にどんなもの作るつもりか2行半くらいで
0224デフォルトの名無しさん2011/03/04(金) 21:18:20.85
>>220
http = Net::Http.new(...)
http.foo(....)

ftp = Net::Ftp;new(....)
ftp.bar(....)

これがRubyの基本だよ。何も難しい話は無いと思うんだけどな。
0225デフォルトの名無しさん2011/03/04(金) 21:22:53.84
>>221
そうですか。
リファレンス見てたら例としてあげられそうだったのであげました。

ありがとうございます。
ということは定義したクラスを実際に使う時に、
HttpなりFtpなりをそれぞれnew()するしかないということでしょうか。

一度のnew()でどのクラスのインスタンスメソッドなのか
分かりやすい状態を作り出すというのは難しいのですか。
0226デフォルトの名無しさん2011/03/04(金) 21:25:11.17
みなさんレスありがとうございます。

>>224
それで私も基本は構わないのですが、
new()を1度呼び出すだけでHttpもFtpもインスタンス化できるように
クラス定義の段階で細工できないかと考えています。
0227デフォルトの名無しさん2011/03/04(金) 21:30:43.70
class C
def initialize
@foo = Foo.new
@bar = Bar.new
end
def foo; @foo; end
def bar; @bar; end
end
class Foo; def f; puts "f!"; end; end
class Bar; def b; puts "b!"; end; end

c = C.new
c.foo.f
c.bar.b
0228デフォルトの名無しさん2011/03/04(金) 21:30:49.37
>>226
>new()を1度呼び出すだけでHttpもFtpもインスタンス化できるように

それなら、こんな感じかな?

class Net
def initilize
 @http = Http.new(....)
 @ftp = Ftp.new(....)
end
attr_reader :http, :ftp

class Http; ....; end
class Ftp; ....; end
end

net = Net.new
net.http.foo(....)
net.ftp.bar(....)
02292272011/03/04(金) 21:32:26.10
6秒勝った…!
0230デフォルトの名無しさん2011/03/04(金) 21:39:16.64
>>227
>>228
うまくいきました。どうもありがとうです。
私のやりたいことは実現できそうです。
アクセサについても調べていましたが、
シンボルの記述をミスしていました。

これで次のコーディングに進めそうですが、
net.ftp.bar(....)
これは最初にレスを頂いたメソッドチェーンと形式が非常によく似ています。
違いについてもう少し知りたいのですが、
何と調べると解説ページなど出てくるか教えて下さい。
0231デフォルトの名無しさん2011/03/04(金) 21:46:29.87
報告になります。
class A
def initialize()
@b = B.new()
end
attr_reader :b

class B
def initialize()
@c = C.new()
end
attr_reader :c

class C
def bar()
puts 'bar'
end
end
end
end

a = A.new()
a.b.c.bar()

これでやりたいことができました。
本当にありがとうございます。
0232デフォルトの名無しさん2011/03/04(金) 21:56:34.91
なるほど、def foo; @foo; end
はselfの代わりに@fooを返すということで、
c.foo.fはメソッドチェーンではあるんですね。

クラスをネスト表記する利点について、調べてみることにします。
ネスト表記で納得できなければまた質問に来るかもしれませんが、
その時はまたレスくれると有難いです。

だらだらと書いて済みません、
ありがとうございました。
0233デフォルトの名無しさん2011/03/04(金) 21:56:50.47
>>207
なるほど、1.8だとx86_64用なのにi686を名乗ることがあるんですねぇ

>>208
Rubyで2GBのString扱いたい事ってあります?
あるなら次のABI互換性破壊時に提案するのが正解ですかね

>>209
そもそも何がやりたくてlongとかポインタのサイズを調べているんでしょうか
たぶんそれによって話が違ってきます
0234デフォルトの名無しさん2011/03/04(金) 21:59:06.73
メソッドを呼び出したオブジェクトって取れませんかね?
selfを引数にして渡すしかない?
0235デフォルトの名無しさん2011/03/04(金) 22:22:04.43
できねっす。
Rubinius では出来なくもないようだけど。
あと、MRI 1.8.4 あたりまではバグを突いて取得可能だった。
0236デフォルトの名無しさん2011/03/04(金) 22:28:56.74
>>232
>クラスをネスト表記する利点

クラスはモジュールの一種である(サブクラスである)から、
クラス定義のネストはモジュールの階層的な構造を表現するという意味がある。
いわゆるモジュラプログラミングとか構造化設計の具体化になる。
>>228のコードについて、モジュール構造を(意識的に)明示して書き直してみると、
以下のようになる。(冗長だけど、例ということで....)

module Net
class Net; .... end
class Http; ....; end
class Ftp; ....; end
end

net = Net::Net.new
net.http.foo(....)
net.ftp.bar(....)

また、クラス特有の階層とは継承(インヘリタンス)を意味するけど、
これら二つ(モジュール構造とクラス継承)は混同しやすいので注意したい。
0237デフォルトの名無しさん2011/03/04(金) 22:35:22.57
>>223
Windows用のネットワークゲーム管理サーバーとその管理ツールです
0238デフォルトの名無しさん2011/03/04(金) 22:43:29.36
>>235
ありがとう
0239デフォルトの名無しさん2011/03/04(金) 22:55:46.14
>>237
…wxでいいんじゃね
なんかモノによっては物凄く遠回りになりそうな気もしなくもないが
0240デフォルトの名無しさん2011/03/05(土) 05:48:27.14
html = <<<http://ruby.com>;>> # htmlの内容を取得
みたいな `` と同格なユーザーが戻り値や副作用を好きに定義できる文字列?ってないですよね。

foo("a")
"a".foo
にするのが普通なんでしょうが。
0241デフォルトの名無しさん2011/03/05(土) 06:49:32.07
一部の演算子は実体がメソッドなので再定義可能だけど
<<http...>>みたいにはどうやってもできないと思う
Rubyマニュアルの演算子のとこ見てね

とはいえこういうことはできるみたい
require 'open-uri'
def `(uri); URI.read(uri); end
html = `http://www.example.com/`
0242デフォルトの名無しさん2011/03/05(土) 07:35:25.66
>>240
f("aaa") は f "aaa" とかけて、さらにスペースをなくして f"aaa" と書ける。
これじゃだめ?
0243デフォルトの名無しさん2011/03/05(土) 08:00:01.25
>>210だと思うんだけど、「そういうのぜんぜんわかりやすくない」から
初心者というものを完全に勘違いしたシステムには枚挙に暇がないけれど
0244デフォルトの名無しさん2011/03/05(土) 08:45:40.00
>>240
どうしてそうしたいのか、そのほうが好ましいのかをじっくりと考えてみるべき。
新しい演算子や構文を作ることは(小細工しないと)できない
0245デフォルトの名無しさん2011/03/05(土) 09:09:08.53

              -― ̄ ̄ ` ―--  _
          , ´         ,    ~  ̄、"ー 、
        _/          / ,r    _   ヽ ノ
       , ´           / /    ●   i"
    ,/   ,|           / / _i⌒ l| i  |
   と,-‐ ´ ̄          / / (⊂ ● j'__   |
  (´__   、       / /    ̄!,__,u●   |
       ̄ ̄`ヾ_     し       u l| i /ヽ、
          ,_  \           ノ(`'__ノ
        (__  ̄~" __ , --‐一~⊂  ⊃_
           ̄ ̄ ̄      ⊂ ̄    __⊃
                   ⊂_____⊃
0246デフォルトの名無しさん2011/03/05(土) 09:56:17.83
まあ文句ばかり言ってても非生産的だぬ

「プログラミング知らない人にも極力わかりやすいようにする」アプローチはいくつかある
いちばんメジャーなのは、設定ファイルを分離してユーザーにデータだけ書かせることだ
プログラムロジックを記述する必要がなければ、だいたいの人はだいたいそれなりに納得する

** 管理者が頑張って作る実行スクリプト

require 'yaml'
require 'open-uri'

data = YAML.load_file('config.yml')
url = data['url']
name = data['name']
html = open(url).read
title = html.scan(/<title>(.+?)</)[0]
puts "#{name}さんこんにちは!\n#{url} のタイトルは #{title} です!"

** ユーザーが自由に記述する config.yml の中身(2行)

url : http://www.ruby-lang.org/en/
name : デフォルトの名無し

** 上記2つを同じディレクトリに入れて実行した結果

デフォルトの名無しさんこんにちは!
http://www.ruby-lang.org/en/ のタイトルは Ruby Programming Language です!
0247デフォルトの名無しさん2011/03/05(土) 10:53:43.57
設定だけUnicodeで保存してくれ、と事務方向けのサービスを
用意したら、メモ帳でUTF16とかBOM付きUTF8保存されて
YAMLロードでコケたトラウマが…
0248デフォルトの名無しさん2011/03/05(土) 10:59:05.53
UTF-8やUnicode関連のファイル保存オプションが膨大すぎて、
どれで保存するのが妥当なのか常用してても忘れるエディタとか

このへんYAMLのほうで自動でなんかどうにかしてくれるとよかったのだけど
でもその変な文字がデータとして必要になる可能性もあるから駄目だな
0249デフォルトの名無しさん2011/03/05(土) 11:11:56.38
日本人向けの設定ファイルは文字エンコーディング自動判別できるくらいの初期コメントを書いておくのが重要
ときどき、リソースフォークが恋しくなる
0250デフォルトの名無しさん2011/03/05(土) 17:18:47.50
def my_sort(e, list)
if 0 == list.size then
nil
elsif list.first == e then
list
else
my_sort(e, list[1..list.size]) << list.first
end
end
puts my_sort('C', ['A', 'B', 'C', 'D']).join()
#=>CDBA

eに与えた値を先頭にして、配列を並べなおしたいのですが、
CDBAとなってしまいます。
CDABとこれを変えたいです。
どのようにしたらよいでしょうか。
■ このスレッドは過去ログ倉庫に格納されています