【激突】関数型言語 VS オブジェクト指向言語2
■ このスレッドは過去ログ倉庫に格納されています
0001営利利用に関するLR審議中@詳細は自治スレへ
2012/04/07(土) 21:26:47.61一部には関数型言語を崇拝している人もいます
どちらが上なのか、この際はっきりさせましょう
前スレ http://toro.2ch.net/test/read.cgi/tech/1331328955/
0002営利利用に関するLR審議中@詳細は自治スレへ
2012/04/07(土) 21:27:35.64http://toro.2ch.net/test/read.cgi/tech/1333801632/
0003営利利用に関するLR審議中@詳細は自治スレへ
2012/04/07(土) 21:29:47.00> それならそれでFILTERでも変更できるインターフェースを付け加えればいいだけ。
そういう変更/拡張のし易さも議論の対象
ちゃんと変更したコードを提出しないと比較にならない
負け惜しみじゃないんだろ?
0004営利利用に関するLR審議中@詳細は自治スレへ
2012/04/07(土) 21:35:39.48本来はフィルタでやることではないよ。
それわかってる?
0005営利利用に関するLR審議中@詳細は自治スレへ
2012/04/07(土) 21:37:53.28class Filter {
private i = 0;
private m = 0;
begin(awk) {awk.RS=';'}
filter(line) {i++; m = max(m, line.length()); }
end() {print "最大文字数は"+m+"文字でした"}
}
こんな感じだろうw
0006営利利用に関するLR審議中@詳細は自治スレへ
2012/04/07(土) 21:39:53.53いいから「改行コードを変更する拡張をする」に対して
OOPでやるとどれくらい簡潔になるか、コードを出せって
疑似コードじゃなくて動くヤツな
0007営利利用に関するLR審議中@詳細は自治スレへ
2012/04/07(土) 21:41:05.68こんな感じかな。まあこの例ならsetuupでやればいいことだけど。
class Filter {
private i = 0;
private m = 0;
private awk;
setup(awk) {this.awk = awk}
begin() {awk.RS=':'}
filter(line) {i++; m = max(m, line.length()); }
end() {print "最大文字数は"+m+"文字でした"}
teardown() {this.awk = null}
}
0008営利利用に関するLR審議中@詳細は自治スレへ
2012/04/07(土) 21:41:31.13肝心の部分はどうしたんですか?
どうやってセパレートしたんですか?
そうやって誤摩化すってことは、関数型言語で一瞬で書けるコードが
OOPでは難しいってことですね?
0009営利利用に関するLR審議中@詳細は自治スレへ
2012/04/07(土) 21:42:07.17OOPでやると簡潔になるんじゃなくて、
変更の範囲を極小化出来るんだよ。
該当のフィルタだけの修正で、
それ以外の場所は何も変えないで変更できる。
0010営利利用に関するLR審議中@詳細は自治スレへ
2012/04/07(土) 21:42:59.33使えないな
0011営利利用に関するLR審議中@詳細は自治スレへ
2012/04/07(土) 21:43:29.55え? 行フィルタなのに、ファイル全体をセパレートするのはおかしいでしょ?
ここにないのは、ここにあるべきじゃないコードだからだよ。
0012営利利用に関するLR審議中@詳細は自治スレへ
2012/04/07(土) 21:43:49.61「標準入力から文字列を読み込んで、カンマ区切りで改行して、
各行の文字数を数えて最大文字数を標準出力に表示せよ」
これを書いて
0013営利利用に関するLR審議中@詳細は自治スレへ
2012/04/07(土) 21:45:14.12ファビョってきたなw
全部関数なんかでやろうとするから
設計ができないんだ。
0014営利利用に関するLR審議中@詳細は自治スレへ
2012/04/07(土) 21:46:27.84それ問題が不適切。
「標準入力」から文字列を読み込んで、「カンマ区切りで改行」して、
「各行の文字数を数えて最大文字数」を「標準出力」に表示せよ
ただし、カッコの中は一例であり
容易に変更できる設計にしておくこと
0015営利利用に関するLR審議中@詳細は自治スレへ
2012/04/07(土) 21:47:53.75各行に対して□を処理をして、その結果を☆に表示せよ
抽象化するとこんな感じか。
0016営利利用に関するLR審議中@詳細は自治スレへ
2012/04/07(土) 21:49:26.82オレ何度も書いたし、もういいや今日は。
0017営利利用に関するLR審議中@詳細は自治スレへ
2012/04/07(土) 21:50:59.800018営利利用に関するLR審議中@詳細は自治スレへ
2012/04/07(土) 21:51:11.25そのリーダーインターフェースを実装した、
標準出力リーダークラスを作る。
行セパレータインターフェースが必要
その行セパレータインターフェースの実装として、
\r\nセパレータを作る
その後フィルタインタフェースが必要で
そのフィルタインタフェース(begin、filter、end)を実装した、
「各行の文字数を数えて最大文字数」はfilterで文字数を数えて
endで結果を出力する。
あとは、同様にライタインターフェースを実装した
標準出力ライタクラス。
0019営利利用に関するLR審議中@詳細は自治スレへ
2012/04/07(土) 21:51:29.89とかそんくらいの成果聞いてみたいもんだわ
0020営利利用に関するLR審議中@詳細は自治スレへ
2012/04/07(土) 21:52:01.14こんな感じになるわけ。
例外が悪いという意味がわかったかな?
0021営利利用に関するLR審議中@詳細は自治スレへ
2012/04/07(土) 21:53:56.240022営利利用に関するLR審議中@詳細は自治スレへ
2012/04/07(土) 21:54:17.31オブジェクト指向は様々な実装を書くための仕組みを
提供するもの、つまり設計の部分なので
やることの対象が違うんだよ。
オブジェクト指向で枠組み設計を行い
関数型言語でその枠組みの中身を書く
0023営利利用に関するLR審議中@詳細は自治スレへ
2012/04/07(土) 21:55:34.83広範囲な部分、処理の連携部分を記述する言語ってことなだけでしょ。
0024営利利用に関するLR審議中@詳細は自治スレへ
2012/04/07(土) 21:57:26.440025営利利用に関するLR審議中@詳細は自治スレへ
2012/04/07(土) 21:58:48.39> オブジェクト指向で枠組み設計を行い
> 関数型言語でその枠組みの中身を書く
こんな感じ?
{-# LANGUAGE RecordWildCards #-}
import System
import Control.Monad
data Filter a b = Filter { begin :: a, body :: a -> String -> b, end :: b -> IO () }
awkLike Filter{..} = end . body begin
countFilter = Filter {
begin = Nothing,
body = \_ -> maximum . map length . lines,
end = \p -> putStrLn $ "最大文字数は" ++ show p ++ "文字でした"}
splitBy _ [] = []
splitBy p xs = a : (splitBy p $ drop 1 b) where (a, b) = break p xs
countFilterSplitBy sep filepath = countFilter {
body = \_ -> maximum . map length . splitBy (== sep),
end = \p -> writeFile filepath $ "最大文字数は" ++ show p ++ "文字でした"
}
main' = awkLike countFilter =<< getContents -- 例1: 標準入出力使用、普通にカウント
main = mapM_ (awkLike (countFilterSplitBy ',' "test.txt") <=< readFile) =<< getArgs -- 改行コードを変えて入出力先も変更
0026営利利用に関するLR審議中@詳細は自治スレへ
2012/04/07(土) 22:00:33.04おー、なかなか。パチパチ
0027営利利用に関するLR審議中@詳細は自治スレへ
2012/04/07(土) 22:04:02.780028営利利用に関するLR審議中@詳細は自治スレへ
2012/04/07(土) 22:37:31.82ソースにパッチを当てて変更するのは容易ではないの?
パッチが容易ではないというのは、もしかして
「CUIは容易ではない」「GUIは容易」みたいな思想と関係あるのか
0029営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 00:08:18.23ソースにパッチ当てるといってもいろんな意味がある。
インターフェースを変更するようなソースの修正は容易ではない。
影響があちこちに波及するからだ。
0030営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 04:41:56.60関数型が使えそうなところには関数型の機能を使う。
両方使えそうにないところは普通の手続き型の格好に。たったそれだけのことだろ?
「関数型 vs オブジェクト指向」 からは、「if文 vs for文」並みのナンセンスさを感じるね。
OOも関数型も単なる一機能なんだから、状況に合わせて 使う/使わない すればよいじゃない。
0031営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 04:57:44.260032営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 07:15:51.37「関数型 vs オブジェクト指向」ならその通りなんだけど、
ここは「関数型言語 vs オブジェクト指向言語」なんだわ
0033営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 09:46:11.980034営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 09:53:06.98パッチの意味は追加と削除の二種類しかない。
マクロな視点でいうと、最新版を出す影響と古い安定版を切り捨てる影響の二つ。
現に大きな影響が出ているが、
関数型とオブジェクト指向の人間はこの問題についてなにも言ってない。
なぜなら、古い仕様が優遇されてしまうと手続き型が圧倒的に有利だから。
0035営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 09:55:37.49具体的に言って下さい。
0036営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 10:00:13.98functional (programming)
0037営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 10:35:21.46・ソースコード自体を書き換える方法
・ソースコードはそのままに静的に書き換える方法(マクロ、テンプレート)
・ソースコードはそのままに実行時に書き換える方法(モンキーパッチ)
などがあるのですが
0038営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 11:01:10.34文字列自体を操作する方法と、文字列に代わるものを操作する方法があるよね
0039営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 11:13:21.18個人的に、関数型言語は「型指向」だと思う
どう言う型受け取って、どう言う型を変えしたいのか考えると、自然と答えが出て来る
0040営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 11:22:39.91それらの区別はたいして何も変わらんw
0041営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 11:25:46.31納期に迫られ、ろくに設計できる環境も、人材も無い現場では関数型言語の方が向いてると思うんだが・・・
checkPermu ns = and.concat $ check ns
where
check [] = [[]]
check (x:xs) = map (x/=) xs : check xs
allPattern 0 _ = [[]]
allPattern _ [] = [[]]
allPattern n (ns:nss) = [x:xs | x <- ns, xs <- allPattern (n-1) nss]
-- 普通に作ったpermutations(使用例:permutations [1..3])
permutations ns = permutations' (length ns) ns
where
permutations' 0 _ = [[]]
permutations' _ [] = [[]]
permutations' n ns = [x:xs | x <- ns, xs <- permutations' (n-1) ns, checkPermu (x:xs)]
-- 汎用的なallPatternを作って、それに差し替えたpermutations
permutations2 ns= filter checkPermu $ allPattern (length ns) (replicate (length ns) ns)
-- allPatternを使った拡張版permutations(使用例:permutationsEx 3 [[1..3],[1..3],[1..3]])
permutationsEx n ns= filter checkPermu $ allPattern n ns
0042営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 11:45:02.42全然違うだろアホか
0043営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 12:11:04.47節子、動的・動的…
0044営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 12:22:28.84やっぱOOPはウンコだわ……
0045営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 12:33:46.770046営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 12:34:12.65俺は
「設計を意識しないとそもそも書けない」のが関数型言語で
手続き型言語やOOPLはメチャクチャな設計でも書けるor書けてしまうが
ちゃんと意識すると関数型言語にも通ずるようなコードが出来上がる
…と感じる
0047営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 12:34:19.200048営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 12:37:13.94設計・・・オブジェクト指向
実装・・・関数型言語
って感じるな。
0049営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 12:47:10.040050営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 13:16:53.33OOだって実装の道具にすぎん。ハンマーやカンナの類だ。
0051営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 13:29:13.33OOにはOOA(分析)やOOD(設計)があって
開発プロセス全体をカバーするものなんだ。
OOPLはOOによる開発プロセスを素直に実装するための言語
分析や設計がなぜOOなのかというと、それが一番
システム開発に適しているから。
そしてその分析、設計に一番適している実装がOOPL
関数型による分析や設計が出てこないことには
関数型は実装のみにしか適用されずに終わるよ。
0052営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 13:33:38.15夢見ちゃったって感じだね。
0053営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 13:36:27.78>システム開発に適しているから。
正しくはこうだね。
分析や設計がなぜOOなのかというと、使う言語がOOPLだから。
0054営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 13:40:00.970055営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 13:51:51.24実装のみの技術ってことだろうね。
0056営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 13:53:30.17何を?
0057営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 14:02:15.980058営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 14:49:46.340059営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 15:50:29.78流れ的に>>41
0060営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 16:36:57.37今Haskell版読みながらRuby版書いてみてるんだけど、やっぱ適当に書かれてる印象はないなあ
発想自体がよく練らないと出てこないというか
「自分が手作業でやるならこう」を素直にコード化する手続き脳ではいきなりは出てこないコードだと思う
0061営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 16:49:51.49どちらにしても行き当たりばったりにも見えないんだよ、それがサクッと出て来る時点でもう設計できてんじゃん、みたいな
0062営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 17:02:45.73そうは言っても関数型言語での記述は、仕様をそのまま記述してるだけだしな・・・
クイックソートの記述が有名だけど、マージソートはもっと仕様そのまま書いてるだけなのがハッキリする
-- ソート済みのリストの小さい方をリストに追加して、他方を元のリストに戻して、リストのどちらかが空になるまで比較とリストへの追加、他方のさし戻しを繰り返す
merge xs [] = xs
merge [] ys = ys
merge (x:xs) (y:ys) | x < y = x:merge xs (y:ys)
merge (x:xs) (y:ys) = y:merge (x:xs) ys
-- 1要素または空になるまで半分に分割を繰り返してからmergeによる結合(1要素のリスト、または空リストはソート済みのリスト)
mergesort [] = []
mergesort [z] = [z]
mergesort zs = merge (mergesort xs) (mergesort ys)
where
(xs,ys) = splitAt (length zs `div` 2) zs
分析については、プログラミングHaskellの最後の方に書いてるプログラムの論証を読むと参考になると思う
>>41も、設計もへったくれも無く、こうしたいなと言う脳内仕様をそのまま書いたし、checkPermuを外に追い出して差し替えられるようにしたいな。とか、長さの異なるリストも扱えるようにしたいな。という気まぐれでどんどん変更してた
(そもそも設計が必要な規模じゃないが)
0063営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 17:07:38.47手作業でやる場合の手順をそのままコードに書いた、非常に手続き的な思考回路だと思う
class Array
def my_permu
return [] if empty?
return [ns] if size == 1
result = []
each do |n|
without_n = reject{|x| x == n }
without_n.my_permu.each do |ary|
result.push( [n] + ary )
end
end
return result
end
end
p (1..3).to_a.my_permu
0064営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 17:08:07.37ruby挫折したりプログラマとしても挫折した(半年で才能無いと悟って辞職)私が褒められてる・・・
設計経験Zeroですよ^^;
0065営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 17:08:33.410066営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 17:12:31.25手続き的なやり方が合わなかったんじゃね?
俺は逆に、そういう式的というか関数的というか…そういう発想が出てこない
まず最初に「それをやるなら、あれをやって、これをやってから…こうかな」と考えて、それをコード化してしまう
その例で言えば俺の脳内ではまず「数字の書かれたカードを並べていき、並べたらメモる」という作業が行われる
いきなりリストを組み合わせ分増やし、フィルタを掛けるなんて発想が出てこない
0067営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 17:14:26.36class Array
def my_permu
return [] if empty?
return [self] if size == 1
result = []
each do |n|
without_n = reject{|x| x == n }
without_n.my_permu.each do |ary|
result.push( [n] + ary )
end
end
return result
end
end
p (1..3).to_a.my_permu
0068営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 17:55:38.95オレのコードは誰も褒めてくれなかった。それどころかオセロの難解コートと同列扱いされる始末…orz
0069営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 17:59:46.60出てこないのはやっぱりって感じ
オブジェクト指向・・・設計部分の実装
関数型 or 手続き型 ・・・ 一処理の実装
といわれるのはこういうとことか
0070営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 18:18:58.67発想の基点は恐らく、リスト内包表記でしょうね
勝手に全ての組み合わせを生成してくれますし、条件で生成される組み合わせを絞り込める
それを柔軟に扱えるようにしない手は無いな。と
じつは、昔、別のスレでリスト内包表記と再帰の合わせ技は見掛けてたんですよ
発想だけ貰って、自分で自作しました
関数脳の作り方は今も昔も、どう言う関数?どう動くべき?です
このメソッドを使ってとか、ここはポインタで・・・とかの発想は無いです
最初にベタな発想があって、流用できる関数があれば、流用する
Q:lengthは何をする関数?
A:リストを受け取って、長さを返す関数
Q:lengthはどう動くべき?
A:先頭から、1ずつ足して行くべき
Q:リストが空っぽになったら?
A:足しても変わらない0を返す
length [] = 0
length (_:xs) = 1 + length xs
流用版
length xs = sum [1 | _ <- xs] -- 上のQ&Aと、要素数と同じ数だけ1が入ったリストを生成して足し合わせるのは等価
多分、手続き脳ですでにプログラミング出来てる人は、最初から抽象的に考える素養はあると思うので、仕様をそのまま書いてる感覚さえ分かれば、一気に関数脳になると思います
0071営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 18:35:37.90これは局所的なコードは手続き型のほうが恩恵あることを示している。
C++やJavaが受け入れられたのは局所的でないところでは
OOの援用が有効だということを示している。
関数型と対峙するのは手続き型。
受け入れられるとしたらOOと手続き型の中間地点なんじゃないかな。
0072営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 18:46:14.25俺の場合、まず >>67 のように書いてから、それを発展させて初めて関数的コードになる感じになる
実は前スレの >>172 を書いたのも俺なんだが、同じようなコードをまず書いて、それを inject に直した
そこから更に発展させると関数型言語のコードとして成り立つようには出来ると思うが(inject→foldlの変換は難しくないし)
本当に関数型な人のアプローチとはやはり違う形になってしまうんじゃないかなと思う
0073営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 19:03:33.53関数に焦点があたってるけどさ、
それより大きな範囲のオブジェクトはどうするのさ?
0074営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 19:06:22.94昔は、手続き型とか関数型とかの選択肢より、切実にメモリやCPU速度が足りなくて、Cが選択されて、速度を損なわずOOP出来るC++が選択されてきた(OOPも最初はメモリの無駄が多いと敬遠されてきた)
PCの進化とともにLLが選択される場面が増えて来たのと同様に、関数型言語が選択される場面が増えても不思議ではない
・・・けど、C系列の言語が多く選ばれるんだろうな
do記法も、モナドが何となく分かってくると順番が重要な処理をこれまた仕様通りに書いてるだけって気付くし、手続き型を見事に矛盾無く関数型言語でエミュレートしてる事に気付いて鳥肌立つんだが
順序の無い関数の世界で順序の概念をエミュレートしてるって凄い!って
前スレの「テキストファイル読み込んで、行番号つけて表示せよ」ってのを読みやすく?書いてみた
import System.Environment
numbering xs = unlines $ map (\(x,y) -> show x ++ y) (zip [1..] (lines xs))
main = do
fnames <- getArgs
fstrings <- mapM readFile fnames
let numfstrings = map numbering fstrings
putStr $ unlines numfstrings
0075営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 19:17:21.85とくにJavascriptは関数型風にも書けるけどただの趣味の範囲で終わってる。
0076営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 19:18:44.83ブラウザで動く言語はJavaScriptで決まりだよ。
0077営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 19:22:04.440078営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 19:24:17.120079営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 19:57:11.75関数型言語は無駄が多いからね。
0080営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 20:42:28.52Objective-CとC#は局所的であることを怖れないが、そういうのは受け入れられにくい
C++とJavaが受け入れられたのは、局所化でないところが実在するのではなく
漠然と、どこかそういうところに行きたいという願望があっただけだろう
0081営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 20:43:30.860082営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 21:27:01.14意味が分からない
親が動物クラスで子が犬クラス・猫クラスとかのあれ?
型の性質を引き継ぐと言うのは型クラスとか有るけど・・・
ええと・・・で、そのオブジェクトで何をしたいの?どう拡張したいの?それって、オブジェクトである必要あるの?
犬か猫かに合わせて泣き声変えるんなら
data Animals = Dog | Cat deriving (Eq,Show)
voice a | a == Dog = "wan wan!"
voice a | a == Cat = "nya- nya-!"
これで十分なんだけど・・・そして、どっちもanimals型
犬は猫じゃないし、猫も犬じゃない
taroは犬で、taroという名前で、7歳
taro = (Dog,"taro",7)
miiは猫で、miiと言う名前で、3歳
mii = (Cat,"mii",3)
taroは猫じゃないし、miiは犬じゃない
let animalCategory (x,_,_) (y,_,_) = x == y
animalCategory taro mii
>False
0083営利利用に関するLR審議中@詳細は自治スレへ
2012/04/08(日) 21:30:52.01全部受け入れられている言語だと思うが・・・
言語なんて金になるかどうかで受け入れるかどうかが決まるもんだよ
関数型言語で金になる話が無いだけ
と言うわけで関数型言語でスマフォアプリ作れる環境を(ry
■ このスレッドは過去ログ倉庫に格納されています