【激突】関数型言語 VS オブジェクト指向言語2at TECH
【激突】関数型言語 VS オブジェクト指向言語2 - 暇つぶし2ch345:デフォルトの名無しさん
12/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:デフォルトの名無しさん
12/04/14 06:40:24.02
ループ禁止で再帰だけで書いてください、とかでも良いな
末尾再帰最適化の無い実装じゃスタックオーバーフロー

347:デフォルトの名無しさん
12/04/14 06:51:51.42
>>325
組み込みクラスを弄るのはOK
組み込み演算子を弄るのはNG

何故?

348:デフォルトの名無しさん
12/04/14 10:00:34.73
初学者といっても
1.プログラミングを学ぶことが目的
2.作りたいものがあって、その手段としてプログラミングが必要
で違う。

1なら関数型言語は良い選択
2ならオブジェクト指向言語やLLの方が早い

こういうスレの喧嘩は
1の人の多くは、プログラミングを座学として勉強しただけで実は何も作れない
2の人の多くは、作りたいものが動けばいいというだけでプログラミングに対する向上心がない

という現実を反映しているだけ。

349:デフォルトの名無しさん
12/04/14 10:10:56.56
そしてモマエは
3向上心のカタマリのオレ様にケンカうってんのかーーー
カワネーゾ

350:デフォルトの名無しさん
12/04/14 10:28:07.46
>>343
いまは人工的に作ったお題の信用がなくなってるんだよ
そこでまた中立でない人間がお題を出しても、紙屑のように無視されるんじゃないの

351:デフォルトの名無しさん
12/04/14 10:47:19.60
>>306
QZってこんなスレまで見てるんだな

352:デフォルトの名無しさん
12/04/14 11:03:19.87
>>350
>>290>>325のような上から目線で変なルール押し付けてくるウザいヤツが
居なければ、言語ごとのアプローチの違いが見れて
遊びとしては面白いんだがなぁ
しかもウザいのに限って口だけでプログラム書けないんだ

あ、もしかして>>290>>325がこのスレに書いたコード在る?だったら謝るけど

353:デフォルトの名無しさん
12/04/14 11:31:51.96
すまんけどちょっと確認させてください。これまで出てきた関数型言語の回答で、
関数合成演算子(あるいは関数)を定義が必須な場合でも、関数 fizz だけ用いた
fizz 1 や fizz 3 はちゃんと組み込み型の数値や文字列である 1 や "Fizz" を返せるのでしょうか?
これって一応要件だと思うんですよね。C++ の回答についても同様です。
Ruby や JS 、Smalltalk の回答はすべてこれが出来ているみたいなんだけど。

354:デフォルトの名無しさん
12/04/14 11:49:35.83
C++は型キャストをカスタマイズできるからそれで対応したら良いと思う。
FizzBuzzオブジェクトから文字列型と数値型へのキャストをそれぞれ用意すればよし。

355:デフォルトの名無しさん
12/04/14 12:28:02.63
>>352
今でも十分おもしろいと思うよ。せっそうのない動的言語(OOといえばOOだけど、
ストラウストラップの抽象データ型OOでなくて、ケイの動的OO寄りの考え方)では
可能だけど、理論的にきっちりした関数型言語では実現不可な境界がはっきりしてきてて。
出来ないと分かっていることを出来ないときちんと理由付きで示せる勇気も見れるし。
他方で、動的言語でもすんなりできるとは限らないから各言語での工夫の仕方も興味深い。

356:デフォルトの名無しさん
12/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"]]

357:デフォルトの名無しさん
12/04/14 13:02:32.74
あ、すいません。F#さんを見落としていました。
F#以外の関数型言語の回答で、ですね!
わざわざの検証、いたみいります。

358:デフォルトの名無しさん
12/04/14 14:04:34.17
スレッドローカルに状態を保持するのはいいアイデアですね。

359:デフォルトの名無しさん
12/04/14 14:10:22.10
いいアイデアですねw

360:デフォルトの名無しさん
12/04/14 14:42:43.34
>>353
>>340だけどテストしてみた

*Main> [map f [1,3,5,7] | f <- [fizz, buzz, gizz]]
[[1,Fizz,5,7],[1,3,Buzz,7],[1,3,5,Gizz]]

361:デフォルトの名無しさん
12/04/14 14:50:32.97
>>353
ついでに>>283もテスト
正しく動かなかったので修正

fizzT f s = (\x -> Left x) . fizzT'
  where
    fizzT' n | f n == 0 = Right s
    fizzT' _ | otherwise = Right []

これで >>360と同じコードが動いた

362:361
12/04/14 15:07:31.88
面白かったのは>>283>>360を試して動かなかったとき
ちゃんとコンパイル時に型エラーになったこと
Haskellの型システムやるじゃん、みたいな

363:デフォルトの名無しさん
12/04/14 15:54:35.13
ねえねえ、1 から 3 までの fizz n の戻り値に対して、文字列なら全大文字化、整数なら 10 倍にして
map するコードを [1, 2, "Fizz"] に対して同じことをするコードとまったく同様に書いて
問題なく実行できるかどうか試しみててよ! クイズの要件をみたしていればできるよね!
もちろんいうまでもなく追加定義や修正は無しだよ。Ruby や F# のはもちろんできるよ!


364:340
12/04/14 16:01:06.17
>>360
fizz (HasA s n) = HasA (s ++ if mod n 3 == 0 then "Fizz" else "") (10 * n)

365:340
12/04/14 16:02:40.14
あ、ごめん>>363だった
それはさておき、後だしでルール追加するの本当に好きだね

366:デフォルトの名無しさん
12/04/14 16:06:40.84
>>363
じゃあ、組み込みクラスをグローバルに汚染するのも禁止しようぜ
classbox等で一部に制限できるならアリ

367:デフォルトの名無しさん
12/04/14 16:07:57.17
というか、ここのHaskellerはどうしてこうも要求仕様を読み取れないくせに
あまつさえ勝手な解釈で適当なコード書いてドヤ顔なの? バカなの? 死ぬの?

368:デフォルトの名無しさん
12/04/14 16:11:06.66
>>367
誰もお前の頭の中なんて知らないし興味ないんだから
言わないと分からないっつーの
ここはお前の要求仕様を満たす場じゃねーし
馬鹿はお前

あと、まさかコードも書かずに議論参加してたとか無いよな
書いたコードのレス示せよ
俺は>>340書いたぞ

