1 名前:営利利用に関するLR審議中@詳細は自治スレへ mailto:sage [2012/04/07(土) 21:26:47.61 ] 一般的には、オブジェクト指向型言語が優勢でが 一部には関数型言語を崇拝している人もいます どちらが上なのか、この際はっきりさせましょう 前スレ toro.2ch.net/test/read.cgi/tech/1331328955/
256 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 08:18:23.98 ] 全くなんの工夫もないが $ cat fizzbuzz.hs import Control.Monad (mapM_) main = mapM_ (runFizzBuzz . gizz . buzz . fizz) [1, 3, 5, 7, 15, 21, 35, 105] runFizzBuzz (n, s) | s == "" = putStrLn $ show n | otherwise = putStrLn $ show s fizz n | n `mod` 3 == 0 = (n, "Fizz") | otherwise = (n, "") buzz (n, s) | n `mod` 5 == 0 = (n, showString s "Buzz") | otherwise = (n, s) gizz (n, s) | n `mod` 7 == 0 = (n, showString s "Gizz") | otherwise = (n, s) $ runghc fizzbuzz.hs 1 "Fizz" "Buzz" "Gizz" "FizzBuzz" "FizzGizz" "BuzzGizz" "FizzBuzzGizz"
257 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 08:45:35.77 ] この場合の顧客がのぞむもの。 map (gizz . buzz . fizz) [1, 3, 5, 7, 15, 21, 35, 105] -- [1, "FIzz", "Buzz", "Gizz", "FizzBuzz", "FizzGizz", "BuzzGizz", "FizzBuzzGizz"] map (buzz . gizz . fizz) [1, 3, 5, 7, 15, 21, 35, 105] -- [1, "FIzz", "Buzz", "Gizz", "FizzBuzz", "FizzGizz", "GizzBuzz", "FizzGizzBuzz"]
258 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 08:54:17.09 ] 整数と文字列が同じリストにフラットに入らなきゃ嫌だという主張?
259 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 09:05:31.58 ] struct filter_t{ int e; const char *t; }; struct fizzbuzz_t { int in; std::string out; fizzbuzz_t &operator >>( filter_t &f ) { if( 0==in%f.e ){ out.append( f.t ); } return *this; } operator const char *() { if( out.length() ) return out.c_str(); static char tmp[50]; itoa( in, tmp, 10 ); return tmp; } }; fizzbuzz_t operator >>( int i, filter_t &f ){ fizzbuzz_t fb; fb.in = i; fb>>f; return fb; } filter_t fizz = { 3, "Fizz", }; filter_t buzz = { 5, "Buzz", }; filter_t gizz = { 7, "Gizz", }; int main(){ 105>>fizz>buzz>>gizz>>endfb; return 0; }
260 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 09:05:55.65 ] fizz buzz gizz (とその合成)で完結する。 合成順が結果に反映される。 結果は標準出力ではなく関数の戻り値として欲しい。 というのが要件だろう。 関数縛りがなければマクロですぐなんだが。
261 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 09:09:14.47 ] ごめんごめん途中で送信してしまった。 読まなくても良いくらいC++でのスタンダードな回答。 struct filter_t{ int e; const char *t; }; struct fizzbuzz_t { int in; std::string out; fizzbuzz_t &operator >>( filter_t &f ) { if( 0==in%f.e ){ out.append( f.t ); } return *this; } operator const char *() { if( out.length() ) return out.c_str(); static char tmp[50]; itoa( in, tmp, 10 ); return tmp; } }; fizzbuzz_t operator >>( int i, filter_t &f ){ fizzbuzz_t fb; fb.in = i; fb>>f; return fb; } filter_t fizz = { 3, "Fizz", }; filter_t buzz = { 5, "Buzz", }; filter_t gizz = { 7, "Gizz", }; int main(){ 105>>fizz>buzz>>gizz; return 0; }
262 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 09:19:13.99 ] スタンダードっていうより姑息だな。(←褒め言葉) とはいえ、関係ない演算子をしれっとまぎれこませちゃったら失格じゃまいか?
263 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 09:30:20.96 ] >>260 マクロを使わなくても、型クラスと多値とモナドが賢い言語なら関数でも書けるんじゃね?
264 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 09:49:06.63 ] >>257 map でそれをやれ、というのは無理。 それに hoge を追加することを想定して、 map (hoge . gizz . buzz . fizz) [1, 3, 5, 7, 15, 21, 35, 105] について考える。 関数合成と map の性質より、 map (f . g) [...] = map f (map g [...]) であるから map (hoge . gizz . buzz . fizz) [1, 3, 5, 7, 15, 21, 35, 105] = map hoge (map (gizz . buzz . fizz) [1, 3, 5, 7, 15, 21, 35, 105]) = map hoge [1, "FIzz", "Buzz", "Gizz", "FizzBuzz", "FizzGizz", "BuzzGizz", "FizzBuzzGizz"] よって hoge が書けない。===== 終 ===== 了 ===== -- という風に論破されちゃうのが嫌な自称上流には嫌われるだろうなぁ、 -- Haskell や形式手法はw
265 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 10:04:19.47 ] メソッドの追加は副作用よりも難しい 代入しても型は不変だがメソッドを追加したら型が変わる
266 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 10:10:13.95 ] マクロも型クラスも多値もモナドも無いけどSqueak Smalltalkで。 Trait named: #FizzBuzz uses: #() category: 'FizzBuzz-Trait' FizzBuzz >> fizzBuzzPrep self value isString ifFalse: [thisContext sender receiver: self -> '']. FizzBuzz >> fizzBuzzReturn | method nextByte type | method := thisContext sender sender method. nextByte := thisContext sender sender method at: thisContext sender sender pc. type := nextByte // 16. ^(type = 13 and: [FizzBuzz selectors includes: (method literalAt: nextByte \\ 16 + 1)]) ifTrue: [self] ifFalse: [self value ifEmpty: [self key]] FizzBuzz >> fizz self fizzBuzzPrep. (self key isDivisibleBy: 3) ifTrue: [self value: self value, 'Fizz']. ^self fizzBuzzReturn FizzBuzz >> buzz self fizzBuzzPrep. (self key isDivisibleBy: 5) ifTrue: [self value: self value, 'Buzz']. ^self fizzBuzzReturn FizzBuzz >> gizz self fizzBuzzPrep. (self key isDivisibleBy: 7) ifTrue: [self value: self value, 'Gizz']. ^self fizzBuzzReturn Integer uses: FizzBuzz. Association uses: FizzBuzz. 105 fizz gizz buzz. "=> 'FizzGizzBuzz' "
267 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 10:18:03.23 ] >>256 は runFizzBuzz に渡す前までは文字列の蓄積で通してるから、 putStrLn を削るだけでリストになるんじゃね?
268 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 10:45:33.86 ] 継続使える言語なら書けるんじゃね?
269 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 11:19:14.13 ] Scheme使いの登場を待ってるわけ? てか継続をどう使うことを想定してるの?
270 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 12:38:39.46 ] join fs n = case concatMap (\f -> f n) fs of "" -> Left n s -> Right s fizzT f s n | f n == 0 = s fizzT _ _ _ | otherwise = "" fizz = fizzT (`mod` 3) "Fizz" buzz = fizzT (`mod` 5) "Buzz" gizz = fizzT (`mod` 7) "Gizz" main = print $ join [fizz, buzz, gizz] 105
271 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 12:50:09.96 ] こっちのほうが join を入れ子に出来て良いかも import Data.Either join fs n = case concat $ rights $ map (\f -> f n) fs of "" -> Left n s -> Right s fizzT f s n | f n == 0 = Right s fizzT _ _ _ | otherwise = Right "" fizz = fizzT (`mod` 3) "Fizz" buzz = fizzT (`mod` 5) "Buzz" gizz = fizzT (`mod` 7) "Gizz" main = print $ join [join [fizz, buzz], gizz] 105
272 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 13:14:50.14 ] join とか無しで gizz buzz fizz 105 で "FizzBuzzGizz" をさくっと返す方法はないの?
273 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 13:43:15.17 ] ここまでruby/python無し LLに有利っぽいのに
274 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 13:43:49.58 ] gizz buzz fizz 105 という式が、ちゃんと型を持っているとする。 また、fizz 105、buzz fizz 105 という式も、同様になんらかの型を持つとする。 すると、 fizz の型は Int -> a buzz の型は (Int -> a) -> Int -> b gizz の型は ((Int -> a) -> Int -> b) -> (Int -> a) -> Int -> c というような型でなければならない。無理。というか、どう頑張っても、 先頭に do か何かが要る。
275 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 13:56:46.55 ] 型システムに制約を受けないパワフルな関数型言語ってのはないもんかね。
276 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 14:00:17.79 ] Perlしか読めないから誰かPerlで書いて
277 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 14:04:41.69 ] >>275 Erlang ?
278 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 14:24:54.40 ] >>273 つーか元出題者が Ruby だとオープンクラスやらなんやら使ってできるぜ、 って言いたいだけで作った問題なのがかなり見え見えなんだが。
279 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 15:57:16.91 ] 書き込み行数がオーバーするんで適当に圧縮した module FizzBuzz SYM_HASH = {} ; def self.add_fizz sym, n ; SYM_HASH[sym] = n ; end def self.do_it sym, n, prefix ; if m = SYM_HASH[sym] if n % m == 0 s = sym.to_s ; s.capitalize! if prefix.kind_of? String then s[0, 0] = prefix end s.fizzbuzzval = n ; s else prefix end else nil end end end class Integer ; def method_missing sym if it = FizzBuzz.do_it(sym, self, self) then it else super end end end class String ; attr_writer :fizzbuzzval ; def method_missing sym if it = FizzBuzz.do_it(sym, @fizzbuzzval, self) then it else super end end end FizzBuzz.add_fizz :fizz, 3 FizzBuzz.add_fizz :buzz, 5 FizzBuzz.add_fizz :gizz, 7 p [1, 3, 5, 7, 15, 21, 35, 105].map{|n|n.fizz.buzz.gizz}
280 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 16:17:23.17 ] >>276 突貫工事だけれど… package FizzBuzzGizz; sub new { my ($c, $n) = @_; bless {n => $n, s => ''}, $c } sub fizz {my $t = shift; $t->{s} .= 'Fizz' if 0 == $t->{n} % 3; $t} sub buzz {my $t = shift; $t->{s} .= 'Buzz' if 0 == $t->{n} % 5; $t} sub gizz {my $t = shift; $t->{s} .= 'Gizz' if 0 == $t->{n} % 7; $t} sub result {my $t = shift; $t->{s} ? $t->{s} : $t->{n}} 1; package main; do { my $fbg = new FizzBuzzGizz($_); print "$_:" . FizzBuzzGizz::result($fbg->fizz->buzz->gizz) . "\n" # あるいは print "$_:" . $fbg->fizz->buzz->gizz->result . "\n" } for qw{1 3 5 7 15 21 35 105}; $ perl p_fizzBuzzGizz.pl 1:1 3:Fizz 5:Buzz 7:Gizz 15:FizzBuzz 21:FizzGizz 35:BuzzGizz 105:FizzBuzzGizz
281 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 16:22:11.22 ] >>280 objectのmethodが返す値はまたobjectだけれど、 printで評価すると判定結果文字列を返すには、 こんな書き方くらいしかないのかな…? 多値のリスト返しでやってみようと思ったけれどうまい方法が思いつかなかったぜよ
282 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 17:12:42.66 ] >>281 package FizzBuzzGizz; sub new { my ($c, $n) = @_; bless \"$n." } sub fizz {my $t=shift; $_=$$t; bless do { /(^\d+)/; 0 == $1 % 3 ? \"${_}Fizz": $t }} sub buzz {my $t=shift; $_=$$t; bless do { /(^\d+)/; 0 == $1 % 5 ? \"${_}Buzz": $t }} sub gizz {my $t=shift; $_=$$t; bless do { /(^\d+)/; 0 == $1 % 7 ? \"${_}Gizz": $t }} 1; package main; do { my $fbg = new FizzBuzzGizz($_); print ${$fbg->fizz->buzz->gizz} . "\n" } for qw{1 3 5 7 15 21 35 105};
283 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 17:29:05.85 ] >>272 何縛りのゲームなのかわからんけど、関数合成演算子でも駄目かね? import Data.Either import Prelude hiding ((.)) (.) f g n = case concat $ rights [f n, g n] of [] -> Left n s -> Right s fizzT f s n | f n == 0 = Right s fizzT _ _ _ | otherwise = Right [] fizz = fizzT (`mod` 3) "Fizz" buzz = fizzT (`mod` 5) "Buzz" gizz = fizzT (`mod` 7) "Gizz" main = print $ fizz.buzz.gizz $ 105
284 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 17:30:10.61 ] >>282 package FizzBuzzGizz; sub new { my ($c, $n) = @_; bless \"$n." } sub comm { my ($t, $r, $s) = @_; $$t =~ /(^\d+)/; 0 == $1 % $r ? \"${_}$s": $t } sub fizz {bless comm((shift), 3, 'Fizz')} sub buzz {bless comm((shift), 5, 'Buzz')} sub gizz {bless comm((shift), 7, 'Gizz')} 1; package main; for (qw(1 3 5 7 15 21 35 105)) { print ${new FizzBuzzGizz($_)->fizz->buzz->gizz} . "\n" }
285 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 17:31:15.65 ] Ruby のカオスな部分を前面に押し出して書いてみた class String attr_accessor :srcint private def f(n,s); (@srcint % n == 0) ? (self << s) : (self); end end class Integer private def f(n,s); (self % n == 0) ? (s.srcint = self; s) : (self); end end class Object def fizz; f(3,'Fizz'); end def buzz; f(5,'Buzz'); end def gizz; f(7,'Gizz'); end end p [1,3,5,7,15,21,35,105].map{|n| n.fizz.buzz.gizz } # => [1, "Fizz", "Buzz", "Gizz", "FizzBuzz", "FizzGizz", "BuzzGizz", "FizzBuzzGizz"] p [1,3,5,7,15,21,35,105].map{|n| n.fizz.gizz.buzz } # => [1, "Fizz", "Buzz", "Gizz", "FizzBuzz", "FizzGizz", "GizzBuzz", "FizzGizzBuzz"]
286 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 17:33:52.32 ] >>284 ${_}$s←バグ package FizzBuzzGizz; sub new { my ($c, $n) = @_; bless \"$n." } sub comm { my ($t, $r, $s) = @_; 0 == $$t % $r ? \"$${t}$s": $t } sub fizz {bless comm((shift), 3, 'Fizz')} sub buzz {bless comm((shift), 5, 'Buzz')} sub gizz {bless comm((shift), 7, 'Gizz')} 1; package main; for (qw(1 3 5 7 15 21 35 105)) { print ${new FizzBuzzGizz($_)->fizz->buzz->gizz} . "\n" }
287 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 17:45:43.30 ] >>286 オッチャン、どうせ書くならこうやろ package FizzBuzzGizz; sub new { my ($c, $n) = @_; bless \"$n." } sub com { my ($t, $m, $s) = @_; bless 0 == $$t % $m ? \($$t.$s): $t } sub fizz {com(shift, 3, 'Fizz')} sub buzz {com(shift, 5, 'Buzz')} sub gizz {com(shift, 7, 'Gizz')} 1; package main; for (qw(1 3 5 7 15 21 35 105)) { print ${new FizzBuzzGizz($_)->fizz->buzz->gizz} . "\n" } 大差ないか…
288 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 17:54:12.60 ] new FizzBuzzGizz($_) している時点でダメだろ。
289 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 17:58:22.56 ] >>288 え?なぜ?
290 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 18:10:15.39 ] 関係ないオブジェクトにもfizz buzz gizzが継承されてしまう気持ち悪さを除けば、 ちゃんと書けているのは今のところRubyだけって感じか。 文字列オブジェクトにインスタンス変数(状態)を持たせられるのが強みだなぁ。 Smalltalkのはやってることが「独立した関数(メソッド)」と呼ぶにはどーよという内容だから失格。 関数型は型システムの制約でこういう仕様の関数モドキは書けないっていうことでFA?
291 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 18:22:32.06 ] >>290 でも実際のところ、こんな書き方したくないけどね 実際にやるなら、何らかのコンテナにラップしてからmapして それが終わったら、文字列や数値として取り出すと思う 原文がいきなり数値に対してメソッド呼んでるから、容赦なく組み込みクラスを弄ったが…
292 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 18:30:51.94 ] JSならやれそうじゃね?
293 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 18:33:45.54 ] >>291 まあクイズだからね。言語機能をどう使って無茶な要件をクリアするかのパズルみたいなもん。
294 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 18:35:01.97 ] >>292 まずコード出せ。話はそれからだ。
295 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 18:57:18.70 ] 数値がobjectとしてmethodを持たない言語ではどうするかってお題だったのかよ…
296 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 19:00:25.49 ] >>290 自分の足を自分で撃ちたいなら、それに向いた言語ある、という話、でFA
297 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 19:35:12.73 ] >>290 RubyはメソッドチェインOKなのに 関数型言語はfizz(buzz(gizz))しか認めないんだろ? そりゃ静的型じゃ無理っつーか制限する意味が分からん 後からgizz等を追加できる拡張性あるコードを 書けないならともかく、そうでもないしな
298 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 19:40:42.95 ] >文字列オブジェクトにインスタンス変数(状態)を持たせられるのが強みだなぁ。 -- String "has-a" Integer data HasA = HasA String Integer instance Show HasA where show (HasA s n) = if s == "" then show n else show s fizz (HasA s n) = HasA (s ++ if mod n 3 == 0 then "Fizz" else "") n buzz (HasA s n) = HasA (s ++ if mod n 5 == 0 then "Buzz" else "") n gizz (HasA s n) = HasA (s ++ if mod n 7 == 0 then "Gizz" else "") n main = print $ map (gizz . buzz . fizz . HasA "") [1,3,5,7,15,21,35,105]
299 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 19:47:44.31 ] >>298 似たようなコード書いてたら先に張られてた 個人的には hasA = HasA "" を定義しておくのが好み それはともかく、.演算子使ってるからケチ付けられると思うぜ多分w
300 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 19:56:22.62 ] >>294 おまえはどれかのコード書いたの?
301 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 20:00:44.98 ] ここまでJava無し
302 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 20:30:30.61 ] JavaScriptできた。俺の使ってるブラウザ以外で動くかどうかはわからん。 var def_fizz = function (name, m) { var fun = function () { var tp = typeof this.valueOf(); var n = (tp === 'number') ? this : this.fizzbuzzval if (n % m === 0) { var s = name.charAt(0).toUpperCase() + name.slice(1); if (tp === 'string') { s = this + s; } s = new String(s); s.fizzbuzzval = n; return s; } else { return this; } } ; Number.prototype[name] = fun; String.prototype[name] = fun; } ; def_fizz('fizz', 3); def_fizz('buzz', 5); for (var i = 1; i <= 30; ++i) { document.writeln(i.fizz().buzz()); }
303 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 20:36:17.98 ] >>301 toro.2ch.net/test/read.cgi/tech/1313183984/190 ‥‥ごめんなさい。
304 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 22:09:50.27 ] あるいはこうかな? toro.2ch.net/test/read.cgi/tech/1313183984/191
305 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 22:25:54.85 ] newはダメらしい…>>288
306 名前: ◆QZaw55cn4c mailto:sage [2012/04/13(金) 22:40:22.27 ] >>305 ΟΓΖ 基本データ型のリテラル単独でクラスのインスタンスになり得ない言語である以上、new しないことにははじまらない‥‥。
307 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 22:42:51.66 ] >>306 newを隠蔽すればいいだけ
308 名前:デフォルトの名無しさん mailto:sage [2012/04/13(金) 23:24:10.63 ] いやいや。基本データ型がオブジェクトでなかったり 組み込みクラスにメソッドを追加できない言語では 普通に関数で実装すればいいと思うよ。gizz( buzz( fizz( n ) ) )みたいに。
309 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 00:02:15.95 ] >>308 それが一番シンプルだと思う。 速度も早いだろうしね。
310 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 00:25:40.80 ] >>309 それがね、gizz() buzz() fizz()の三関数をどれも特別扱いせず、 いずれの戻り値もいずれの引数となり得る柔軟さを備える仕様にし、かつ print gizz( buzz( fizz( n ) ) )で 1 "Fizz" "Buzz" "Gizz" "FizzBuzz" "FizzGizz" "BuzzGizz" "FizzBuzzGizz" という出力を得るのは、以外とマンドくさいのよ。 gizz()だけは文字列を返すなどそれぞれの関数のIFを個別に制約すれば子供の使いなみに楽。 つかこういう要求仕様でnewは使うなとか制限もうけること自体が仕様策定の段階でミスなんだろ。
311 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 00:32:11.23 ] その意外と面倒くさいところをどう回避するかがこのクイズの味噌なんだが。(´・ω・`)
312 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 00:51:08.06 ] >>299 > .演算子使ってるからケチ付けられると思うぜ多分w 志村! HasA! HasA!
313 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 01:11:55.03 ] >>311 そしたら、こうだな。 sub com { my ($mod, $zz, $num, $str) = @_; $str .= $zz if 0 == $num % $mod; $str ? ($num, $str) : $num } sub fizz {com(3, 'Fizz', @_)} sub buzz {com(5, 'Buzz', @_)} sub gizz {com(7, 'Gizz', @_)} print "$_: " . gizz(buzz(fizz($_))) . "\n" for qw(1 3 5 7 15 21 35 105); 実効例: $ perl p_FizzBuzzGizzAret.pl 1: 1 3: Fizz 5: Buzz 7: Gizz 15: FizzBuzz 21: FizzGizz 35: BuzzGizz 105: FizzBuzzGizz perlのscalar context/list contextを巧みに?利用してるんで、 それを知らない人には分かりにくいかもしれず、申し訳ないんだか… ※もうちょっと考えて出題して欲しいな、言っちゃ悪いがこういった仕様策定ミスをcodeでカバーすることに何の意味が…
314 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 01:16:27.94 ] perlのscalar context/list contextの説明。 関数の引数にフラグを一個追加したもの つまり、 foo(value, false) ・・・ スカラ呼び出し foo(value, true) ・・・ リスト呼び出し foo(value, flag)関数の説明 flagがfalseの場合、スカラタイプの値を返します。 flagがturの場合、リストタイプの値を返します。 まあ、こんなもん。
315 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 01:24:45.45 ] >>314 志村、ここ、ここ。 my ($mod, $zz, $num, $str) = @_; ↑ $str ? ($num, $str) : $num sub xxx {com(3, 'Fizz', @_)} ↑ print "$_: " . gizz(buzz(fizz($_))) . "\n" と print "$_: " , gizz(buzz(fizz($_))) , "\n" の動作の違い なんか、中途半端に知っている人が出てきたな… 寝るか…。ノシ
316 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 01:45:08.21 ] 核の部分はこれだけか sub com { my ($mod, $zz, $num, $str) = @_; $str .= $zz if 0 == $num % $mod; $str ? ($num, $str) : $num } sub fizz {com(3, 'Fizz', @_)} sub buzz {com(5, 'Buzz', @_)} sub gizz {com(7, 'Gizz', @_)}
317 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 02:13:05.47 ] Perlは良く知らないのだが、 print が ($num, $str) の $num を都合よく読み捨ててくれるのは何故? print fizz(3) の出力は、3Fizz になりそうに思うんだが。よーわからん。
318 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 02:16:18.43 ] >>317 そゆ話は質問スレ ttp://toro.2ch.net/test/read.cgi/tech/1330666216/
319 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 02:40:58.54 ] >>317 結局 Perl のはこのクイズの要求には到達できてなくて(関数単体では完結できていない)、 出力時の文字列との結合でごまかしているってカラクリ。map とかすればズルが露呈する。
320 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 02:52:04.92 ] >>319 ズルはしてないよ。返戻contextの何番目を数値、何番目を文字列とし後続を省略時はundefとなる 利用しているだけでこういうやり方は使うときは使う。 でも、こういうズレたクイズはもういいよ。 関数型言語、オブジェクト指向言語の比較としてこの題材がどういう意味を持っているの? これ単に>>297 とか排除して特定の機能を持った言語を有利に導きたかっただったんじゃない?
321 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 03:04:43.03 ] じゃあ、map版です。 use 5.12.0; sub com { my ($mod, $zz, $num, $str) = @_; $str .= $zz ;if 0 == $num % $mod; $str ? ($num, $str) : $num } sub fizz {com(3, 'Fizz', @_)} sub buzz {com(5, 'Buzz', @_)} sub gizz {com(7, 'Gizz', @_)} map{say "$_: " . gizz(buzz(fizz($_)))} qw(1 3 5 7 15 21 35 105);
322 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 03:07:01.05 ] >>321 しくったorz、ifの前の;が余計だった。 use 5.12.0; sub com { my ($mod, $zz, $num, $str) = @_; $str .= $zz if 0 == $num % $mod; $str ? ($num, $str) : $num } sub fizz {com(3, 'Fizz', @_)} sub buzz {com(5, 'Buzz', @_)} sub gizz {com(7, 'Gizz', @_)} map {say "$_: " . gizz(buzz(fizz($_)))} qw(1 3 5 7 15 21 35 105);
323 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 03:07:30.38 ] そっちじゃなくて、print時の文字列連結による$numの読み飛ばしの件についてでしょ。 print "$_: " , gizz(buzz(fizz($_))) , "\n" だと 3: 3Fizz とかなる。
324 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 03:14:00.28 ] >>323 「gizz,buzz,fizzの三関数をscalar contexで評価すると判定文字列が得られ list contextで評価すると数値と判定文字列のリストが得られる関数である ただし数値が3,5,7の倍数でない場合は返戻リストの第二要素の判定文字列は undef(文字列として評価すると空文字列)」 という仕様の関数として書いている。 のだよ。code嫁よ。
325 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 03:17:44.46 ] >>297 の主張もじっさい意味不明なんだけど。。。 メソッドチェーンっていうのは関数の入れ子の呼び出し gizz(buzz(fizz(n))) と実質同じだろ? 組み込みの関数合成関数の使用を禁じている訳ではないのだから、要求通り関数で完結できてさえいれば それらを合成しようがぜんぜん問題ないし、型システムのモデルが足を引っ張っている以外、 なにが不利なのかさっぱり分からん。Perl のズル同様で、関数で完結できてないくせに 合成関数のオーバーロードでつじつまを合わせようとするからなんだかなーとなる。
326 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 03:19:31.46 ] >>322 "$_: " . ってのを無しでやっみてくんない?
327 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 03:21:01.17 ] >>325 ずれてないよ。 値と評価文字列をlistdで返戻する。 scalarで評価するかlistで評価するかで 返戻を両方参照するか、そのうちの判定文字列だけを印字出力などのために使うか 選択しているだけだよ。
328 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 03:25:52.86 ] >>326 sub com { my ($mod, $zz, $num, $str) = @_; $str .= $zz if 0 == $num % $mod; $str ? ($num, $str) : $num } sub fizz {com(3, 'Fizz', @_)} sub buzz {com(5, 'Buzz', @_)} sub gizz {com(7, 'Gizz', @_)} map {print gizz(buzz(fizz($_))) . "n"} qw(1 3 5 7 15 21 35 105);
329 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 03:27:01.29 ] ニヤニヤ
330 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 03:27:10.20 ] Perlは醜いラクダどころか白鳥だったのか 他の言語の立場がないな
331 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 03:27:54.81 ] >>328 しくった。 "n" → "\n"
332 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 03:38:24.58 ] 天然?
333 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 03:41:23.69 ] いや、コピペミスw
334 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 03:43:40.92 ] 多数値の返り値の、主値かそれ以外か、を使う手があるわけか
335 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 03:43:48.91 ] >scalarで評価するかlistで評価するか そんなの認めるんなら、C++だと型キャストのオーバーロードがあるから楽勝じゃねーか。 operator const char*(); operator const int(); こんなんすりゃ良いんだろ? ちなみに当たり前にオーバーロードがあるから、Fizz(3)とFizz(FizzBuzzObj)との区別もつくし。 C++ですら出来るんなら、この話もう終わりになっちまうじゃねーか。
336 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 03:45:12.07 ] しかし、ruby以外はズル、という結論にしたくて必死らしいが、 むしろrubyやJavaScriptがチートだろw リフレクション使いまくってるしw
337 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 03:46:02.04 ] >>335 書け書け。だれもC++をけなしてないぞw 後出しじゃんは、なしね。
338 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 03:59:30.30 ] >>337 すでに >>261 に書いた。
339 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 04:40:06.83 ] C++の>>261 がありなら Haskellの>>283 もありだよな ていうか、>>325 がズルと言ってるの理由がさっぱり分からん 演算子オーバーロードのある言語でそれ使って何が悪いの? 別にmapもできるぜ? main = print $ map (fizz.buzz.gizz) [1,3,5,7,15,21,35,105]
340 名前:339 mailto:sage [2012/04/14(土) 05:12:10.70 ] まあいいや、関数合成のオーバーロードは無しで >>312 の言う通りHasAも隠蔽すれば良いんだな? data HasA = HasA String Integer deriving Eq instance Show HasA where show (HasA s n) = if s == "" then show n else s instance Num HasA where (+) (HasA r m) (HasA s n) = HasA (r ++ s) (m + n) (-) (HasA r m) (HasA s n) = HasA "" (m - n) (*) (HasA r m) (HasA s n) = HasA "" (m * n) negate (HasA s n) = HasA s (-n) abs (HasA s n) = HasA s (abs n) fromInteger n = HasA "" n signum (HasA s n) = HasA s (signum n) fizz (HasA s n) = HasA (s ++ if mod n 3 == 0 then "Fizz" else "") n buzz (HasA s n) = HasA (s ++ if mod n 5 == 0 then "Buzz" else "") n gizz (HasA s n) = HasA (s ++ if mod n 7 == 0 then "Gizz" else "") n main = print $ map (gizz . buzz . fizz) [1,3,5,7,15,21,35,105]
341 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 05:12:11.99 ] F#で演算子オーバーロードなし。 let threadLocal = new System.Threading.ThreadLocal<_>() let makeFizzBuzz name condition (x : obj) = match x with | :? int as number -> threadLocal.Value <- number if condition number then box name else box number | :? string as names -> box (if condition threadLocal.Value then names + name else names) | _ -> failwith "ロジックエラー" let fizz = makeFizzBuzz "Fizz" (fun x -> x % 3 = 0) let buzz = makeFizzBuzz "Buzz" (fun x -> x % 5 = 0) let gizz = makeFizzBuzz "Gizz" (fun x -> x % 7 = 0) > [1; 3; 5; 7; 15; 21; 35; 105] |> List.map (fun x -> gizz(buzz(fizz x)));; val it : obj list = [1; "Fizz"; "Buzz"; "Gizz"; "FizzBuzz"; "FizzGizz"; "BuzzGizz"; "FizzBuzzGizz"]
342 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 05:26:59.93 ] さーて、また関数型言語が不利になるルールが追加されるよー
343 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 05:45:13.46 ] 次は関数型言語使いがお題を出したらいいんじゃないか Rubyじゃこんなの書けないだろ的なのを スレタイの趣旨にも沿ってる
344 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 05:58:16.50 ] それ以前に「使える言語機能を恣意的に制限する」アホを 排除しておかないと比較にも議論にもなんねーんだよ
345 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 05:59:25.03 ] じゃあ、型的に間違ってるプログラムをコンパイルエラーにしてください、という問題はどうだろうか。 fizzbuzzのscheme多値版ね。マクロ使っちゃっちゃったけど。 (define-syntax fizz (syntax-rules () ((_ arg) (receive it arg (fuzzbuzz it "Fizz" 3))))) (define-syntax buzz (syntax-rules () ((_ arg) (receive it arg (fuzzbuzz it "Buzz" 5))))) (define fuzzbuzz (lambda (arg name m) (let* ((is-num (null? (cdr arg))) (s (if is-num "" (car arg))) (a (if is-num (car arg) (cadr arg)))) (if (= 0 (mod a m)) (values (string-append s name) a) (if is-num a (values s a)))))) (define main (lambda (_) (letrec ((loop (lambda (n) (if (<= n 30) (begin (print (buzz (fizz n))) (loop (+ n 1))))))) (loop 1))))
346 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 06:40:24.02 ] ループ禁止で再帰だけで書いてください、とかでも良いな 末尾再帰最適化の無い実装じゃスタックオーバーフロー
347 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 06:51:51.42 ] >>325 組み込みクラスを弄るのはOK 組み込み演算子を弄るのはNG 何故?
348 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 10:00:34.73 ] 初学者といっても 1.プログラミングを学ぶことが目的 2.作りたいものがあって、その手段としてプログラミングが必要 で違う。 1なら関数型言語は良い選択 2ならオブジェクト指向言語やLLの方が早い こういうスレの喧嘩は 1の人の多くは、プログラミングを座学として勉強しただけで実は何も作れない 2の人の多くは、作りたいものが動けばいいというだけでプログラミングに対する向上心がない という現実を反映しているだけ。
349 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 10:10:56.56 ] そしてモマエは 3向上心のカタマリのオレ様にケンカうってんのかーーー カワネーゾ
350 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 10:28:07.46 ] >>343 いまは人工的に作ったお題の信用がなくなってるんだよ そこでまた中立でない人間がお題を出しても、紙屑のように無視されるんじゃないの
351 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 10:47:19.60 ] >>306 QZってこんなスレまで見てるんだな
352 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 11:03:19.87 ] >>350 >>290 や>>325 のような上から目線で変なルール押し付けてくるウザいヤツが 居なければ、言語ごとのアプローチの違いが見れて 遊びとしては面白いんだがなぁ しかもウザいのに限って口だけでプログラム書けないんだ あ、もしかして>>290 や>>325 がこのスレに書いたコード在る?だったら謝るけど
353 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 11:31:51.96 ] すまんけどちょっと確認させてください。これまで出てきた関数型言語の回答で、 関数合成演算子(あるいは関数)を定義が必須な場合でも、関数 fizz だけ用いた fizz 1 や fizz 3 はちゃんと組み込み型の数値や文字列である 1 や "Fizz" を返せるのでしょうか? これって一応要件だと思うんですよね。C++ の回答についても同様です。 Ruby や JS 、Smalltalk の回答はすべてこれが出来ているみたいなんだけど。
354 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 11:49:35.83 ] C++は型キャストをカスタマイズできるからそれで対応したら良いと思う。 FizzBuzzオブジェクトから文字列型と数値型へのキャストをそれぞれ用意すればよし。
355 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 12:28:02.63 ] >>352 今でも十分おもしろいと思うよ。せっそうのない動的言語(OOといえばOOだけど、 ストラウストラップの抽象データ型OOでなくて、ケイの動的OO寄りの考え方)では 可能だけど、理論的にきっちりした関数型言語では実現不可な境界がはっきりしてきてて。 出来ないと分かっていることを出来ないときちんと理由付きで示せる勇気も見れるし。 他方で、動的言語でもすんなりできるとは限らないから各言語での工夫の仕方も興味深い。
356 名前:デフォルトの名無しさん mailto:sage [2012/04/14(土) 12:29:01.02 ] >>353 >>341 だけど、関数fizz, buzz, gizzをそれぞれ単独で使用した場合をテスト。 > [fizz; buzz; gizz] |> List.map(fun f -> [1; 3; 5; 7] |> List.map f);; val it : obj list list = [[1; "Fizz"; 5; 7]; [1; 3; "Buzz"; 7]; [1; 3; 5; "Gizz"]]