- 1 :uy:2012/08/11(土) 12:21:25.19
- 面白かったのでコピペ
979 名前:uy[sage] 投稿日:2012/08/11(土) 11:53:55.80
面接官「特技はRubyとありますが?」
学生 「はい。Rubyでならなんでもかけます。」
面接官「ではシングルトンパターンを書いてください。」
学生 「存在しません?」
面接官「え、存在しない?」
学生 「はい。存在しません。Rubyはシングルトンパターンを言語でサポートしています。」
面接官「・・・で、その言語でサポートされた機能を使うとシングルトンパターンになるんですよね?」
学生 「はい。シングルトンパターンです。」
面接官「いや、あなたRubyでシングルトンパターンは存在しないといいましたよね。なぜシングルトンパターンになるんですか?」
学生 「でも、シングルトンパターンは存在しないんですよ。」
面接官「いや、存在しないとか問題じゃなくてですね・・・」
学生 「Rubyなら簡単にシングルトンパターン書けますよ。」
面接官「ふざけないでください。それに機能が用意されてるってことは存在するでしょ。だいたい・・・」
学生 「機能は用意されていますが言語でサポートしているんです。だから存在しません。」
面接官「聞いてません。帰って下さい。」
学生 「あれあれ?怒らせていいんですか?シングルトンパターン書きますよ。」
面接官「いいですよ。書いてください。Rubyでシングルトンパターンを。それで満足したら帰って下さい。」
学生 「運がよかったな。Rubyにシングルトンパターンは存在しないようだ。」
面接官「帰れよ。」 - 146 :デフォルトの名無しさん:2012/08/15(水) 15:17:03.87
- Rubyはなんでdoに|つけるの?
- 149 :デフォルトの名無しさん:2012/08/15(水) 15:39:44.61
- >>146
パイプでブロック引数をはさまないと、
それがブロック引数なのか、
単に式としてそこにあるのかが区別できない - 151 :デフォルトの名無しさん:2012/08/15(水) 15:46:24.88
- >>149
pythonみたいな
for t in list:
みたいにできなかったの?
絶対にこっちのほうがわかりやすいと思うんだけど||でかこったら特殊な演算やってそうじゃん - 153 :デフォルトの名無しさん:2012/08/15(水) 15:49:51.63
- >>151
for t in list; end という構文も最初から存在していますけど、なにか? - 162 :uy:2012/08/15(水) 16:52:58.51
- rubyで一番よく使うのはmap、これは戻り値に配列を返す
普通に書いたら
p [1,2,3].map { |x| x*2 } # => [2, 4, 6]
だけど、メソッド(イテレータ)チェインする事によって、本来配列を返さない
each_with_indexなども
p [1,2,3].each_with_index { |x,i| x*(2+i) } # => [1, 2, 3]
mapを置く事による戻り値を変えられる
p [1,2,3].each_with_index.map { |x,i| x*(2+i) } # => [2, 6, 12]
これをforで書くとこう
s??=??[]
i??=??0
for??x??in??[1,2,3]
????s??<<??x*(2+i)
????i??+=??1
end
p??s
for文とイテレータじゃ力の差が有りすぎて異論の余地すらない - 177 :デフォルトの名無しさん:2012/08/15(水) 18:40:16.04
- だから、分かりやすいのがよいなら、
一時変数用意すればよいだろ。何の説明も要らなくなるよ。 - 181 :153:2012/08/15(水) 19:14:29.25
- >>177
一時変数は悪ではないし、否定しないよ
実際に実用的なプログラムでは、あまりに長いメソッドチェーンを
途中で切って、間に一時変数を入れることがある
ただし、一度代入したら二度と更新しない
問題は変数の「破壊的代入」
たとえば>>162の最後にあるforを使った手続き型スタイルでは、
最初にリスト変数とループ変数に初期値を代入した後、
forループ内でこれら変数をゴリゴリと更新(破壊的に代入)している
これが可読性の悪化とコード品質の低下をまねく要因
なお破壊的代入の無さは、専門用語だと「参照透明性」と呼ばれる - 191 :デフォルトの名無しさん:2012/08/15(水) 21:10:40.01
- 内包表記が読み難いとか言ってる奴は
数学の素養が無いって自己紹介してることに気付いてないの?
かっこわるいから控えた方が良いよ - 197 :153:2012/08/15(水) 21:57:54.67
- >>191
自分は内包表記が読み難いとは思わないね
ただしPythonの場合、局所宣言またはクロージャがないから
せっかくの内包表記構文が台無しになっている
過去スレ19,20で議論になったコードを以下に示す
==== Haskell ====
data Option a = None | Some a
ys = [fn x | x <- xs]
where fn x =
let
h = if is_first_page x then generate_header else None
b = generate_body x
f = if is_last_page x then generate_footer else None
in
(h, b, f)
Haskellには局所宣言としてwhere節があるから、関数fnを定義することで
内包表記を含む式をトップダウンに数学っぽく記述できる
==== Python ====
ys??=??(Document.new(h,b,f)??for??x??in??xs
for??h??in??[generate_header()??if??x.is_first_page??else??None]
for??b??in??[generate_body(x)]
for??f??in??[generate_footer()??if??x.is_last_page??else??None])
このPythonコードが何をしているかどうか、はたして一目で把握できるかな? - 198 :153:2012/08/15(水) 22:01:18.03
- 参考として、>>197に関するRubyのコードを過去スレからコピペする
==== Ruby ====
ys = xs.map { |x|
h = if x.first_page? then generate_header else nil end
b = generate_body x
f = if x.last_page? then generate_footer else nil end
Document.new h, b, f
}
Rubyには内包表記構文は無いけれど、普通に書ける(実に初歩的なコードだ) - 211 :デフォルトの名無しさん:2012/08/15(水) 22:52:50.85
- >>197をPythonで(RubyやHaskellのコード相当で)書くならごく素直に
def preprocess(x):
h = generate_header() if x.is_first_page else None
b = generate_body(x)
f = generate_fotter() if x.is_last_page else None
return h, b, f
ys = [Document(preprocess(x)) for x in xs]
じゃないかと。まずリスト内包で書くことはない - 235 :153:2012/08/16(木) 10:04:35.58
- >>211
ん、最終行にはリスト内包表記が見えるけど、気のせいかな?
それはさておき、Pythonでは「ごく普通に」関数を定義して適用するのに対して、
Ruby(および関数型言語)では「ごく普通に」ブロックや無名関数を使って
シンブルな式として表現できる、ということになった
また当たり前だけど、>>211のような関数を定義するコードはRubyでも書ける
これは>>197,198で述べたように、関数型言語風プログラミングにおいて
局所宣言が無いというPythonの欠点、そしてRubyの優位性を示している - 237 :デフォルトの名無しさん:2012/08/16(木) 11:05:52.40
- >>235
Rubyは関数内関数を素直に定義できないじゃん
Proc??と??lambda??の違いとかキモイし
どさくさにまぎれて関数型言語と一緒にすんなよ - 243 :153:2012/08/16(木) 14:13:16.73
- >>237
>Rubyは関数内関数を素直に定義できないじゃん
エッ!、Rubyは普通に関数内関数を定義できるよ???
以前(1.8)は関数内関数のスコープに問題があったけど、今(1.9)では解消されたし
・メソッド定義のネスト - Ruby 1.9.3 リファレンスマニュアル
http://doc.ruby-lang.org/ja/1.9.3/doc/spec=2fdef.html#nest_method
というか、OOPLであるRubyでは、プライベートメソッドとして定義するのが一般的で、
関数内関数はまず目にすることはない
しかも(>>211のPyhtonのような)他LLでは関数定義を「普通」に使うけど、
Rubyならブロックがあるから一度しか適用しない関数は式の中に埋め込むのが「普通」
つまり、(関数内関数を多用せざるをえない他LLと違って)関数内関数を使う頻度は少ない
>Proc??と??lambda??の違いとかキモイし
確かにProcとlambdaの微妙な差異は分かりづらいよね
でもRubyにはブロック構文があるから、(Procやlambdaのような)明示的な無名関数宣言を
使う頻度は比較的少ないし、使うケースでもどちらか一方を使えば済むことが多い
また、言語の微妙な弱点を避けて、良い点を引き出すことに注力することが
(Rubyに限らず)中級プログラマのたしなみの一つだと考える
>どさくさにまぎれて関数型言語と一緒にすんなよ
え、一度も「Rubyは関数型言語である」とは言ってないけど.....???
「関数型言語風プログラミングには(他LLよりも)Rubyは明らかに優れている」と主張している - 244 :デフォルトの名無しさん:2012/08/16(木) 14:25:57.61
- >>243
>??エッ!、Rubyは普通に関数内関数を定義できるよ???
はあ?じゃあ何で関数内関数が外から見えてんだよ
http://ideone.com/4J057 - 245 :デフォルトの名無しさん:2012/08/16(木) 14:42:18.11
- >??つまり、(関数内関数を多用せざるをえない他LLと違って)関数内関数を使う頻度は少ない
関数型言語でも関数内関数を多用するけど...?
「関数型言語風プログラミング」って何?
それってただの「Ruby風プログラミング」なんじゃないの? - 248 :153:2012/08/16(木) 14:50:55.63
- >>244
わざわざideon上のコードを引用しなくても、Rubyの振る舞いは>>243で示した
リファレンスマニュアル「普通のメソッド定義式と同じ」の通りだよ???
確かに、理想的には内側のメソッドが外部から隠蔽されたほうが望ましいことは認める
これが>>211のPythonコードのように、関数定義を多用するのが「普通」、
あるいは関数定義を多用「しなければならない」言語であれば、致命的な欠陥になる
でも>>243で述べたように、Rubyでは関数内関数の必要性がほとんど存在していないんだ
もしも可能であるならば、ブロックやプライベートメソッド定義では読みづらかったり
冗長だったりするけど、関数内関数であれば素直に表現できるコード例を示してほしいなあ... - 255 :153:2012/08/16(木) 15:41:10.73
- >>245
>関数型言語でも関数内関数を多用するけど...?
うん、関数型言語では関数内関数でプログラムを構築していくのが普通だね
でもRubyはオブジェクト指向言語であり(>>243の最後で書いたように)関数型言語ではないから、
モジュールやクラスでプログラムを構築するのが普通なんだ
>「関数型言語風プログラミング」って何?
「(破壊的代入を含む)副作用を避けた参照透明性のあるプログラミング」(>>181も参照)
これは関数型言語のパラダイムと同じ
もちろん(関数内関数ではない)Rubyでは、入出力や効率(性能や資源)といった理由から
完全に参照透明性のあるコードは書けないけど、それでも副作用を極力避けたり、
参照透明性のある部分とない部分を意識的に使い分ける、あるいは副作用のあるコードを隠蔽する
現実に実用的なテキスト処理プログム開発で試したところ(全体で約20Kstep)、
8割は参照透明性のあるコードで実装することが可能だった
残る2割の部分は、トップレベルの(入出力を含む)メイン処理モジュール群と
最下層の副作用をカプセル化(隠蔽)した内部ライブラリ群になる - 264 :デフォルトの名無しさん:2012/08/16(木) 17:48:13.46
- 旧世代的なラムダ脳にはリスト内包表記、イテレータ、ジェネレータ、デコレータを上手く使うPythonicなコードは理解出来ない
なんとかラムダで書こうとするのは、どの言語でもCみたいなコードを書く奴と何も変わらん - 267 :153:2012/08/16(木) 18:11:28.09
- >>264
論よりコード - 270 :デフォルトの名無しさん:2012/08/16(木) 18:42:06.27
- >>267
Closures in Python (part 1)
http://ivan.truemesh.com/archives/000392.html
>(ie. use a "list comprehension" - I think it reads a bit easier than using the map/lambda). - 278 :デフォルトの名無しさん:2012/08/16(木) 19:02:19.29
- そもそも関数定義無しに書けなきゃダメって
勝手にルール作ってるところがおかしい - 285 :デフォルトの名無しさん:2012/08/16(木) 19:21:31.64
- >全ての関数をラムダ式で書くわけもなく、普通に関数定義するし
普通の関数もかけるのは当たり前で、
それだけじゃつらいからラムダを導入したって話だろ。
論点ずれてるだろ。何言ってんだか。
ラムダが要らないものならわざわざ変な文法作ってまで導入するかよ。 - 286 :デフォルトの名無しさん:2012/08/16(木) 19:23:37.43
- >>285
上のはラムダで書くべき例なの? - 287 :153:2012/08/16(木) 19:26:19.29
- >>278,279
あらゆる関数型言語であれば関数定義無しにかけるから、
それは「関数型プログラミング」の特徴の一つである、という理屈
だってPythonだけが関数定義が無ければ書けないんだから、
マイナス評価されても当然だろ?
というかさ、もしルールに不満があるならそれを最初に主張すべきだった
具体的には、>>235の指摘に対して即座に反論すればよかったのに....
いろいろゴネたあげく、技術論で反論できないからルールに不満を言うのは
カッコワルイと思うよ - 294 :デフォルトの名無しさん:2012/08/16(木) 20:14:22.38
- >>287
あれ?お前>>255でRubyはOOPLだから関数内関数無くても良いんだとか
言ってなかったっけ?
関数型言語では関数内関数あるんだからRubyではdefの入れ子で
関数内関数が定義できないのはマイナス評価されても良いの? - 297 :デフォルトの名無しさん:2012/08/16(木) 20:18:08.51
- (1)Pythonのlambdaじゃ書けなくて
(2)関数を定義したら冗長になってしまうほど短い
そんな例題があればいいんだよ - 310 :153:2012/08/16(木) 21:19:31.47
- >>294
>関数型言語では関数内関数あるんだからRubyではdefの入れ子で
>関数内関数が定義できないのはマイナス評価されても良いの?
正確には「関数内関数定義で内部の関数が外部から隠蔽されない」だね
もちろんこの点はRubyのマイナス評価であると認めるよ
また、アンカも間違いで(>>255ではなくて)>>243じゃないかな?
さらに言えば、>>297自身も(>>243,248から)引用しているように、
このマイナス評価はRubyにとっては致命的な欠点ではない
もしも致命的ではないという意見が不満ならば、
>>248の最後でリクエストしたように具体的なコードで語って欲しい
論よりコードだ - 328 :デフォルトの名無しさん:2012/08/16(木) 22:02:23.59
- Pythonディスりたければ、俺みたいに、
あの糞みたいな、ネスとスコープの仕様をつつけば良いのに。
あれだけは生粋のパイソニストでも擁護不可能だからね。
擁護しようものなら、
今になってnonlocal追加した事実に反してしまうしな。 - 333 :デフォルトの名無しさん:2012/08/16(木) 22:08:32.79
- >>328
nonlocal(酷い名前だ)を追加したPython3ではネストスコープの問題は無いの? - 344 :デフォルトの名無しさん:2012/08/16(木) 22:24:22.12
- >>333
ああ、問題残ってるよ。代入の有る無しでスコープが切り替わる問題が。
互換性のためか残っちゃってるけど、
nonlocal追加したんなら、思い切ってこの糞仕様は廃止すべきだったな。
nonlocal有りならネストスコープ、無しならローカルスコープ。
一貫してそれでよかったんだよ。シンプル、単純、分かりやすい。
スコープ調べるのに代入の有る無し調べるとか意味わかんねー。
折角nonlocal追加したのに、なぜに。
二箇所調べなきゃならなくなったから、状況はより悪化したともいえる。 - 346 :デフォルトの名無しさん:2012/08/16(木) 22:26:16.84
- >>344
ちょっと待てよ。nonlocal追加以前はそもそも代入不可だろ - 349 :デフォルトの名無しさん:2012/08/16(木) 22:30:33.87
- >>346
いや、代入できるよ。ローカルスコープの変数になるけどな。
代入があっても、nonlocalならネストスコープ。
nonlocal無くても、代入が無ければネストスコープ。
あー超ややこしいね。
単に、nonlocal有り/無しで、ネスト/ローカルが切り替わる
方が直感的で良いよなぁ。 - 419 :デフォルトの名無しさん:2012/08/17(金) 02:16:05.29
- ラムダを多用ってどこの誰が多用してんの?
- 512 :uY:2012/08/20(月) 05:46:11.83
- さっきちょっと書いたコードなんだけど
何も考えずに適当に書くとこうなるコードでも
n??=??i??=??0
s??=??[]
b??=??["a","b"]
[1,2,3].cycle??do??|??m??|
????n??+=??1
????i??+=??1
????break??if??n??==??21
????s??<<??m
????if??i??==??4
????????i??=??0
????????s??<<??b.first
????????b.rotate!
????end
end
p??s
↓ちゃんと書けばちゃんとブロック内に全部収まるところが、rubyが最強である所以だと思う
[1,2,3].cycle.take(20).each_with_index.each_with_object??[??s??=??[]??,??["a","b"]??]????do??|??(??m??,??i??)??,??(??s??,??b??)??|????
????s??<<??m
????(??(i??+=??1)??%??4??).zero???and??s??<<??b.rotate![-1]
end
p??s
メソッド名が長かったりしてソースは長いけどアルゴリズムとしては完璧なものが書けるんだよ - 519 :uY:2012/08/20(月) 16:31:55.85
- 40.times.map.each.with_index(1).each_with_object( [ [1,2,3] , ["a","b"] ].map(&:cycle) ).map?? do | ( m , i ) , ( a , b ) |??
?? Hash[ true , b.next , false , a.next ][ ( i % 5 ).zero? ]
end.display
puts
[1,2,3].cycle.take(40).each.with_index(1).each_with_object( ["a","b"].cycle ).map?? do | ( m , i ) , b |??
?? ( i % 5 ).zero? ? b.next : m
end.display
変数の完全隠蔽がされている
アルゴリズムとして完璧なんだよこれは
これを無駄に長いとはいわない
短くしようと思えば出来る長さなんだよ
すべてがメソッドで、その引数で構成されているから
↓これが出来る
a = [1,2,3].cycle.take(40).each.with_index(1).each_with_object( ["a","b"].cycle )
a.map do | ( m , i ) , b |??
?? ( i % 5 ).zero? ? b.next : m
end.display - 520 :デフォルトの名無しさん:2012/08/20(月) 17:05:56.67
- from??itertools??import??cycle
print([s??if??i??%??5??==??0??else??n??for??n,s,i
????????in??zip(cycle([1,2,3]),??cycle("ab"),??range(1,41))]) - 576 :uY:2012/08/21(火) 19:53:34.60
- def func n , aa , bb
?? y = Enumerator.new do | e |
?? ?? a = aa.cycle
?? ?? b = bb.cycle??
?? ?? [*1..n].cycle { |i|
?? ?? ?? r = (i%n) == 0 ? a : b
?? ?? ?? e << r.next
?? ?? }
?? end
end
y = func 5 , ["a","b"] , [1,2,3]
p y.take(20) # => [1, 2, 3, 1, "a", 2, 3, 1, 2, "b", 3, 1, 2, 3, "a", 1, 2, 3, 1, "b"]
y = func 2 , [true] , [false]
p y.take(20) # => [false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true]
ゲームでインターバルの制御に使うんです - 592 :デフォルトの名無しさん:2012/08/21(火) 21:51:53.70
- >>576
func の中の y の代入が意味不明。
[*1..n].cycle は冗長。
def func(n, aa, bb)
????Enumerator.new do |y|
????????a = aa.cycle
????????b = bb.cycle
????????loop{ (n-1).times{ y << b.next }; y << a.next }
????end
end
enum = func(5, ["a","b"], [1,2,3])
p enum.take(25) - 720 :デフォルトの名無しさん:2012/08/30(木) 16:23:23.43
- 大学のプログラミングでperlやってるんですが
3年になったら何言語やるんでしょう?
1年 C java Basic Javascript ruby
2年 C++ perl
な感じです。
2学期後期は何ですか? - 765 :uy:2012/08/31(金) 03:21:35.57
- 逆に考えると専門にはいれば
論外的に才能ない奴はすぐ挫折していなくなるから、かえってそのほうが早期にIT脱出できて幸せなんじゃね
大学だと才能なくてもやめずに4年間ズルズルとやり続けて産廃になってる可能性もある
才能がないなら早めにリターンしたほうが絶対良い
http://toro.2ch.net/test/read.cgi/tech/1344655285/l50/../人気ブログランキングへ