369:デフォルトの名無しさん
12/04/14 16:16:29.12
(defmacro defun-fizz-buzz (name divisor)
`(defmacro ,name (form)
`(multiple-value-bind (int str) ,form
(values int
(if (= (mod int ,',divisor) 0)
(concatenate 'string str (string ',',name))
str)))))

(defun-fizz-buzz fizz 3)
(defun-fizz-buzz buzz 5)
(defun-fizz-buzz gizz 7)

370:デフォルトの名無しさん
12/04/14 16:21:51.37
>>367
> ドヤ顔なの?バカなの? 死ぬの?
w
いまどき、こんな台詞をわざわざ書くやつがいるんだww

371:デフォルトの名無しさん
12/04/14 16:23:54.35
勘違いしたふりして頓珍漢なコード出してきて、
言語や自分の発想の限界とかクリティカルなところはなんとか避けようとしているんだよ。
仕様を取り違えてるよってやんわりチェック方法をしめすと、
ルールを増やすな、後出しだ、仕様が欠陥だってなんやかやクレームつけて
相手が根負けして要求仕様のほうが変わるのを粘り強くじっと待つ戦略なんだ。
ある意味、賢いよ。

372:デフォルトの名無しさん
12/04/14 16:26:54.36
お題提出者の解答ってもう出てるの?

373:デフォルトの名無しさん
12/04/14 16:29:32.45
>>363
> map するコードを [1, 2, "Fizz"] に対して同じことをするコードとまったく同様に書いて

Haskellは静的型付けだから数と文字列を同じリストには入れられないんだ
そんなことも知らずに議論してたんじゃないよね?

374:デフォルトの名無しさん
12/04/14 16:32:03.01
>>371

>>368
> あと、まさかコードも書かずに議論参加してたとか無いよな
> 書いたコードのレス示せよ

って書いてるのに示さないってことは、まさか本当にコード書いてなかったの?

375:デフォルトの名無しさん
12/04/14 16:33:37.46
まさかの口だけ野郎説浮上www

376:デフォルトの名無しさん
12/04/14 16:44:57.11
>>363は問題が頓珍漢だけど(静的型で [1, 2, "Fizz"] はねーよw)
最大限エスパーして書いてみた

>>283はこんな感じ

conv (Left n) = Left $ 10 * n
conv (Right s) = Right $ map toUpper s
main = do
  print $ map conv [Left 1, Left 2, Right "Fizz"]
  print $ map conv $ map fizz [1,2,3]

>>340はこんな感じ

conv (HasA s n) = HasA (map toUpper s) (10 * n)
main = do
  print $ map conv [1, 2, "Fizz" `HasA` 3]
  print $ map conv $ map fizz [1,2,3]

377:デフォルトの名無しさん
12/04/14 17:03:29.49
>> xs = (1..3).map{ |n| n.fizz }
=> [1, 2, "Fizz"]
>> xs.map{ |x| case x when Integer then x*10 when String then x.upcase end }
=> [10, 20, "FIZZ"]
>> ys = [1, 2, "Fizz"]
=> [1, 2, "Fizz"]
>> ys.map{ |x| case x when Integer then x*10 when String then x.upcase end }
=> [10, 20, "FIZZ"]

378:デフォルトの名無しさん
12/04/14 17:45:03.77
◆QZaw55cn4c が出てきて有耶無耶になってるけど
「Javaドカタはコード書けない」説はまだ有効

379:デフォルトの名無しさん
12/04/14 17:57:01.51
◆QZaw55cn4c はドカタではないとでも

380:デフォルトの名無しさん
12/04/14 18:26:18.94
Haskellでコード書くだけで天才になれた気がした15の夜

381:デフォルトの名無しさん
12/04/14 18:49:30.59
敵はハスケラだけと思ってるところがウケるw
どんな言語使いから見ても口だけ野郎は最底辺のゴミだぞwww

382:デフォルトの名無しさん
12/04/14 18:52:07.05
おまえもなw

383:デフォルトの名無しさん
12/04/14 19:54:38.00
コード書けないドカタは「なでしこ」使えば良いんじゃないか?
運が良ければ日本語で書いた戯れ言が
実行されるかもしれないぞ

384:デフォルトの名無しさん
12/04/14 21:39:02.30
>>383
お前は詳しそうだな、その言語。
興味持って使ってみたのか?w

385:デフォルトの名無しさん
12/04/15 10:22:56.77
まだPythonは出てなかったので


class F(object):
    def __init__(self, f):
        self.fs = f if hasattr(f, '__iter__') else [f]
    def __call__(self, x):
        if isinstance(x, int):
            s = ''.join(f(x) for f in self.fs if isinstance(f(x), str))
            return x if s == '' else s
        else:
            return F(self.fs + [x])

fizz = F(lambda x: 'Fizz' if x % 3 == 0 else '')
buzz = F(lambda x: 'Buzz' if x % 5 == 0 else '')
gizz = F(lambda x: 'Gizz' if x % 7 == 0 else '')

print [fizz(buzz)(gizz)(x) for x in [1,3,5,7,15,21,35,105]]

386:デフォルトの名無しさん
12/04/15 10:31:36.36
F#、さすがだな。

387:デフォルトの名無しさん
12/04/15 10:48:20.05
>>385
可能なら、
gizz(buzz(fizz(105))) is "FizzBuzzGizz" となるようなヤツをお願いします。

388:デフォルトの名無しさん
12/04/15 10:55:31.60
>>387
理由を聞いても良い?
Pythonでは>>385のほうがデコレータでも使えて良いんだけど……

@fizz
@buzz
def bizz(x):
    if x % 11 == 0: return 'Bizz'
    else: ''

389:デフォルトの名無しさん
12/04/15 11:03:37.43
静的型言語にIntを返したりStringを返したりする関数って縛りがそもそも無理

390:デフォルトの名無しさん
12/04/15 11:07:14.65
>>388
>>254

391:デフォルトの名無しさん
12/04/15 11:08:32.55
PerlとかSchemeの、多値をうまく使ったのが一番エレガントかな。

RubyとかJSは、同じようなコードをStringとNumberの両方に生やすとか、
見事に汚い解だw

392:デフォルトの名無しさん
12/04/15 11:13:32.41
関数を返す関数(カリー化されてりゃ普通)にケチがつくとか
スゲーなこのスレ

393:デフォルトの名無しさん
12/04/15 11:16:23.31
>>390
ちゃんと「など」って書いてるぞー

> オープンクラス機構やメソッドのない言語では関数(buzz(fizz(3)) #=> "Fizz" など)で。

それとも高階関数は関数じゃないんですかー

394:デフォルトの名無しさん
12/04/15 11:20:37.25
>>389
それだけじゃない。
継続の状態如何で関数に振る舞いを変えさせるとか
関数型には無理な事ばかり要求している。
悪意に満ちたクイズだ。

395:デフォルトの名無しさん
12/04/15 11:23:20.66
>>394
素直に考えれば、オープンクラスのある言語が良いという
意見に持っていきたい問題だからね

でも出てきた解はRubyが一番汚いという

396:デフォルトの名無しさん
12/04/15 11:25:11.88
>>389
型クラスとかってこういう時には使えないの?

397:デフォルトの名無しさん
12/04/15 11:30:40.55
要求による。

問題の「#=> "FizzBuzz"」が意味しているものが、REPLでそのように表示されるもの、
という意味なら、Show型クラスでいいんだけど、String型([Char]型)を要求してるなら無理。

398:デフォルトの名無しさん
12/04/15 11:32:07.68
静的型 vs 動的型スレ向きの問題だよね

399:デフォルトの名無しさん
12/04/15 11:52:01.47
>>391
いやあ俺は>>341のF#(er)が一番エレガントだと思うぞ。
無茶な要求仕様も黙ってすべて満たしつつ、簡潔できれいなコード出してきてるし。

400:デフォルトの名無しさん
12/04/15 11:57:38.79
>>399
ThreadLocalが一番エレガントって
どういうセンスしてんだよ

401:デフォルトの名無しさん
12/04/15 12:04:48.59
#include <stdio.h>
#include <string.h>
int v,w,t;char buf[4<<10];void*fizz(void*n){if(!t&&!v){v=(int)n;t=!t;}
if(!(v%3))goto a;else if(!(w&0x7))goto b;else goto c;a:{size_t
(*f)(char*restrict,const char*restrict,size_t);f=(w&0x7)?strlcat
:strlcpy;w|=0x1;f(buf,"Fizz",4<<10);}goto c;b:{char b[2<<8];;;;;;;;;;;
snprintf(b,2<<8,"%d",v);strlcpy(buf,b,2<<8);}goto c;c:return buf;}void
*buzz(void*n){if(!t&&!v){v=(int)n;t=!t;}if(!(v%5))goto a;else
if(!(w&0x7))goto b;else goto c;a:{size_t/**/(*f)(char*restrict,const
char*restrict,size_t);f=(w&0x7)?strlcat:strlcpy;w|=0x2;f(buf,"Buzz",
4<<10);}goto c;b:{char b[2<<8];snprintf(b,2<<8,"%d",v);strlcpy(buf,b,
2<<8);}goto c;c:return buf;}void*gizz(void*n){if(!t&&!v){v=(int)n;t=!t;}
if(!(v%7))goto a;else if(!(w&0x7))goto b;else goto c;a:{size_t (*f)
(char*restrict,const char*restrict,size_t);f=(w&0x7)?strlcat:strlcpy;
w|=0x1;f(buf,"Gizz",4<<10);}goto c;b:{char b[2<<8];;;snprintf(b,2<<8,
"%d",v);strlcpy(buf,b,2<<8);}goto c;c:return buf;}int main(void){printf
("%s\n",gizz(buzz(fizz(105))));}

402:デフォルトの名無しさん
12/04/15 12:22:36.47
>>368
>あと、まさかコードも書かずに議論参加してたとか無いよな

>>395
>でも出てきた解はRubyが一番汚いという

このスレの特徴まとめ

403:デフォルトの名無しさん
12/04/15 12:34:01.13
>>399
グローバル変数ではまずいと考えてThreadLocalにしたみたいに見える
まずいという認識がありながら、それを上に報告しないのはおかしい
結局、要求に対する不平不満は正直に言えばいいんだよ

404:デフォルトの名無しさん
12/04/15 12:52:12.22
コード書けないドカタとプログラマでは綺麗さの認識が違う

405:デフォルトの名無しさん
12/04/15 13:06:57.34
そうだね
お前のコードかけないドカタって概念がおかしいけどねw

406:デフォルトの名無しさん
12/04/15 13:29:07.47
>>405
あれ?まだこのスレに居たの?
派遣仕事で使い慣れたJavaを使って良いから
早くエレガントな解を出してくださいよwww

407:デフォルトの名無しさん
12/04/15 13:32:57.13
くやしいんだねw

408:デフォルトの名無しさん
12/04/15 13:55:54.00
仕事しろ。言語の勉強はするだけ無駄。

求められているのは動くアプリだ。

409:デフォルトの名無しさん
12/04/15 14:23:06.70
そもそも関数としての体をなしてないのだから、
副作用を使わずにこのクイズは解けない。
よって純粋な関数型パラダイムでは対応不可。終了。

410:デフォルトの名無しさん
12/04/15 14:32:35.61
Scalaならいろいろ駆使して書けそうだけどな

411:デフォルトの名無しさん
12/04/15 14:38:59.15
>>393
この場合の「など」は、関数呼び出しにもいろいろありますよね、
buzz(fizz(3)) 、 (buzz (fizz 3)) 、buzz fizz 3 など―とかの「など」だと思われ。

412:デフォルトの名無しさん
12/04/15 15:23:11.97
関数じゃないものを
関数型言語で作るには
どうしたらいいのだろうか?

413:デフォルトの名無しさん
12/04/15 15:27:19.67
>>409
副作用なしに解いたSchemeさんが涙目です

414:デフォルトの名無しさん
12/04/15 15:35:03.47
>>411
三つ目が>>385だね(カリー化されてれば)
それとも見た目だけの問題?

415:デフォルトの名無しさん
12/04/15 16:42:00.03
F#でThreadLocal等の副作用もないバージョン。

type MainBuilder() =
    member this.Return x =
        x |> List.map (function
        | _, Some names -> box names
        | number, None -> box number)
let main = MainBuilder()

let makeFizzBuzz name condition (x : obj) =
    match x with
    | :? int as number -> number, if condition number then Some name else None
    | _ ->
        let number, names = x :?> int * string option
        number, if condition number then (defaultArg names "") + name |> Some else names

// fizz, buzz, gizzの定義は>>341と同じなので省略

> main { return [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"]

416:デフォルトの名無しさん
12/04/15 17:46:44.23
新ルール「カリー化禁止」

417:デフォルトの名無しさん
12/04/15 17:53:43.12
>>415
mainがダウト、なんじゃないか?

418:デフォルトの名無しさん
12/04/15 18:08:11.82
>>417
main { return ... } 部分をただのコードブロックとみせかけて
実は戻り値を変換しているという作戦だったのに、バレたか。

419:デフォルトの名無しさん
12/04/15 18:31:37.86
Smalltalkが流行らないように関数型メインは流行らないよ

420:デフォルトの名無しさん
12/04/15 18:34:04.58
ついに「流行らない」以外に縋るものがなくなっちゃったか

421:デフォルトの名無しさん
12/04/15 18:34:51.92
副作用ありとは言え、唯一まともな解出しててF#△だったのに
この期に及んで汚ないチートとかなにこのものすごい残尿感。

422:デフォルトの名無しさん
12/04/15 18:40:05.54
.NET発表時のHaskell.NETはどこに行ったんだよ?

423:デフォルトの名無しさん
12/04/15 18:43:46.95
マクロ使っていいならそもそも多値なんぞ使わんでも楽勝だろ。

424:デフォルトの名無しさん
12/04/15 18:47:39.47
FizzBuzzって流行ってるけど何が面白いの?

425:デフォルトの名無しさん
12/04/15 18:52:45.85
低能はFizzBuzzすら書けないという事実が面白い

426:デフォルトの名無しさん
12/04/15 18:53:02.18
>>423 具体的にドーゾ

427:デフォルトの名無しさん
12/04/15 19:04:47.51
オープンクラスとか副作用有り等の
汚いコードだけが「合格」www

勝手に判定してる(コード書けない)バカのセンスが露呈してますな

428:デフォルトの名無しさん
12/04/15 19:05:21.22
>>423
perl書いたのオレなんだけれどもさ、その通りなんだよな…

429:デフォルトの名無しさん
12/04/15 19:08:10.88
C#とかも関数型言語のエッセンスを取り入れるけど
すげえ無理矢理くさくて笑えるw
関数型がオブジェクト指向を取り入れるのはもっと自然なのに

オブジェクト指向っていうかC系列はもう駄目なんだと思う

430:デフォルトの名無しさん
12/04/15 19:18:55.29
守らなければならない資産がたくさんあるからな
そりゃ無理やりくさくもなるさ

431:デフォルトの名無しさん
12/04/15 19:28:01.70
後付で入れなきゃならなくなる時点で失敗だったはずなんだけどなぁ。
最近のC#の機能なんてC#以前から概念として存在してたはずなのに。
必要ないという当初の目論見は外れてるわけだ。

というか、資産っていうのはC風の構文そのものなんだよね・・・
C風じゃないとヤダヤダいう人が多すぎてD言語とかいちいち作られてる気がする。

C++、Java、C#、D言語
このへんは全て老害でしょ。

432:デフォルトの名無しさん
12/04/15 19:30:26.05
C#、D言語は設計に一貫した思想がないからアホっぽくなるのは仕方ない。

433:デフォルトの名無しさん
12/04/15 19:41:07.47
fizz 1 -- "1"
fizz 3 -- "Fizz"
buzz 5 -- "Buzz"
buzz fizz 15 -- "FizzBuzz"
だったらHaskellでも解ける?

434:デフォルトの名無しさん
12/04/15 19:45:23.42
可変長引数とかさーー

435:デフォルトの名無しさん
12/04/15 19:50:00.84
>>431
C系列でまともなのはCだけ

436:デフォルトの名無しさん
12/04/15 19:50:26.06
>>433
型の不整合が生じるから無理

437:デフォルトの名無しさん
12/04/15 19:52:02.10
>>432
C#はどんどんダメな方向に向かってる気はするわー。

438:デフォルトの名無しさん
12/04/15 20:01:50.15
Javascriptは結構好きなのよん > C系文法族

439:デフォルトの名無しさん
12/04/15 20:11:47.98
>>406
>>303-304

440:デフォルトの名無しさん
12/04/15 20:19:32.18
>>431
後付で入れてもらったのがScala、Clojure、F#でしょ
なんで後付を悪く言うのかな

441:デフォルトの名無しさん
12/04/15 20:41:24.35
C#は言語設計に一貫性がなく節操のないところが最大の魅力
偉い人にはそれがわからんのです

442:デフォルトの名無しさん
12/04/15 21:08:30.57
>>440
アホか
それらは最初から関数型言語として作られてるでしょ。
関数型は糞、オブジェクト指向最高ってスタンスで作ってたはずのもんが
なんで今更関数型の要素を入れようとするんだよ。

443:デフォルトの名無しさん
12/04/15 21:16:51.80
>>439
オーバーライドした toString() を println() に暗黙に呼ばせるとかいう
使い古されたチートをキメ顔で出してこられても…。
new myInteger(3).fizz() が "Fizz" を返せるとか少しは挑戦しようよ。

444:デフォルトの名無しさん
12/04/15 21:17:08.32
「.Netファミリーに関数型言語入ったからC#でも使えるようにすっか!」
くらいのノリだろ。たぶん
dynamic型導入したときもそんな感じだったし

445:デフォルトの名無しさん
12/04/15 21:18:37.55
いやC#の場合は「C#で~が出来ないと言わせない」という一貫した姿勢があると思う。
もともとJavaへの嫉妬から始まった言語だし。

446:デフォルトの名無しさん
12/04/15 21:21:52.66
>>442
手続き型言語がまずあって、
そこへOOの機能を取り入れた。
こんどはさらに関数型の機能も取り入れようとしているだけ。

447:デフォルトの名無しさん
12/04/15 21:40:30.50
C#厨ってVB.NETをVB厨のための言語って馬鹿にしてたけど
C#だってCっぽくないとヤダヤダっていう老害のために
無理矢理作ってるんだから全然人のこといえねーわ。
ラムダとかそんなに良いんならなんで最初から関数型言語使わないんだよw

448:デフォルトの名無しさん
12/04/15 21:46:15.09
>>442
> 関数型は糞、オブジェクト指向最高ってスタンスで作ってたはずのもんが
> なんで今更関数型の要素を入れようとするんだよ。

オブジェクト指向最高はそうかもしれないが、
関数型は糞なんて言ってないだろ。

現実世界における物質(オブジェクト)に対応づけやすい
自然な発想に基づくオブジェクト指向。
そこに便利な関数型を取り入れただけ。

りんごの方程式とは何か?を考えれば
オブジェクト指向と関数型の関係がわかるだろう。

449:デフォルトの名無しさん
12/04/15 21:48:54.81
C#作った奴らはvoidを型と思っていなかった。
だから、C#じゃクロージャ作るのに引数や戻り値にvoidがあると作れないw
やるには予めデリゲートを定義しなきゃならん。
クロージャを使うのを考えさせられる。
ありえん。手軽さが全然ない。

F#はローカル変数(厳密には違うが)を定義するのもクロージャを定義するのも同じ手間しかかからない。
クロージャをバンバン使っていけるのでクロージャの応用もどんどん閃ける。
F#やった方がC#が上手くなるという現実。
C#はやればやるほど馬鹿になる言語。

450:デフォルトの名無しさん
12/04/15 21:50:04.90
速度やメモリ・言語ごとの風習で最適かどうかは変わるのだろうけれど、
関数型でOOPをするときは、返り値として変更したオブジェクトを返すより、新たなオブジェクトを返したほうが関数型ぽいのかね?

451: ◆QZaw55cn4c
12/04/15 21:51:05.55
>>447
F#のことも思い出してあげてください

452:デフォルトの名無しさん
12/04/15 21:59:08.45
関数型言語でWindowsアプリを開発したいっつー需要がどれだけあるかだな

453:デフォルトの名無しさん
12/04/15 22:00:17.15
>>442
どちらが糞でどちらが最高かなんて、問い詰められても答えなくていいと思うんだが
沈黙が正解って小学生でも知ってる奴は知ってるだろ

454:デフォルトの名無しさん
12/04/15 22:54:52.02
>>443
>>443
がんばってみたんですが、糸口がみえてきません。もしよろしければアドバイスをいただけないでしょうか。

>new myInteger(3).fizz() が "Fizz" を返せる

① これは、「メソッド fizz() が副作用として "Fizz" を出力する」ということですか?
この場合、fizz(), buzz(), gizz() を通過してきて 3 でも 5 でも 7 でもわりきれなかった場合に元の数字を出力する、ということが不可能だと思います。
>>303 では妥協して endl() というメソッドを準備してこの処理を行うしかありませんでした。

② それとも「メソッド fizz() の返り値が String("fizz") であるべき」ということですか?
String にメソッド fizz() を追加したいのであれば、 String から新しいクラスmyString を継承して、そこにメソッドを定義するということだろうと思いますが、
(new myString(3).fizz() が myString("Fizz") を返す)
②-1 java.lang.String は final。
②-2 メソッド fizz() が "Fizz" を返してしまうと、もとの String("3") を忘れてしまい、buzz(), gizz() が処理できない。多値を返したいのですが >>304 で精一杯。
>>304 の toString()#Object をオーバーライドする、ってこういうときには普通にすることだと思っていたんですが、何かまずい問題でもあるのでしょうか?

455:デフォルトの名無しさん
12/04/15 23:40:26.22
トイプログラムしか書かない奴は言語なんて何でもいいだろw

456:デフォルトの名無しさん
12/04/15 23:47:29.56
>>443
>>303 の方針でがんばってみました。gizz() は最後に置かなければならない、と決めうちすることにしました。
スレリンク(tech板:194番)

457:デフォルトの名無しさん
12/04/15 23:49:17.32
苦しいねぇ

458:デフォルトの名無しさん
12/04/15 23:50:41.61
>>454
> fizz() が "Fizz" を返してしまうと、もとの String("3") を忘れてしまい、buzz(), gizz() が処理できない

その一見回避不可能な問題を解決する方法を考えるのがこのクイズがクイズたるゆえんです。
言語によっては型システムの制約によりどうやっても実現できないこともあります。

459:デフォルトの名無しさん
12/04/16 00:02:21.18
>>450
関数型に限らず、GCのあるOOPLだと
属性変更をせずに新規オブジェクトをサクサク作るやり方も結構使うね

460:デフォルトの名無しさん
12/04/16 00:45:51.08
>>454
>>341の方法(元の数値をどこかにメモしておいて適宜参照)はJavaでも使えます。

461:デフォルトの名無しさん
12/04/16 01:11:55.59
>>458
OOとPFの言語比較としてこのようなクイズを出したのは、
どのような観点からこれら両者のパラダイムの優劣を比較しようとしたのか
聞きたい

462:デフォルトの名無しさん
12/04/16 01:13:44.79
もうこのお題はcloseでいいんじゃないの?
このクイズではせっかくの労力を生産的でないことに費やしている

463:デフォルトの名無しさん
12/04/16 01:30:58.12
>>462
クイズなんかそんなもんだろ。しょせん暇つぶし。
つーか、こんな程度のクイズ解くのに「労力」なんか大仰なもん必要か?

464:デフォルトの名無しさん
12/04/16 01:38:59.77
このクイズのくだらなさはかなり問題。

465:デフォルトの名無しさん
12/04/16 01:48:07.75
くやしいのうw

466:デフォルトの名無しさん
12/04/16 02:07:04.82
全然くやしくないぜよ。perlでobjectのnew版も多値版もさらりと書いた。
tieとマクロ使ったのも書こうと思ったけれど手間がもったいなくなってやめた。
パラダイム比較としてもうすこし書く値打ちのあるテーマ出せよ、
このクイズじゃ再帰は使いどころないし
javaのnewだめ静的型システムダメ
何を有利に誘導したいんだか
せめて前スレのpermutationレベルのテーマを出題の下限レベルとしてクレヨ

467:466
12/04/16 02:18:35.03
大体fizz buzzってのが下らないんだよ
プログラムプロムナード、ナノピコ教室、Cマガ課題、オイラー4、AIアルゴリズム、OR最適化、
パーサ、マッチング、グラフ問題あたりの
小問題で再帰・高階/部分適用、遅延・カーリー化vsOOの比較できる題材が妥当かもな
step数は2chの1レスに収まるくらいの小問題でいいからサ

468:466
12/04/16 02:26:58.99
最悪、基本アルゴリズムの再実装でもいいや
たとえばqsortはperlやhaskellでpivotを適当に選択して再帰した短いコードと
pivot選択くどくど頑張ったCやjavaの長いコード比較してファンクショナルの再帰はマンセーみたいな
サイトがあちこちにあるだろ、
あのレベルでも今回のFizzBuzzGizzよりましだろ

469:466
12/04/16 02:35:35.13
あと、言い出しっぺの法則はナシだぞw


470:466
12/04/16 02:44:04.67
つか、OOとPFの単純比較って何か意味あるのか?
どのみち記述する言語の特徴または弱点、癖の比較レベルの議論に落ちがちな稀ガス
ズット前スレでヨンだが、意味論的にはOOとPFは相容れない物らしい
しかし生々しい実装レベルではいまんとこ清濁併せ呑んで実現するし
まあいいや寝るか。ノシ

471:デフォルトの名無しさん
12/04/16 02:46:25.77
多値使うアイデアはイケてたはずなのに、仕上げの文字列との結合やprintとの併用で
ズル呼ばわりされるわ、Rubyの>>377の挙動も再現できなかったしで散々だったしね。

472:デフォルトの名無しさん
12/04/16 02:53:06.66
なぜかC++で挑み続ける俺。
これ以上C++では無理かも。0xだと知らんが。

template< int e, unsigned t >
struct fizzbuzz
{
  int in; std::string out;
  fizzbuzz( int i ):in( i ){ init(); }
  template< int e2, unsigned t2 >
  fizzbuzz( const fizzbuzz< e2, t2 > &r )
    :in( r.in ),out( r.out ){ init(); }
  void init(){ if( in%e ) return;
    unsigned tmp=t; out.append( (char*)&tmp, 4 ); }
  operator const char *(){ return out.c_str(); }
  operator int(){ return in; }
};
typedef fizzbuzz< 3, 'zziF' > fizz;
typedef fizzbuzz< 5, 'zzuB' > buzz;
typedef fizzbuzz< 7, 'zziG' > gizz;

int main()
{
  int     i = (gizz)(buzz)(fizz)1;
  std::string t = (gizz)(buzz)(fizz)15;
  std::string u = (gizz)(buzz)(fizz)105;
  std::string v = gizz((buzz(fizz(105)))); //こうも書けるね
  return 0;
}

473:466
12/04/16 02:54:29.65
>>471
あれはね最初に書いたnewはだめって言われて仕方なくの面はあるのよ

$scalar = 関数(関数

と明示的にscalarで主値だけを受けとるように明示するのがホントは作法なんだ。

Rubyの>>377に関しては読んでなかったから挙動の再現にそもそも着手してないよ。
rubyは文法がかなりカオスになって来ちゃって残念だね

474:466
12/04/16 02:59:22.51
fizzbuzzgizzはいいんだどうでも。
それより前スレのpermutaion perl版はwebなど参照せず一から考えて書いて
オレなりに結構な自信作だったのに
なんの反応もなかったことの方が寂しかったな

475:デフォルトの名無しさん
12/04/16 03:19:21.92
何このスレ

476:デフォルトの名無しさん
12/04/16 06:20:08.75
ruby無双をしたかった奴が、もっとエレガントな解を他言語で出されて、
涙目でdisるスレです

477:デフォルトの名無しさん
12/04/16 06:53:26.91
Rubyと違う解法が出る度に
必死に難癖付けてて笑ったわww

478:デフォルトの名無しさん
12/04/16 08:13:17.85
頭が固くて馬鹿だから
数や文字列に状態持たせる以外の方法が
理解できないんだろう

479:デフォルトの名無しさん
12/04/16 08:32:48.03
頭が固くて馬鹿だから
数や文字列に状態持たせる方法が
許容できないんだろう

480:デフォルトの名無しさん
12/04/16 08:38:53.99
世の中は状態がある世界なのにねw

481:デフォルトの名無しさん
12/04/16 08:50:48.96
じゃあFixnumのインスタンスに特異メソッド定義してみろRuby厨

482:デフォルトの名無しさん
12/04/16 09:44:46.42
元ネタのCLのEQLスペシャライザならそういうことできたよな。

Haskellとかでコンストラクタ無しで1以外の引数をとるとコンパイル時に
型エラーになる関数って定義できたっけ?

483:デフォルトの名無しさん
12/04/16 10:00:08.87
template< int n > void func(){int i="";}
template<> void func<1>(){}
・・・
func<2>();//エラー

484:デフォルトの名無しさん
12/04/16 12:34:04.90
> cat FooTH.hs
{-# LANGUAGE TemplateHaskell #-}
module FooTH where
import Language.Haskell.TH
foo 1 = [| 1 |]
foo _ = error ""

> cat Main.hs
{-# LANGUAGE TemplateHaskell #-}
import FooTH
main = print $(foo 1) -- foo 2 に変えるとコンパイルエラー

485:デフォルトの名無しさん
12/04/16 12:50:08.98
>>474
あれ覚えてるよ、実は感心してた
ていうか、このスレでPerlの評価が結構変わったよ(もちろん高い方へ)

でも、読み易さ優先で書いてあれとは
Perl使いとは分かり合えないな...と思ったけどw

486:デフォルトの名無しさん
12/04/16 20:25:48.62
>>479
許容はしてるだろう
エレガントさから程遠いと言ってるだけで

487:デフォルトの名無しさん
12/04/16 22:19:41.52
俺の基準における
エレガントってやつかw

488:285
12/04/17 00:46:48.85
正直、あの問題は無いと思うよ
問題があれだし書き捨てだからやったが、実際には絶対にやりたくないな

489:デフォルトの名無しさん
12/04/17 00:47:44.00
>>487
FizzBuzzすら書けない口だけ野郎の基準よりマシだろwww
お前はこのスレでは最底辺のカスなんだから敬語使えw

490:デフォルトの名無しさん
12/04/17 00:53:04.36
>>481
ぶっちゃけ>>479のバカが理解できたのが
たまたまRubyのコードだっただけでRuby厨ですらねーと思うぜ
むしろバカにクソコード褒められてRuby可哀想ってなもんだ

491:デフォルトの名無しさん
12/04/17 00:59:54.74
あの問題出したのぶっちゃけPython使いだと思う(陰謀説)

492:466
12/04/17 01:35:17.45
>>491
アレは学部・卒研レベルの課題をここに投げたのかなーと
オレは感じた。(真相はシラネ)
もしかしてオレ様はボクちゃんに利用されたのかなとww

493:デフォルトの名無しさん
12/04/17 10:56:11.26
F#のスレッドローカル(有り体にはグローバル変数)と同様の方法でSqueak Smalltalkの解。
オープンクラスは使わずにブロック(無名関数)で。

| fb fizz buzz gizz |
fb := [:x :cond :str |
   | p n |
   p := Processor activeProcess.
   (x isKindOf: Integer)
      ifTrue: [p instVarNamed: #env put: (n := x). x := '']
      ifFalse: [n := p instVarNamed: #env].
   (cond value: n) ifTrue: [x, str] ifFalse: [x ifEmpty: [n]]].

fizz := [:x | fb value: x value: [:n | n isDivisibleBy: 3] value: 'Fizz' ].
buzz := [:x | fb value: x value: [:n | n isDivisibleBy: 5] value: 'Buzz'].
gizz := [:x | fb value: x value: [:n | n isDivisibleBy: 7] value: 'Gizz'].

self assert: (fizz value: 1) = 1.
self assert: (fizz value: 3) = 'Fizz'.
self assert: (buzz value: (fizz value: 1)) = 1.
self assert: (buzz value: (fizz value: 3)) = 'Fizz'.
self assert: (buzz value: (fizz value: 5)) = 'Buzz'.
self assert: (buzz value: (fizz value: 15)) = 'FizzBuzz'.
self assert: (gizz value: (buzz value: (fizz value: 105))) = 'FizzBuzzGizz'.
self assert: (buzz value: (gizz value: (fizz value: 105))) = 'FizzGizzBuzz'.

494:デフォルトの名無しさん
12/04/17 12:02:41.83
>>493
Pythonも同じ方針のやつ

import threading
fbdata = threading.local()

def fb(x, cnd, msg):
if isinstance(x, int):
fbdata.m = n = x
s = ""
else:
n = fbdata.m
s = x
if cnd(n):
return s + msg
elif s <> "":
return s
else:
return n

def fizz(n): return fb(n, lambda n: n%3==0, "Fizz")
def buzz(n): return fb(n, lambda n: n%5==0, "Buzz")
def gizz(n): return fb(n, lambda n: n%7==0, "Gizz")

assert fizz(1) == 1
assert fizz(3) == "Fizz"
assert buzz(fizz(1)) == 1
assert buzz(fizz(3)) == "Fizz"
assert buzz(fizz(5)) == "Buzz"
assert buzz(fizz(15)) == "FizzBuzz"
assert gizz(buzz(fizz(105))) == "FizzBuzzGizz"
assert buzz(gizz(fizz(105))) == "FizzGizzBuzz"

495:デフォルトの名無しさん
12/04/18 13:10:30.34
っていうか問題どこだよ

496:デフォルトの名無しさん
12/04/18 13:31:40.56
スレタイに惹かれて開いたけどゴミスレだった・・・

497:デフォルトの名無しさん
12/04/19 02:49:08.33
$t = sub { my $f = shift;
           sub { my $x = shift;
                $f->($f->($x)) } };
$rst = $t->($t)->($t)->($t)->(
    sub{ my $x = shift;
            $x + 1 })->(0);

print $rst, "\n";

498:デフォルトの名無しさん
12/04/19 09:02:56.87
同じくRubyも。
ケチがついた、オープンクラス、メソッドチェーン、リフレクションは無しで

require 'test/unit'

def fb(x, cnd, msg)
th = Thread.current
x.kind_of?(Integer) ? (th[:m] = n = x; s = "") : (n = th[:m]; s = x)
cnd[n] ? s + msg : !s.empty? ? s : n
end

def fizz(n); fb(n, proc{ |n| n%3==0 }, "Fizz") end
def buzz(n); fb(n, proc{ |n| n%5==0 }, "Buzz") end
def gizz(n); fb(n, proc{ |n| n%7==0}, "Gizz") end

class FizzBuzzQuizTest < Test::Unit::TestCase
def test_fbq
assert_equal( fizz(1), 1 )
assert_equal( fizz(3), "Fizz" )
assert_equal( buzz(fizz(1)), 1 )
assert_equal( buzz(fizz(3)), "Fizz" )
assert_equal( buzz(fizz(5)), "Buzz" )
assert_equal( buzz(fizz(15)), "FizzBuzz" )
assert_equal( gizz(buzz(fizz(105))), "FizzBuzzGizz" )
assert_equal( buzz(gizz(fizz(105))), "FizzGizzBuzz" )
end
end

499:デフォルトの名無しさん
12/04/19 09:53:30.31
リフレクションやらスレッドローカルやら組み込みクラス汚染やら使った
クソみたいな実装が出てくる出題だったけど
言語比較に役立つ何かは得られましたか?

500:デフォルトの名無しさん
12/04/19 10:07:54.14
あるときは数値またあるときは文字列を返すような関数は
動的型であれ作るもんじゃないという幼稚園児並みの洞察が得られました

501:デフォルトの名無しさん
12/04/19 10:43:06.55
>>499
「数値と文字列の組」と「数値または文字列」の違いが不明瞭だった。
リフレクションや継承で二つのクラスを一組にしたいのか、
それとも一つのクラスを数種類に分けたいのか明示されていなかった。

502:デフォルトの名無しさん
12/04/19 10:53:45.22
どうしてもスレッドローカル変数が必要になったとき
関数的にはどう記述したらいいのかよかったら教えてください。

503:デフォルトの名無しさん
12/04/19 11:37:33.00
そもそもスレッド自体が処理系に依存した、言語パラダイムとは関係ない概念だから、
関数型的にもオブジェクト指向的にも、どう記述したらいいかとか答えようがない。

504:デフォルトの名無しさん
12/04/19 12:23:49.22
Readerモナドでグローバル変数っぽいことをするには
どうすればいいのでしょうか。たとえば、状態をfizzとかbuzzから
(引数として渡すことなしに)参照したり更新したりしたいのです。

505:デフォルトの名無しさん
12/04/19 12:50:34.08
URLリンク(www.haskell.org)
いまんとこHaskellからTLSを使う、「これ」といった定番はないようだ

506:デフォルトの名無しさん
12/04/19 12:58:07.14
個人的に、関数型でスレッドとかハードに近い領域の制御はしたくないな。

507:デフォルトの名無しさん
12/04/19 13:20:53.20
>>504
それは基本的にStateモナドの領域。
Readerモナドの中で、さらにサブルーチン的に他のReaderモナドを呼び出す時に、
一時的に書き換えたように見せかけたい、っていう場合ならばlocal関数が使えるけど。

Readerモナドで更新したいって、読み取り専用変数に書き込みたいって言ってるのと同じ事なのはわかってるよな…?

508:デフォルトの名無しさん
12/04/19 17:54:57.76
Reader
(s -> a) -> (a -> s -> b) -> s -> b
Writer
(a,s) -> (a -> (b,s)) -> (b,s)
State
(s -> (a,s)) -> (a -> s -> (b,s)) -> s -> (b,s)

509:デフォルトの名無しさん
12/04/20 11:54:43.80
>>500
あるときは a
またあるときは m a
m a -> (a -> m b) -> m b

510:デフォルトの名無しさん
12/04/20 17:52:20.76
なんつーか、FizzBuzzしたいんならHQ9F+使えばいんじゃね?


511:デフォルトの名無しさん
12/04/20 22:29:27.34
お題出していい?

512:デフォルトの名無しさん
12/04/20 22:55:07.28
・コンソール上で動く、カード(つーてもただの数字を表示するだけだが)を使ったミニゲーム
・1~9のカードを各4枚ずつ用意、それをシャッフルして「ストック」とする
・ストックから7枚のカードを引く
・引いたカードの中から、プレイヤーは合計が15になるように数枚を選んで捨てる
(選ばせ方はプログラマが考える、ギブアップ手段も用意)
・捨てなかったカードと合わせて再び7枚になるか、もしくはストックが空になるまでストックからカードを引く
・また15になるように捨てる
・引いては捨ててを繰り返し、ストックと手札が共に空になったらおめでとう的な言葉を吐いて終了

513:デフォルトの名無しさん
12/04/20 23:16:37.51
つまらない。

514:デフォルトの名無しさん
12/04/21 01:27:35.30
>>512
Squeak Smalltalk で。

| ui stock player |
ui := UIManager default.
stock := (1 to: 9) gather: [:each | Array new: 4 withAll: each].
stock := stock shuffled asOrderedCollection.
player := (stock removeFirst: 7) asOrderedCollection.
[ | choice |
   [ | input |
      input := ui request: player asSortedArray asString, 'から合計が15になるようにチョイス'.
      choice := input subStrings collect: #asInteger.
      choice ifEmpty: [(ui confirm: 'ギブアップ?')
         ifTrue: [^self] ifFalse: [choice := {nil}]].
      (choice allSatisfy: #isInteger)
         and: [choice sum = 15]
         and: (player includesAllOf: choice)
         and: [choice asSet allSatisfy: [:card | (player occurrencesOf: card) >= (choice occurrencesOf: card)]]
   ] whileFalse.
   player removeAll: choice.
   player addAll: (stock removeFirst: (choice size min: stock size)).
   player notEmpty] whileTrue.
ui inform: 'おめでとう!'

515:デフォルトの名無しさん
12/04/21 02:46:31.71
>>514
なぜこの人は今どきSmalltalkの末裔を使っているのか理由をうかがいたいので
おしえてくださいです

516:デフォルトの名無しさん
12/04/22 01:52:01.88
# Ruby版、指定は半角空白区切り、EOFでギブアップ
class CardNotFoundException < RuntimeError; end
def remove_cards(specs, tableau)
    specs.each do |spec|
        if idx = tableau.find_index{|card| card == spec }
            then tableau.delete_at idx
            else raise CardNotFoundException.new(spec.to_s)
        end
    end
end
stock = ((1..9).to_a * 4).shuffle
tableau = []
until tableau.empty? && stock.empty?
    tableau.push stock.pop until tableau.size >= 7 || stock.empty?
    printf "stock=%d tableau=%p\n? ", stock.size, tableau
    k = gets or exit
    specs = k.chomp.split(' ').map{|s| s == 'giveup' ? exit : s.to_i }
    begin
        remove_cards specs,tableau.dup
        if (total = specs.inject{|result,n| result + n }) == 15
            then remove_cards specs,tableau
            else puts "total(#{total}) not equal to 15"
        end
    rescue CardNotFoundException => e
        puts "not found `#{e}'."
    end
end
puts 'Congraturations !'

517:デフォルトの名無しさん
12/04/22 02:31:25.32
>>514をRubyに翻訳してみた版

stock = ([*1..9]*4).shuffle
player = stock.shift(7)
loop do
  choice = nil
  loop do
    puts player.sort.inspect + "から合計が15になるようにチョイス"
    choice = gets.split(/[, ]/).map(&:to_i)
    choice.delete(0)
    if choice.empty?
      puts "ギブアップ?[Y/n]"
      !(gets=="n\n") ? exit : choice = [0]
    end
    break if choice.all?(&:integer?) and
      choice.reduce(&:+) == 15 and
      choice.uniq.all?{ |card| player.count(card) >= choice.count(card) }
  end
  choice.each{ |e| player.delete_at(player.index(e)) }
  player += stock.shift([choice.size, stock.size].min)
  break if player.empty?
end
puts "おめでとう!"

518:デフォルトの名無しさん
12/04/22 12:27:13.72
Squeakは入れたことあるが(てか今も入ってるけど)何をどうしたらいいのか判らん
>>514 のコードをどこに入力して、どう実行したら動くんだ?

519:デフォルトの名無しさん
12/04/22 17:54:43.65
>>518
1. URLリンク(sourceforge.jp) から Squeak4.2-ja-all-in-one.zip を入手して展開。
2. 同梱 ReadMe-ja.txt などを参考に手元のOSでなんとか起動までこぎつける。無印VMでも新CogVMでもOK。
3. 「ツール」メニューから「ワークスペース」を選択してスクリプトなどのお試し実行用ウインドウを開く。
4. >>514 の | ui stock player | から ui inform: 'おめでとう!' をコピーして 3 のウインドウにペースト。
5. 改めて alt(Macならcmd)+a やマウスドラッグで全選択してから、alt(同cmd)+d で実行。
6. うまく動作すると入力欄がポップアップするので、そこに数字をでスペースなどで区切ってタイプ。
7. 「了解(s)」ボタンクリック(あるいはリターンキー)で入力決定。以降はこれの繰り返し。空決定でギブアップ。

ざっと調べた感じ最新の日本語化版である 4.2ja にこだわらなくても 3.9以降であれば動作するようです。
ただし公式英語版などでは日本語が化けますので適宜英語などに置き換えてからペーストしてください。
日本語版であってもペースト時にエラーがでるようならそのときの対処も同様です。

520:デフォルトの名無しさん
12/04/22 21:05:31.50
// F#で入出力以外の副作用なし
let rec input hands =
    printfn "合計が15になるように捨てるカードをスペース区切りで指定(ギブアップの場合は指定なし)"
    match System.Console.ReadLine() with
    | "" -> None
    | inp ->
        try
            let discardCount = inp.Split([|' '|]) |> Seq.map int |> Seq.countBy id |> Map.ofSeq
            let handCount = hands |> Seq.countBy id |> Map.ofSeq
            if discardCount |> Map.exists (fun n c -> defaultArg (Map.tryFind n handCount) 0 < c)
                || discardCount |> Map.toSeq |> Seq.sumBy ((<||) (*)) |> (<>) 15 then input hands else
            handCount |> Map.map (fun n c -> c - defaultArg (Map.tryFind n discardCount) 0)
            |> Map.toList |> List.collect (fun (n, c) -> List.replicate c n) |> Some
        with _ -> input hands

let rec play hands stocks =
    if (hands, stocks) = ([], []) then printfn "おめでとう!" else
    let cards = stocks |> Seq.truncate (7 - List.length hands) |> Seq.toList
    let nowHands, nextStocks = hands @ cards, (stocks |> Seq.skip cards.Length |> Seq.toList)
    nowHands |> Seq.sort |> Seq.map string |> String.concat " " |> printf "手札 : %s, "
    printfn "山札の残り枚数 : %d" nextStocks.Length
    match input nowHands with Some nextHands -> play nextHands nextStocks | None -> ()

let random = System.Random()
[for i in 1 .. 9 do yield! List.replicate 4 i] |> List.sortBy (fun _ -> random.Next()) |> play []

521:デフォルトの名無しさん
12/04/23 00:28:55.28
>>519
ありがと。何か前に入れたバージョンでやってみたら「[ | input |」の行の左に「Period or right bracket expected ->」とか出たけど、実行の仕方自体は判ったから色々試してみる。

522:デフォルトの名無しさん
12/04/23 00:33:02.59
ああ、インデントを一旦削って入れ直したら動いたわ。thx

523:デフォルトの名無しさん
12/04/23 07:26:59.30
あ、動的にいたスモールトーカーだ。よろしく!

524:デフォルトの名無しさん
12/04/24 12:35:28.99
日本語でおk

525:デフォルトの名無しさん
12/04/25 13:12:07.32
お題:
コンウェイのライフゲームで、
配列の配列(あるいはリストのリスト)で表わされた格子を受け取り
次世代を返す関数lifeを定義せよ。

life([
[0,1,1,1,0],
[0,1,0,0,0],
[0,0,1,0,0],
[0,0,0,0,0],
[0,0,0,0,0]])

#=> [
[0,1,1,0,0],
[0,1,0,1,0],
[0,0,0,0,0],
[0,0,0,0,0],
[0,0,1,0,0]]

また作成した同関数を用いて、500x500のランダムな状態の格子の
500世代目を算出するのにかかった時間(無理なら、算出可能な
世代数とその時間)を計測して示せ。

526:デフォルトの名無しさん
12/04/25 13:54:49.01
くだらん

527:デフォルトの名無しさん
12/04/25 14:03:57.26
Java8でラムダ式が言語仕様に入るようだね
javaもマルチパラダイム化が進むな

OOPLが関数型言語の特徴の一部を取り込む中
スレタイの通り言語比較した場合
「副作用の有無」が一番重要なんじゃないかと思ったけどどうだろう?
機能を取り込むことはあっても無くすことはしないだろうから

副作用の有無が、開発速度や可読性、保守性にどのように影響してくるか・・・

と考えても良いお題は思いつかないんだけどね

528:デフォルトの名無しさん
12/04/25 15:26:58.18
Javaって今でも組み込み型以外は参照型でしか扱えないの?
関数型言語使うようになってから、nullを持たない参照型とか、イミュータブルな値型がいかに重要か思い知った。
しかも、イミュータブルな値型を基本として、nullを持った参照オブジェクト型、nullを持たない参照オブジェクト型って形で扱えないと厳しい。
これは言語仕様として取り込まれていないとどうしようもない。
そういう意味では、C++は結構惜しいところまで行ってたと思う。

529:デフォルトの名無しさん
12/04/25 16:37:33.03
C++にはpure virtual function callというのがあって、仮想関数がnullを持つ。
値型でも仮想関数があったら元も子もない。
仮想関数をやめてswitchを使う覚悟がないと厳しい。
関数型言語のパターンマッチはswitchと同じ方式だ。

530:デフォルトの名無しさん
12/04/25 16:43:26.43
>>528 関数型言語はむしろ全てが参照型とも言えるんだが

531:デフォルトの名無しさん
12/04/25 17:35:29.26
>>525
Squeak Smalltalk (4.2-ja w/CogVM), 1.8GHz Core i7で5分弱。

life := [:ary2d |
   | sum survivs |
   sum := ary2d * 0.
   #(-1 0 1) do: [:dx | #(-1 0 1) do: [:dy |
      sum := sum + ((ary2d collect: [:row | row flipRotated: dx*2]) flipRotated: dy*2)]].
   survivs := #(3 4) collect: [:alive |
      sum collect: [:row | row collect: [:cell | (cell = alive) asBit]]].
   survivs first + (survivs second * ary2d)].

life value: #(
   (0 1 1 1 0)
   (0 1 0 0 0)
   (0 0 1 0 0)
   (0 0 0 0 0)
   (0 0 0 0 0)).

"=> #(
   (0 1 1 0 0)
   (0 1 0 1 0)
   (0 0 0 0 0)
   (0 0 0 0 0)
   (0 0 1 0 0)) "

cells := (1 to: 500) collect: [:row | (1 to: 500) collect: [:cell | #(0 1) atRandom]].
[500 timesRepeat: [cells := life value: cells]] timeToRun "=> 267282(msec) "

532:デフォルトの名無しさん
12/04/25 20:45:17.23
>>531をRubyに翻訳してみた版。1.9だが50世代に4分以上かかってしまう。
翻訳の手間を省くのにArray#*,#+を置き換えちゃったのが足を引っ張ったか?

require "benchmark"

class Array
  def *(x); zip(x.kind_of?(Array)?x:Array.new(size,x)).map{|e|e.reduce(&:*)} end
  def +(x); zip(x.kind_of?(Array)?x:Array.new(size,x)).map{|e|e.reduce(&:+)} end
end

def life(ary2d)
  sum = ary2d * 0
  (-1..1).each{ |dx| (-1..1).each{ |dy|
    sum += ary2d.map{ |row| row.rotate(dx) }.rotate(dy) } }
  survivs = [3,4].map{ |alive| sum.map{ |row| row.map{ |cell| (cell == alive)?1:0 } } }
  survivs.first + (survivs.last * ary2d)
end

p life([
  [0,1,1,1,0],
  [0,1,0,0,0],
  [0,0,1,0,0],
  [0,0,0,0,0],
  [0,0,0,0,0]])

#=> [[0,1,1,0,0],[0,1,0,1,0],[0,0,0,0,0],[0,0,0,0,0],[0,0,1,0,0]]

cells = (1..500).map{ (1..500).map{ [0,1].sample } }
p Benchmark.measure{ 50.times{ cells = life(cells) } }

533:デフォルトの名無しさん
12/04/25 22:15:29.46
1.6GHz Core i5で2分


import qualified Data.Vector.Unboxed as V
import qualified Data.List as L
import System.Random.Mersenne

data Lattice = Lattice! Int Int (V.Vector Int)

(!) (Lattice m n v) (i,j) = v V.! (n * mod i m + mod j n)

next b i j = case (sum xs, b ! (i,j)) of
                  (3, _) -> 1
                  (4, 1) -> 1
                  (_, _) -> 0
  where xs = [b ! ((i+m),(j+n)) | m <- [-1,0,1], n <- [-1,0,1]]

updateBoard board@(Lattice m n v) =
  Lattice m n $! V.fromList [next board i j | i <- [0..m-1], j <- [0..n-1]]

randomBoard rs x y = Lattice x y $ V.fromList $ take (x * y) rs

main = do
  rs <- newMTGen Nothing >>= randoms
  let board = randomBoard (map (`mod` 2) rs) 500 500
  print $ L.foldl' (\x _ -> updateBoard x) board [1..500]

534:533
12/04/25 22:20:37.27
instance Show Lattice where
  show (Lattice m n v) = concat $ snd $ L.mapAccumL (\i x ->
    if i == n-1 then (0, show x ++ "\n") else (i+1, show x)) 0 $ V.toList v

lattice xss = Lattice n m $ V.fromList $ concat xss
  where
    n = length xss
    m = length (concat xss) `div` n


> updateBoard $ lattice
              [[0,1,1,1,0],
               [0,1,0,0,0],
               [0,0,1,0,0],
               [0,0,0,0,0],
               [0,0,0,0,0]]

# 出力
01100
01010
00000
00000
00100

535:デフォルトの名無しさん
12/04/26 20:54:15.37
(_, _)   (`mod` 2)   (\x _ ->


536:デフォルトの名無しさん
12/04/26 20:56:38.97
最近Lispさんを見かけないけどもう廃れちゃったの?

537:デフォルトの名無しさん
12/04/26 21:25:38.01
言語仕様を共通にするというトレンドは終わった
個別の実装は始まってなかった

538:デフォルトの名無しさん
12/04/27 01:17:14.79
Rで
life <- function(ary2d) {
  sum <- rbind(ary2d[ncol(ary2d),], ary2d[-ncol(ary2d),]) + ary2d + rbind(ary2d[-1,], ary2d[1,])
  sum <- cbind(sum[,nrow(sum)], sum[,-nrow(sum)]) + sum + cbind(sum[,-1], sum[,1])

  ifelse(sum == 3 | (ary2d == 1 & sum == 4), 1, 0)
}


539:デフォルトの名無しさん
12/04/27 08:45:31.15
>>536
2chで世間が判った気になり始めたら色々ヤバイな。

540:デフォルトの名無しさん
12/04/27 10:14:19.97
>>538
500x500 500世代で測ったら 1.8GHz Core i7 で 68秒だった。けっこう速いね。

541:デフォルトの名無しさん
12/04/27 11:00:18.10
ライフゲームで関数型とオブジェクト指向の何を比較したいんだろう?

>>525は次世代を返す関数としてるけどオブジェクト指向側は
 lg = new lifegame(500,500);
 for(i=0;i<500;i++)lg.life();
 console(lg);
って感じでいいの?
そうしないと関数型 vs 手続き型みたいなことになるよね

542:デフォルトの名無しさん
12/04/27 11:37:20.76
例えばF#とC#を比較したら関数型言語と手続き型言語の比較になる
本物のOOは言語に依存しない
関数型言語と対立するようなOOは偽物

543:デフォルトの名無しさん
12/04/27 12:00:12.21
>>541
ライフゲームは単純だけどパラダイムの特徴をかろうじて出せるくらいの規模はあるんじゃない?
お題にあるlifeという関数名(メソッド名)にこだわらなくていいと思うよ。
要は小さな例での正常動作と、500x500セル 500世代(必要なら50世代とかに軽減して)
にどのくらいかかるかが示せていればOKかと。

544:デフォルトの名無しさん
12/04/27 12:17:25.49
>>543
規模の大きさは良いと思うけど、
データの破壊的操作ができると有利な御題のほうが
違いが出て良いと思った

Haskellで配列使ったバージョン


import Data.Array

life ary = array ((1,1),(x,y)) [((i,j), f i j) | i <- [1..x], j <- [1..y]]
  where
    (x,y) = snd $ bounds ary
    f i j = let n = sum [ary ! (g x (i+a), g y (j+b)) | a <- [-1,0,1], b <- [-1,0,1]]
            in if n == 3 || (n == 4 && ary ! (i,j) == 1) then 1 else 0
    g x i = if i < 1 then x else if i > x then 1 else i

545:デフォルトの名無しさん
12/04/27 14:36:04.79
javascriptで書いてみた。破壊的操作有りで。
ソースの長さ汚さは勘弁してください。
URLリンク(ideone.com)
※↑は5秒制限のため500回でなく1回だけ

lg.life(500);
console.log("life500:" + (new Date()-st) + " msec");
に書き換えてから
windows版node.js(pen4 2.6GHz)でやったら30秒くらいだった。

>node.exe life.js
0,1,1,1,0
0,1,0,0,0
0,0,1,0,0
0,0,0,0,0
0,0,0,0,0
---------------
0,1,1,0,0
0,1,0,1,0
0,0,0,0,0
0,0,0,0,0
0,0,1,0,0
---------------
create :39 msec
life500:29794 msec

546:デフォルトの名無しさん
12/04/27 20:27:45.31
てきとーにCで書いてみた
500回はさすがに秒数制限に引っかかったけど、50回で0.69秒

URLリンク(ideone.com)

547:デフォルトの名無しさん
12/04/27 22:35:14.09
F# 2.6GHz Core2Duo 500世代で2分57秒

let life (field : int[,]) =
    let height, width = field.GetLength 0, field.GetLength 1
    field |> Array2D.mapi (fun y x c ->
        let s =
            seq { y - 1 .. y + 1 } |> Seq.sumBy (fun y' ->
                seq { x - 1 .. x + 1 } |> Seq.sumBy (fun x' ->
                    field.[(y' + height) % height , (x' + width) % width]))
        match s, field.[y, x] with 4, 1 | 3, _ -> 1 | _ -> 0)

548:デフォルトの名無しさん
12/04/27 22:37:08.83
手続き型言語F#で書くと>>547と同じ環境で500世代9秒

let life (field : int[,]) =
    let height, width = field.GetLength 0, field.GetLength 1
    let result = Array2D.zeroCreate height width
    for y = 0 to height - 1 do
        for x = 0 to width - 1 do
            let mutable s = 0
            for y' = y - 1 to y + 1 do
                for x' = x - 1 to x + 1 do
                    s <- s + field.[(y' + height) % height, (x' + width) % width]
            result.[y, x] <- match s, field.[y, x] with 4, 1 | 3, _ -> 1 | _ -> 0
    result

549:デフォルトの名無しさん
12/04/28 00:03:43.28
OOPならセルごとにオブジェクトで、と思ったが、
仕様が全状態の配列から配列への変換なのね。

550:デフォルトの名無しさん
12/04/28 00:54:50.29
>>549
べつにこだわらなくてもいいでしょ。組みやすいように組めば。
要は小さな例での動作確認出力結果と、
500x500セル 500世代(必要なら50世代とかに軽減して)の計測結果を示せればOK。

551:デフォルトの名無しさん
12/04/28 04:39:34.80
まあ出題者が関数的なアタマなんだろう

552:デフォルトの名無しさん
12/04/28 06:37:42.91
セルごとにオブジェクトとかねぇよww

553:デフォルトの名無しさん
12/04/28 07:45:09.18
問題領域がどこかわかれば何処をオブジェクトにしたら良いか分かるよ

554:デフォルトの名無しさん
12/04/28 09:32:38.01
なかなか面白いじゃないか。
オブジェクト指向で設計されたライフゲーム、頼む。

555:デフォルトの名無しさん
12/04/28 09:44:59.90
この題じゃ>>541くらいにしかならんだろ
オブジェクト指向をどういうもんだと思ってんだよw

556:デフォルトの名無しさん
12/04/28 10:37:13.10
セル毎にオブジェクトか、面白そうだしちょっとやってみるかな

557:デフォルトの名無しさん
12/04/28 10:51:25.73
セル毎にオブジェクトってこんなの?(コードはPython)


class Cell(object):
    def __init__(self, alive):
        self.neighborhood = []
        self.alive = alive
    def evaluate(self):
        s = sum(x.alive for x in self.neighborhood)
        self._alive = 1 if s == 3 or (s == 4 and self.alive == 1) else 0
    def update(self):
        self.alive = self._alive


全部は長いのでこっち
URLリンク(ideone.com)

558:デフォルトの名無しさん
12/04/28 11:05:27.26
8coreのXeonマシンでOpenMP使ってCのコードを並列化したら
500*500の500世代で1秒切ったわw

559:デフォルトの名無しさん
12/04/28 12:11:25.24
>>557
他スレで遊んでる内に作られてしまった…

560:デフォルトの名無しさん
12/04/28 12:13:20.34
>>552
ライフゲームは生物が単純だから変に思えるかもしれないけど、
これがゲームのキャラクターと考えればごく普通の考え方。

ライフゲームはどの生物も同じ能力だけど、セルがオブジェクトなら
実際の生物みたく、オブジェクトごとに能力を変えることだって出来る

というかそういうゲームがあったね。

マルチプレイヤー・ネットワーク・ゲームTerrarium
URLリンク(www.atmarkit.co.jp)
> プレイヤーは各自プログラミングした動物を持ち寄り、フィールド上で動物同士を戦わせる。


561:デフォルトの名無しさん
12/04/28 12:23:40.64
やっぱりオブジェクト指向だと規模が大きくなる。

逆に言えば、規模が大きい場合は
オブジェクト指向が有利ってことか。

562:デフォルトの名無しさん
12/04/28 12:42:19.17
大規模で全貌の把握がしづらいものを
個々人では把握できないままでも比較的扱いやすいのがOOPLだと思ってる

563:デフォルトの名無しさん
12/04/28 12:57:03.02
全体を統一しづらい規模になると言語は一つではなくなる
Objective-C++/CLIのような状態

564:デフォルトの名無しさん
12/04/28 16:19:14.44
>セルがオブジェクトなら
>実際の生物みたく、オブジェクトごとに能力を変えることだって出来る

大抵のOOPLにはマルチメソッドすらないのに、
良くそんな大口たたけるな。

565:デフォルトの名無しさん
12/04/28 16:24:25.86
無いのはマルチメソッドを実現するための言語仕様であって、
マルチメソッド自体は実装できるからね。

566:デフォルトの名無しさん
12/04/28 16:25:24.90
>>564
突然何言い出してんのこの子(´・ω・`)

567:デフォルトの名無しさん
12/04/28 16:28:06.39
ホーミングミサイルの話でボコボコにされたやつだ。
気にすんな

568:デフォルトの名無しさん
12/04/28 18:10:20.59
>>565
関数型言語でも実装できる
パラダイムじゃなく言語間の比較スレなんだから
そんなこと言っても意味ない

569:デフォルトの名無しさん
12/04/28 18:15:28.58
>>561
仮に「OOPだと規模が大きくなる」が真だとしても
そこから「規模が大きいとOOPは有利」は導けない

570:デフォルトの名無しさん
12/04/28 18:53:58.34
静的型付けの割に簡潔に書けて、かつ型チェックも厳しくやってほしい

こういうニーズに関数型言語が応えてるから使ってるだけで、
関数型言語使ってる奴が皆OOを嫌ってるわけでも
設計レベルで使わないわけでもないんよ

争いは不毛だ

571:デフォルトの名無しさん
12/04/28 19:06:33.77
> 静的型付けの割に簡潔に書けて、かつ型チェックも厳しくやってほしい
なんとなくC#を思いだしたけどC#で書く人いないね

572:デフォルトの名無しさん
12/04/28 19:31:55.12
争わなかったらスレの存在意義がないだろ

573:デフォルトの名無しさん
12/04/28 20:25:37.43
>>571
C#のジェネリックってダックタイピングできないんでしょ?簡潔かなぁ。

574:デフォルトの名無しさん
12/04/28 20:41:49.41
>>560
ライフゲームのセルっていう文脈だからねぇよって言ったわけで
ゲームのキャラクターのオブジェクト化まで否定はしてねぇよw

>>564
またホーミングの子www

575:デフォルトの名無しさん
12/04/28 21:39:52.98
>>570
Scalaがそう。

静的言語で、簡潔に書けることを
証明した言語。

576:デフォルトの名無しさん
12/04/28 21:45:24.53
>>575
このスレでまだ一回もScala出て来てないぞ
ライフゲームで良いからコードで証明してみてくれ

577:デフォルトの名無しさん
12/04/28 23:03:24.87
「Scalaは簡潔に書けると証明した」=>「じゃあチョット書いてみて」=> 逃亡


どんなコントだよwww

578:デフォルトの名無しさん
12/04/28 23:11:10.96
ん? Scala知らないの?

579:デフォルトの名無しさん
12/04/28 23:31:57.42
Scala待ちの間にw、Squeak Smalltalkでセルがオブジェクト版。(要クラスブラウザ)
細かい違いを無視すれば Python の >>557 とほぼ同じ方針。

Object subclass: #Cell
   instanceVariableNames: 'neighbors next'
Cell >> setBit: int
   neighbors := OrderedCollection with: int
Cell >> collectNeighborsAt: pos in: array2D
   neighbors addAll: (#(-1 0 1) gather: [:dx | #(-1 0 1) collect: [:dy |
      (array2D atWrap: (pos y + dy)) atWrap: (pos x + dx)]]); remove: self
Cell >> calcNext
   next := (neighbors inject: 0 into: [:sum :neigh | sum + neigh value])
      caseOf: {[3]->[1]. [4]->[self value]} otherwise: [0]
Cell >> update
   neighbors at: 1 put: next
Cell >> value
   ^neighbors first
Cell >> printOn: stream
   self value printOn: stream
Cell class >> newWith: bitInt
   ^self new setBit: bitInt; yourself
Cell class >> newLatticeFrom: array2D
   | lattice |
   lattice := array2D collect: [:row | row collect: [:bit | Cell newWith: bit]].
   ^lattice doWithIndex: [:row :y | row doWithIndex: [:cell :x |
      cell collectNeighborsAt: x@y in: lattice]]; yourself
Cell class >> updateLattice: array2D
   ^array2D do: [:row | row do: #calcNext]; do: [:row | row do: #update]

| lattice |
lattice := Cell newLatticeFrom: {{0. 1. 1. 1. 0}. {0. 1. 0. 0. 0}. {0. 0. 1. 0. 0}. {0. 0. 0. 0. 0}. {0. 0. 0. 0. 0}}.
Cell updateLattice: lattice. "=> {{0. 1. 1. 0. 0}. {0. 1. 0. 1. 0}. {0. 0. 0. 0. 0}. {0. 0. 0. 0. 0}. {0. 0. 1. 0. 0}} "

580:デフォルトの名無しさん
12/04/29 00:22:22.02
純粋な関数型言語って、参照するたびに値が変化する変数みたいなのは作れるの?
たとえば乱数とか、参照した時点の現在時刻を値として持ってる変数とか

581:デフォルトの名無しさん
12/04/29 00:31:18.37
>557をscalaでベタ移植してみた。

case class Cell(var alive:Int) {
 var neighborhood = List[Cell]()
 var alive_ = 0
 def evaluate() {
  val s = neighborhood.map(_.alive).sum
  alive_ = if(s == 3 || s == 4 && alive == 1) 1 else 0
 }
 def update() { alive = alive_ }
}
case class Board(val lattice:List[List[Int]]) {
 val cells = lattice.map(_.map(x => Cell(x)))
 val m = lattice.size; val n = lattice(0).size
 for(i <- 0 until m; j <- 0 until n; k <- -1 to 1; l <- -1 to 1)
  cells(i)(j).neighborhood ::= cells((i+k+m)%m)((j+l+n)%n)
 def life() {
  cells.foreach(_.foreach(_.evaluate))
  cells.foreach(_.foreach(_.update))
 }
 override def toString() = {
  cells.map(_.map(_.alive.toString).reduce(_ + "," + _)).reduce(_ + "\n" + _)
 }
}
val board = Board(List(List(0,1,1,1,0),List(0,1,0,0,0),List(0,0,1,0,0),List(0,0,0,0,0),List(0,0,0,0,0)))
board.life
print(board)

scalaの機能を余り活用できていない感じ。

582:デフォルトの名無しさん
12/04/29 01:14:20.15
これで静的型付け言語なんだぜ。

val msg = if (true) "true dayo" else "false dayo"

583:デフォルトの名無しさん
12/04/29 01:27:13.41
せっかくなのですべてのセルが並行に動くように>581を修正

case class Cell(var alive:Int) extends Actor {
 var neighborhood = List[Cell]()
 def act() = {
  neighborhood.foreach(_ ! alive)
  var count = 0; var s = 0
  loopWhile(count < neighborhood.size) {
   receive { case i:Int => s += i; count += 1 }
  } andThen { alive = if(s == 3 || s == 4 && alive == 1) 1 else 0 }
 }
}
case class Board(val lattice:List[List[Int]]) {
 val cells = lattice.map(_.map(x => Cell(x)))
 val m = lattice.size; val n = lattice(0).size
 for(i <- 0 until m; j <- 0 until n; k <- -1 to 1; l <- -1 to 1)
  cells(i)(j).neighborhood ::= cells((i+k+m)%m)((j+l+n)%n)
 def life() {
  cells.foreach(_.foreach(_.start))
 }
 override def toString() = cells.map(_.map(_.alive.toString).reduce(_ + "," + _)).reduce(_ + "\n" + _)
}
val board = Board(List(List(0,1,1,1,0),List(0,1,0,0,0),List(0,0,1,0,0),List(0,0,0,0,0),List(0,0,0,0,0)))
board.life
print(board)

evaluate/updateの分割が不要になったので少し短くなったか

584:デフォルトの名無しさん
12/04/29 01:30:58.02
これで静的型付け言語なのか。
本当に短いコードは動的型付け言語だけの特権じゃないことを
証明してしまったな。

585:デフォルトの名無しさん
12/04/29 02:11:32.74
ただ静的型にしては遅いよね。
500x500 500世代で動的な >>579 が 112秒なのに、>>581 は 196秒。

586:デフォルトの名無しさん
12/04/29 02:18:22.73
>>585
それ事前コンパイルしてないだろ?

587:デフォルトの名無しさん
12/04/29 02:35:44.97
>>583
これって一回のlifeのコール後、
すべてのセルがアップデートを終えるのをどこで待ち合わせているの?

588:デフォルトの名無しさん
12/04/29 06:27:13.54
>>582
そんなんで感動できるとか何時の時代の人?

OCaml : let msg = if true then "true" else "false"
Haskell : let msg = if True then "true" else "false"

589:デフォルトの名無しさん
12/04/29 06:30:26.82
どうせ、RubyとかLLばっかり使ってる人だろw

590:デフォルトの名無しさん
12/04/29 07:52:20.17
C++,C#にも導入されたね
C++11 : auto msg = true ? "true dayo" : "false dayo";
C#(3.0) : var msg = true ? "true dayo" : "false dayo";

591:デフォルトの名無しさん
12/04/29 08:14:29.69
最近どんどん動的型付け言語の
メリットがなくなっていくね。

592:デフォルトの名無しさん
12/04/29 08:47:25.44
>>590
…それでmsgの型を推論しろってか。

593:デフォルトの名無しさん
12/04/29 09:24:13.53
>>591
この戦いが終わったら全ての武器のメリットがなくなるんだ

594:デフォルトの名無しさん
12/04/29 09:42:55.39
機械語のメリットがなくなってゆくね、とか言ってる奴の同類だよなぁw

595:デフォルトの名無しさん
12/04/29 09:43:05.44
でも静的型はコンパイルが必要でREPLももっさり、型推論も万能じゃない
スクリプト言語はこれからも残るよ

596:デフォルトの名無しさん
12/04/29 10:59:45.94
trueって名前の変数を作って、遅延評価によってmsgを参照したときの変数trueの値によりmsgの値も変わるってことでいいんかの
変数trueに再代入できたりしないとあんま意味なくね?
いや違ってたらすまんが

597:デフォルトの名無しさん
12/04/29 11:11:11.60
>>590は型推論の話じゃないの?
"true dayo"も"false dayo"も文字列リテラルなので
三項演算の条件のtrue/falseを問うことなくmsgの型を文字列と確定できる

598:デフォルトの名無しさん
12/04/29 11:27:23.87
>>597
ああなんだそういうことか、勘違いしてたわ

599:デフォルトの名無しさん
12/04/29 11:55:08.69
変数に互換性がない別の型の値を
再代入できる言語はクソです。

600:デフォルトの名無しさん
12/04/29 12:10:48.87
>>586
Scalaって事前(?)にコンパイルする以外になんか実行方法あったっけ?

601:デフォルトの名無しさん
12/04/29 12:18:53.17
>>600

>>581はコンパイルしたらエラーがでます。

602:デフォルトの名無しさん
12/04/29 12:21:46.03
コンパイルしない場合は、そのまま動きます。

603:デフォルトの名無しさん
12/04/29 12:31:37.65
>581はscalaスクリプトだから、コンパイルする場合は
-Xscript XXX オプションをつける必要があるかと

604:デフォルトの名無しさん
12/04/29 12:42:00.90
動くね

$ time scala Lifegame.scala
0,1,1,0,0
0,1,0,1,0
0,0,0,0,0
0,0,0,0,0
0,0,1,0,0
scala Lifegame.scala 1.44s user 0.09s system 4% cpu 37.965 total
AMD MV-40 1.6GHz シングルコア

605:デフォルトの名無しさん
12/04/29 12:42:30.36
>>599
それで、代入を禁止するのと共用体を禁止するのは、どっちが良いんですか

606:デフォルトの名無しさん
12/04/29 12:48:02.58
スクリプト実行
time scala LifeGame.scala
0,1,1,0,0
0,1,0,1,0
0,0,0,0,0
0,0,0,0,0
0,0,1,0,0
real 0m1.819s
user 0m0.704s
sys 0m0.104s

コンパイル実行
time scala LifeGame
0,1,1,0,0
0,1,0,1,0
0,0,0,0,0
0,0,0,0,0
0,0,1,0,0
real 0m0.585s
user 0m0.528s
sys 0m0.072s

コンパイル時間の分、スクリプト実行だと起動に時間がかかるね

607:デフォルトの名無しさん
12/04/29 12:48:20.97
>>605
両方いいです。

608:デフォルトの名無しさん
12/04/29 12:51:30.57
>>597
よく見れ。
msgにtrueを代入してる。

609:デフォルトの名無しさん
12/04/29 12:53:31.56
>>608
どのtrueを代入してるんですか?

全文を引用して、該当のtrueを【】でくくって下さい。

610:デフォルトの名無しさん
12/04/29 13:04:26.07
>>601
コンパイル通らないのでAppにして通したんだけどこれでも遅いままなのかな?

object LifeCell extends App {
val board = Board(List(List(0,1,1,1,0),List(0,1,0,0,0),List(0,0,1,0,0),List(0,0,0,0,0),List(0,0,0,0,0)))
board.life
println(board)
val rand = new Random()
val b500 = Board(List.fill(500, 500){rand nextInt 2})
val s = new Date().getTime
for (i <- 1 to 500) b500.life
println(new Date().getTime - s)
}

>>603
あ、Scalaスクリプトなんてモードがあるんですね。
実行オプションでそんなに差が出るものなんですか?

611:デフォルトの名無しさん
12/04/29 13:31:36.87
Javaの実行環境に詳しくないとまともにベンチとれないんじゃないかと思う

>>608
$ cat hello.cs
class Program {
public static void Main() {
var hoge = true ? "*true*" : "*false*";
System.Console.WriteLine(hoge); } }
$ mono hello.exe
*true*

612:デフォルトの名無しさん
12/04/29 13:56:15.31
>>608
お前が良く見た方がいい

613:デフォルトの名無しさん
12/04/29 14:10:28.74
括弧を省略する言語は危険
式と文を区別しない言語も危険

614:デフォルトの名無しさん
12/04/29 14:12:28.08
>>613
蛇の国からようこそおこしやす

615:デフォルトの名無しさん
12/04/29 14:22:29.08
Lisp系から見るとHaskellも括弧省略言語だな

616:デフォルトの名無しさん
12/04/29 19:36:04.13
λ式に比べたらLispだって

617:デフォルトの名無しさん
12/04/30 00:25:42.19
>>616
Lispの関数は
apply = foldl ($)
(((f x) y) z) == (apply f) [x, y, z]
省略ではなく、式を変形している
(x, y, zの型が異なる場合、Haskellは上の式が間違っていると主張する)

618:デフォルトの名無しさん
12/04/30 01:24:53.48
>610
core i5で90s程度だね。
ちなみに
 def life() {
  cells.foreach(_.foreach(_.evaluate))
  cells.foreach(_.foreach(_.update))
 }

 def life() {
  cells.par.foreach(_.foreach(_.evaluate))
  cells.par.foreach(_.foreach(_.update))
 }
にして並列化すると30s。
まだまだ遅いけど。

619:デフォルトの名無しさん
12/04/30 01:28:51.62
>>587
遅くなって悪い。確かに待ち合わせが抜けてるね。
BoardもActorをextendsしてlifeを以下のactに替えればよさそう。
 def act() {
  cells.foreach(_.foreach((c:Actor) => {link(c); c.start}))
  var count = 0
  loopWhile(count < m * n) { receive { case _ => count += 1 } } andThen { print(this) }
}

620:デフォルトの名無しさん
12/04/30 01:42:08.34
やっぱり手続き型のC言語が
こういうのは一番早いね。

621:デフォルトの名無しさん
12/04/30 06:36:40.19
つまりCの関数を簡単に呼べる言語が優秀

622:デフォルトの名無しさん
12/04/30 08:02:32.77
なんだ。Rubyが最強ってことか。

623:デフォルトの名無しさん
12/04/30 09:21:02.55
>>546のCの関数を呼び出してみた


from __future__ import print_function
from ctypes import *

clife = cdll.LoadLibrary('liblife.so')
clife.life.argtypes = [POINTER(POINTER(c_int)), POINTER(POINTER(c_int)), c_int, c_int]

x = [[0,1,1,1,0], [0,1,0,0,0], [0,0,1,0,0], [0,0,0,0,0], [0,0,0,0,0]]
a, b = (POINTER(c_int) * 5)(), (POINTER(c_int) * 5)()
for i in xrange(5):
    a[i], b[i] = (c_int * 5)(*x[i]), (c_int * 5)()
clife.life(a, b, 5, 5)
print('\n'.join(''.join(str(b[i][j]) for j in xrange(5)) for i in xrange(5)))

624:デフォルトの名無しさん
12/04/30 15:16:50.31
Haskell(GHC)からC関数を使用


import Foreign.Marshal (newArray, mallocArray, peekArray, free)
import Foreign.C.Types (CInt)
import Foreign.Ptr (Ptr, plusPtr)
import Foreign.Storable (sizeOf, peek)
import Data.List (unfoldr)

foreign import ccall "life" cLife ::
    Ptr (Ptr CInt) -> Ptr (Ptr CInt) -> CInt -> CInt -> IO ()

main = do
  x' <- newArray $ concat xss :: IO (Ptr (CInt))
  y' <- mallocArray (m * n)
  x <- f x' =<< peek x'
  y <- f y' =<< peek y'
  cLife x y (fromIntegral m) (fromIntegral n)
  z <- peekArray (m * n) y'
  mapM_ free [x, y]
  mapM_ free [x',y']
  print $ unfoldr (\xs -> if null xs then Nothing else Just $ splitAt n xs) z
  where
    xss = [[0,1,1,1,0], [0,1,0,0,0], [0,0,1,0,0], [0,0,0,0,0], [0,0,0,0,0]]
    m = length xss
    n = length (concat xss) `div` m
    f p h = newArray [plusPtr p (sizeOf h * i * n) | i <- [0..m-1]]

625:デフォルトの名無しさん
12/04/30 20:00:22.80
速度が必要な極一部の処理だけ
速い言語(C/C++/Java)で書けば良いのに
クソ遅い言語で速度競っててワロタwww

626:デフォルトの名無しさん
12/04/30 20:14:25.98
なんだJava厨か

627:デフォルトの名無しさん
12/04/30 20:25:46.03
Ruby「実行速度とかそんなの求めてませんから(キリッ」

628:デフォルトの名無しさん
12/04/30 21:11:28.94
>>546のコードをJavaにベタ移植したんですが
C言語に比べて物凄く遅いです(6.5倍遅い)
(出力が遅すぎるので、そこをコメントアウトしてもまだ遅いです)

URLリンク(ideone.com)

どうやったら速くなりますか?

629:デフォルトの名無しさん
12/04/30 21:27:32.39
すいません正しく移植したら速くなりました
URLリンク(ideone.com)

630:デフォルトの名無しさん
12/05/01 03:28:55.35
関数型言語で書くとどうしてもボトムアップになる,
そこが問題,
小さい処理ならそれでいいが,大きなシステムだとはなしにならん

631:デフォルトの名無しさん
12/05/01 03:59:53.53
関数型言語はトップダウンでもボトムアップでも組む事が出来る
出来ないのはそいつが未熟なだけ

632:デフォルトの名無しさん
12/05/01 04:44:27.14
>>630
自分は逆に関数型言語でトップダウンだが・・・
入れ子になった関数を変更するときぐらいだな。ボトムアップな感じになるのは


633:デフォルトの名無しさん
12/05/01 05:04:37.25
マクロな関数(処理)から書き始め、マクロな関数から呼ばれる
ミクロな関数は入出力の型だけ決めて実装は後回し

なんでこんな簡単なことが>>630には出来ないの?

634:デフォルトの名無しさん
12/05/01 07:57:45.80
トップダウンはどうしても車輪の再発明になる
再利用はどうしてもボトムアップになる

635:デフォルトの名無しさん
12/05/01 09:19:19.80
え?

636: ◆QZaw55cn4c
12/05/01 12:12:45.49
>>634
実感として、トップダウンとボトムアップの出会うところでうんうんうなっています。

637:デフォルトの名無しさん
12/05/01 15:17:57.73
>>634
ボディを違う色で塗って「ニューモデル」っていうだけだろ

638:デフォルトの名無しさん
12/05/01 19:35:01.49
Excel内臓の関数型言語の普及率はすげぇよな。
窓際に座ってる禿ですら操作できるんだからなぁ。
URLリンク(research.microsoft.com)

639:デフォルトの名無しさん
12/05/01 19:48:21.14
simonpj先生の勤務先都合仕事だからだまされないで!

640:デフォルトの名無しさん
12/05/01 19:53:04.34
騙されるも何も、内容は事実じゃん。

641:デフォルトの名無しさん
12/05/01 19:57:17.64
スプレッドシート猿によるアホな決定というリスクマネジメントのための学会?

642:デフォルトの名無しさん
12/05/01 20:11:03.69
現実には使えないExcelの拡張の話だけどなw

643:デフォルトの名無しさん
12/05/01 20:20:54.13
拡張せずとも、普通に計算するだけで関数型だろ?
何言ってんだ?

644:デフォルトの名無しさん
12/05/01 20:54:33.43
A1=3
A2=A1-32
A3=A2*5/9

これは静的単一代入 (SSA) です。
SSAは関数型に入りますか?

645:デフォルトの名無しさん
12/05/01 20:59:05.32
y = x + 5 は一次関数。あとは説明要らんよな。

646:デフォルトの名無しさん
12/05/01 21:02:58.15
そもそも、型に入るとか入らないとかいう型の理論が要らない

647:デフォルトの名無しさん
12/05/01 21:47:34.44
型がないと、実行時にしかメソッド名の解決ができない。
これは開発工数が伸びる原因になる。

648:デフォルトの名無しさん
12/05/01 21:56:43.18
なんという緻密な分析

649:デフォルトの名無しさん
12/05/01 22:03:59.52
関数"型"の話してんだろコミュ障

650:デフォルトの名無しさん
12/05/01 22:36:11.12
>>649
だから、型ですよね?

651:デフォルトの名無しさん
12/05/01 22:36:32.17
型だよ型。

652:デフォルトの名無しさん
12/05/01 22:37:00.05
型の話しようぜ。

653:uy
12/05/02 01:30:41.35
>>67
class Array
  def my_permu
    return [self] if size < 1
    inject [] do |r , n|
      reject{|x| x == n }
      .my_permu.inject r do |r,ary|
        r << [n] + ary
      end
    end
  end
end
p (1..3).to_a.my_permu

654:デフォルトの名無しさん
12/05/02 03:53:50.68
ぶっちゃけ関数型もオブジェクト指向もどうでも良くて
自分が使ってる言語以外をdisりたいだけだよね

655:デフォルトの名無しさん
12/05/02 11:28:46.31
>>653
まだpermutationやってんのかよ、こんなもんがそんな面白いか?

perm [] = [[]]
perm xs = [x:y | x <- xs, y <- perm $ filter (/=x) xs]

main = print $ perm [1,2,3]

656:デフォルトの名無しさん
12/05/02 11:34:39.78
こっちは要素の重複を取り除かないバージョン

import Data.List
perm' [] = [[]]
perm' xs = [x:y | x <- xs, y <- perm $ delete x xs]

657:uy
12/05/02 13:23:15.71
>>655
Rubyのpermutationって誰も知らないのか話題にならないから俺が最初に2chにコード投下したやつじゃん(半年前くらいに)
67の冗長ゴミカスRubyソースコードを添削しただけだよ

658:デフォルトの名無しさん
12/05/02 13:33:49.06
へえー、これ良いね。

659:デフォルトの名無しさん
12/05/02 15:29:43.37
>>658
いやHaskellでもRubyでも標準添付や組み込みのライブラリに入ってますし…

660:デフォルトの名無しさん
12/05/03 10:07:46.90
>>655
要素の重複を取り除くところでバグるかもしれない点は面白い

661:デフォルトの名無しさん
12/05/03 14:24:19.11
>>655 を Squeak Smalltalk で書いてみた。バグもそのまま。

perm := [:xs |
   xs ifEmpty: [#(())] ifNotEmpty: [
      xs gather: [:x | (perm value: (xs copyWithout: x)) collect: [:ys | {x}, ys]]]].

perm value: #(1 2 3) "=> #((1 2 3) (1 3 2) (2 1 3) (2 3 1) (3 1 2) (3 2 1)) "

662:デフォルトの名無しさん
12/05/03 20:11:32.07
>>653 も書いてみた。これも重複要素があるとバグる。

SequenceableCollection >> perm
   self size < 1 ifTrue: [^Array with: self].
   ^self inject: #() into: [:r1 :n |
      (self reject: [:x | x = n]) perm inject: r1 into: [:r2 :ary |
         r2 copyWith: (ary copyWithFirst: n)]]

#(1 2 3) perm "=> #((1 2 3) (1 3 2) (2 1 3) (2 3 1) (3 1 2) (3 2 1)) "

ちなみに、Squeak Smalltalkで組み込みのpermutation相当を見たらこんなふうに
破壊的操作による実装だった。

class Array
  def perm_each(&block)
    clone.perm_start_at(0, &block)
  end

  def perm_start_at(n, &block)
    return if n > size-1
    return block.call(self) if n == size-1
    (n..size-1).each do |i|
      swap!(n, i)
      perm_start_at(n+1, &block)
      swap!(n, i)
    end
  end

  def swap!(a, b); self[a], self[b] = self[b], self[a] end
end

663:デフォルトの名無しさん
12/05/04 12:04:28.46
F#で遅延評価

let bind m f = seq {for x in m do yield! (f x)}
let ret x = Seq.singleton x
let rec perm xs =
  if Seq.isEmpty xs then ret Seq.empty else
    bind (seq {0 .. (Seq.length xs - 1)}) (fun n ->
      bind (perm (Seq.append (Seq.take n xs) (Seq.skip (n+1) xs))) (fun ys ->
        ret (seq {yield (Seq.nth n xs); yield! ys})))

664:デフォルトの名無しさん
12/05/05 00:05:09.38
 URLリンク(metalab.at)
こんなひとおる?

665:デフォルトの名無しさん
12/05/06 08:01:00.40
未だに関数型言語の機能が欲しいと思ったことがない。
俺みたいな奴は案外多いんじゃないかね。
そんなことよりトランザクショナルメモリはよ。

666:デフォルトの名無しさん
12/05/06 09:25:35.24
欲しいと思う機能はそれほど多くない
だが変な機能をゴリ押しされるとそれに対抗するものが欲しくなる
ゴリ押しを断るために、先約があるとかいって他のを抜擢するみたいな話は案外多い

667:デフォルトの名無しさん
12/05/06 11:09:05.44
うむ。関数型言語というより
コレクションライブラリがあれば
十分だったりするw

Guavaおすすめ

668:デフォルトの名無しさん
12/05/06 12:23:52.01
ム板の関数型言語派の大半は「関数型言語派」ではなく「型推論派」だろ

669:デフォルトの名無しさん
12/05/06 12:33:51.12
スレタイが無知だな。

手続型 vs 関数型
構造化設計 vs オブジェクト指向設計

670:デフォルトの名無しさん
12/05/06 12:34:57.95
>666
メタプログラミングなんてどう?
LISPのように構文を犠牲にしないMPといえば、OO系が主流だろう。

671:デフォルトの名無しさん
12/05/06 12:59:41.15
コレクションにもpush型とpull型があって
push型は一昔前のOO
pull型は遅延評価できるので関数型に近い印象がある

最近はpull型も普及したので、まだ売れ残っている型推論の方が関数型らしく見える

メタプログラミングは、共通のVMまたはC言語の上に好きな言語を乗せるのが主流

672:デフォルトの名無しさん
12/05/06 13:07:46.75
メタオブジェクトプロトコルみたいな話は最近どうなったのか

673:デフォルトの名無しさん
12/05/06 16:21:50.38
>>671
一昔前がよくわからないのでpull型とpush型の違いがよくわからんです

674:デフォルトの名無しさん
12/05/06 17:41:19.49
>>673
getterを呼び出したり成功か失敗か調べたりするのがpull型
getter反対派はpush型

675:デフォルトの名無しさん
12/05/06 19:43:30.18
言語はなんでもいいので具体例をプリーズ。

676:デフォルトの名無しさん
12/05/06 20:31:27.12
pushとかpullなんて名前は知らないけどこんな感じなんじゃね?

サンプルはJava。上がきっとpushで下がpull

URLリンク(www.akirakoyasu.net)
List<B> blist = new ArrayList<B>(alist.size());
for (A a : alist) {
 blist.add(new B(a));
}

Guavaを使う場合は次のように書きます。
List<B> blist = Lists.transform(alist, new Function<A, B>(){
 @Override
 public B apply(A a) {
  return new B(a);
 }
});

677:デフォルトの名無しさん
12/05/06 20:34:08.65
いまさらだけど、>>671
pullとpushの言葉の使い方逆じゃね?

678:デフォルトの名無しさん
12/05/06 20:43:49.33
>>677
放置したほうがいい人だと思うがどうか?

"Push-Pull Functional Reactive Programming"風に、
pull: demand driven
push: data driven
ってことでいいかと。

679:デフォルトの名無しさん
12/05/06 20:45:09.00
言葉のままに捉えればよいんじゃない?

pullは引く。
result = hoge( piyo( huga() ) );

pushは押す。
huga( result );
piyo( result );
hoge( result );

680:デフォルトの名無しさん
12/05/06 20:59:16.39
>>678
遅延評価はdemand drivenだから、671は合ってるだろ

681:デフォルトの名無しさん
12/05/06 21:05:42.54
一箇所だけ取り上げてそんな事言われても困りますよ。

682:デフォルトの名無しさん
12/05/06 21:16:14.00
>>677は0箇所ですよ
0箇所よりも1箇所の方がいいんじゃないか

683:デフォルトの名無しさん
12/05/06 21:18:45.89
pullとかpushって>>671が作った言葉だろ?

手続きタイプと、コールバックタイプとかでいいんじゃね?

684:デフォルトの名無しさん
12/05/06 21:23:25.41
なんだ、オレオレ用語かよ

685:デフォルトの名無しさん
12/05/06 21:44:18.93
>>682
まあそりゃそうだねw

push/pullは、上に上げたようにFRPでも取り上げられてるし、
他にはWebアプリフレームワークとかXML系APIとか、
いろいろなところでAPIデザインの選択肢として語られてる。
大げさに騒ぐような概念じゃないけど。


次ページ
最新レス表示
レスジャンプ
類似スレ一覧
スレッドの検索
話題のニュース
おまかせリスト
オプション
しおりを挟む
スレッドに書込
スレッドの一覧
暇つぶし2ch