1 名前:営利利用に関するLR審議中@詳細は自治スレへ mailto:sage [2012/04/07(土) 21:26:47.61 ] 一般的には、オブジェクト指向型言語が優勢でが 一部には関数型言語を崇拝している人もいます どちらが上なのか、この際はっきりさせましょう 前スレ toro.2ch.net/test/read.cgi/tech/1331328955/
520 名前:デフォルトの名無しさん mailto:sage [2012/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 名前:デフォルトの名無しさん mailto:sage [2012/04/23(月) 00:28:55.28 ] >>519 ありがと。何か前に入れたバージョンでやってみたら「[ | input |」の行の左に「Period or right bracket expected ->」とか出たけど、実行の仕方自体は判ったから色々試してみる。
522 名前:デフォルトの名無しさん mailto:sage [2012/04/23(月) 00:33:02.59 ] ああ、インデントを一旦削って入れ直したら動いたわ。thx
523 名前:デフォルトの名無しさん mailto:sage [2012/04/23(月) 07:26:59.30 ] あ、動的にいたスモールトーカーだ。よろしく!
524 名前:デフォルトの名無しさん mailto:sage [2012/04/24(火) 12:35:28.99 ] 日本語でおk
525 名前:デフォルトの名無しさん mailto:sage [2012/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 名前:デフォルトの名無しさん mailto:sage [2012/04/25(水) 13:54:49.01 ] くだらん
527 名前:デフォルトの名無しさん mailto:sage [2012/04/25(水) 14:03:57.26 ] Java8でラムダ式が言語仕様に入るようだね javaもマルチパラダイム化が進むな OOPLが関数型言語の特徴の一部を取り込む中 スレタイの通り言語比較した場合 「副作用の有無」が一番重要なんじゃないかと思ったけどどうだろう? 機能を取り込むことはあっても無くすことはしないだろうから 副作用の有無が、開発速度や可読性、保守性にどのように影響してくるか・・・ と考えても良いお題は思いつかないんだけどね
528 名前:デフォルトの名無しさん mailto:sage [2012/04/25(水) 15:26:58.18 ] Javaって今でも組み込み型以外は参照型でしか扱えないの? 関数型言語使うようになってから、nullを持たない参照型とか、イミュータブルな値型がいかに重要か思い知った。 しかも、イミュータブルな値型を基本として、nullを持った参照オブジェクト型、nullを持たない参照オブジェクト型って形で扱えないと厳しい。 これは言語仕様として取り込まれていないとどうしようもない。 そういう意味では、C++は結構惜しいところまで行ってたと思う。
529 名前:デフォルトの名無しさん mailto:sage [2012/04/25(水) 16:37:33.03 ] C++にはpure virtual function callというのがあって、仮想関数がnullを持つ。 値型でも仮想関数があったら元も子もない。 仮想関数をやめてswitchを使う覚悟がないと厳しい。 関数型言語のパターンマッチはswitchと同じ方式だ。
530 名前:デフォルトの名無しさん mailto:sage [2012/04/25(水) 16:43:26.43 ] >>528 関数型言語はむしろ全てが参照型とも言えるんだが
531 名前:デフォルトの名無しさん mailto:sage [2012/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 名前:デフォルトの名無しさん mailto:sage [2012/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 名前:デフォルトの名無しさん mailto:sage [2012/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 mailto:sage [2012/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 名前:デフォルトの名無しさん mailto:sage [2012/04/26(木) 20:54:15.37 ] (_, _) (`mod` 2) (\x _ ->
536 名前:デフォルトの名無しさん mailto:sage [2012/04/26(木) 20:56:38.97 ] 最近Lispさんを見かけないけどもう廃れちゃったの?
537 名前:デフォルトの名無しさん mailto:sage [2012/04/26(木) 21:25:38.01 ] 言語仕様を共通にするというトレンドは終わった 個別の実装は始まってなかった
538 名前:デフォルトの名無しさん mailto:sage [2012/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 名前:デフォルトの名無しさん mailto:sage [2012/04/27(金) 08:45:31.15 ] >>536 2chで世間が判った気になり始めたら色々ヤバイな。
540 名前:デフォルトの名無しさん mailto:sage [2012/04/27(金) 10:14:19.97 ] >>538 500x500 500世代で測ったら 1.8GHz Core i7 で 68秒だった。けっこう速いね。
541 名前:デフォルトの名無しさん mailto:sage [2012/04/27(金) 11:00:18.10 ] ライフゲームで関数型とオブジェクト指向の何を比較したいんだろう? >>525 は次世代を返す関数としてるけどオブジェクト指向側は lg = new lifegame(500,500); for(i=0;i<500;i++)lg.life(); console(lg); って感じでいいの? そうしないと関数型 vs 手続き型みたいなことになるよね
542 名前:デフォルトの名無しさん mailto:sage [2012/04/27(金) 11:37:20.76 ] 例えばF#とC#を比較したら関数型言語と手続き型言語の比較になる 本物のOOは言語に依存しない 関数型言語と対立するようなOOは偽物
543 名前:デフォルトの名無しさん mailto:sage [2012/04/27(金) 12:00:12.21 ] >>541 ライフゲームは単純だけどパラダイムの特徴をかろうじて出せるくらいの規模はあるんじゃない? お題にあるlifeという関数名(メソッド名)にこだわらなくていいと思うよ。 要は小さな例での正常動作と、500x500セル 500世代(必要なら50世代とかに軽減して) にどのくらいかかるかが示せていればOKかと。
544 名前:デフォルトの名無しさん mailto:sage [2012/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 名前:デフォルトの名無しさん mailto:sage [2012/04/27(金) 14:36:04.79 ] javascriptで書いてみた。破壊的操作有りで。 ソースの長さ汚さは勘弁してください。 ideone.com/xNY9J ※↑は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 名前:デフォルトの名無しさん mailto:sage [2012/04/27(金) 20:27:45.31 ] てきとーにCで書いてみた 500回はさすがに秒数制限に引っかかったけど、50回で0.69秒 ideone.com/a7mH5
547 名前:デフォルトの名無しさん mailto:sage [2012/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 名前:デフォルトの名無しさん mailto:sage [2012/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 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 00:03:43.28 ] OOPならセルごとにオブジェクトで、と思ったが、 仕様が全状態の配列から配列への変換なのね。
550 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 00:54:50.29 ] >>549 べつにこだわらなくてもいいでしょ。組みやすいように組めば。 要は小さな例での動作確認出力結果と、 500x500セル 500世代(必要なら50世代とかに軽減して)の計測結果を示せればOK。
551 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 04:39:34.80 ] まあ出題者が関数的なアタマなんだろう
552 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 06:37:42.91 ] セルごとにオブジェクトとかねぇよww
553 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 07:45:09.18 ] 問題領域がどこかわかれば何処をオブジェクトにしたら良いか分かるよ
554 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 09:32:38.01 ] なかなか面白いじゃないか。 オブジェクト指向で設計されたライフゲーム、頼む。
555 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 09:44:59.90 ] この題じゃ>>541 くらいにしかならんだろ オブジェクト指向をどういうもんだと思ってんだよw
556 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 10:37:13.10 ] セル毎にオブジェクトか、面白そうだしちょっとやってみるかな
557 名前:デフォルトの名無しさん mailto:sage [2012/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 全部は長いのでこっち ideone.com/3WKkG
558 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 11:05:27.26 ] 8coreのXeonマシンでOpenMP使ってCのコードを並列化したら 500*500の500世代で1秒切ったわw
559 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 12:11:25.24 ] >>557 他スレで遊んでる内に作られてしまった…
560 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 12:13:20.34 ] >>552 ライフゲームは生物が単純だから変に思えるかもしれないけど、 これがゲームのキャラクターと考えればごく普通の考え方。 ライフゲームはどの生物も同じ能力だけど、セルがオブジェクトなら 実際の生物みたく、オブジェクトごとに能力を変えることだって出来る というかそういうゲームがあったね。 マルチプレイヤー・ネットワーク・ゲームTerrarium www.atmarkit.co.jp/fdotnet/wwebserv/wwebserv010/wwebserv010-001.html > プレイヤーは各自プログラミングした動物を持ち寄り、フィールド上で動物同士を戦わせる。
561 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 12:23:40.64 ] やっぱりオブジェクト指向だと規模が大きくなる。 逆に言えば、規模が大きい場合は オブジェクト指向が有利ってことか。
562 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 12:42:19.17 ] 大規模で全貌の把握がしづらいものを 個々人では把握できないままでも比較的扱いやすいのがOOPLだと思ってる
563 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 12:57:03.02 ] 全体を統一しづらい規模になると言語は一つではなくなる Objective-C++/CLIのような状態
564 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 16:19:14.44 ] >セルがオブジェクトなら >実際の生物みたく、オブジェクトごとに能力を変えることだって出来る 大抵のOOPLにはマルチメソッドすらないのに、 良くそんな大口たたけるな。
565 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 16:24:25.86 ] 無いのはマルチメソッドを実現するための言語仕様であって、 マルチメソッド自体は実装できるからね。
566 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 16:25:24.90 ] >>564 突然何言い出してんのこの子(´・ω・`)
567 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 16:28:06.39 ] ホーミングミサイルの話でボコボコにされたやつだ。 気にすんな
568 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 18:10:20.59 ] >>565 関数型言語でも実装できる パラダイムじゃなく言語間の比較スレなんだから そんなこと言っても意味ない
569 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 18:15:28.58 ] >>561 仮に「OOPだと規模が大きくなる」が真だとしても そこから「規模が大きいとOOPは有利」は導けない
570 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 18:53:58.34 ] 静的型付けの割に簡潔に書けて、かつ型チェックも厳しくやってほしい こういうニーズに関数型言語が応えてるから使ってるだけで、 関数型言語使ってる奴が皆OOを嫌ってるわけでも 設計レベルで使わないわけでもないんよ 争いは不毛だ
571 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 19:06:33.77 ] > 静的型付けの割に簡潔に書けて、かつ型チェックも厳しくやってほしい なんとなくC#を思いだしたけどC#で書く人いないね
572 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 19:31:55.12 ] 争わなかったらスレの存在意義がないだろ
573 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 20:25:37.43 ] >>571 C#のジェネリックってダックタイピングできないんでしょ?簡潔かなぁ。
574 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 20:41:49.41 ] >>560 ライフゲームのセルっていう文脈だからねぇよって言ったわけで ゲームのキャラクターのオブジェクト化まで否定はしてねぇよw >>564 またホーミングの子www
575 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 21:39:52.98 ] >>570 Scalaがそう。 静的言語で、簡潔に書けることを 証明した言語。
576 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 21:45:24.53 ] >>575 このスレでまだ一回もScala出て来てないぞ ライフゲームで良いからコードで証明してみてくれ
577 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 23:03:24.87 ] 「Scalaは簡潔に書けると証明した」=>「じゃあチョット書いてみて」=> 逃亡 どんなコントだよwww
578 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 23:11:10.96 ] ん? Scala知らないの?
579 名前:デフォルトの名無しさん mailto:sage [2012/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 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 00:22:22.02 ] 純粋な関数型言語って、参照するたびに値が変化する変数みたいなのは作れるの? たとえば乱数とか、参照した時点の現在時刻を値として持ってる変数とか
581 名前:デフォルトの名無しさん mailto:sage [2012/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 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 01:14:20.15 ] これで静的型付け言語なんだぜ。 val msg = if (true) "true dayo" else "false dayo"
583 名前:デフォルトの名無しさん mailto:sage [2012/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 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 01:30:58.02 ] これで静的型付け言語なのか。 本当に短いコードは動的型付け言語だけの特権じゃないことを 証明してしまったな。
585 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 02:11:32.74 ] ただ静的型にしては遅いよね。 500x500 500世代で動的な >>579 が 112秒なのに、>>581 は 196秒。
586 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 02:18:22.73 ] >>585 それ事前コンパイルしてないだろ?
587 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 02:35:44.97 ] >>583 これって一回のlifeのコール後、 すべてのセルがアップデートを終えるのをどこで待ち合わせているの?
588 名前:デフォルトの名無しさん mailto:sage [2012/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 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 06:30:26.82 ] どうせ、RubyとかLLばっかり使ってる人だろw
590 名前:デフォルトの名無しさん mailto:sage [2012/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 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 08:14:29.69 ] 最近どんどん動的型付け言語の メリットがなくなっていくね。
592 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 08:47:25.44 ] >>590 …それでmsgの型を推論しろってか。
593 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 09:24:13.53 ] >>591 この戦いが終わったら全ての武器のメリットがなくなるんだ
594 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 09:42:55.39 ] 機械語のメリットがなくなってゆくね、とか言ってる奴の同類だよなぁw
595 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 09:43:05.44 ] でも静的型はコンパイルが必要でREPLももっさり、型推論も万能じゃない スクリプト言語はこれからも残るよ
596 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 10:59:45.94 ] trueって名前の変数を作って、遅延評価によってmsgを参照したときの変数trueの値によりmsgの値も変わるってことでいいんかの 変数trueに再代入できたりしないとあんま意味なくね? いや違ってたらすまんが
597 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 11:11:11.60 ] >>590 は型推論の話じゃないの? "true dayo"も"false dayo"も文字列リテラルなので 三項演算の条件のtrue/falseを問うことなくmsgの型を文字列と確定できる
598 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 11:27:23.87 ] >>597 ああなんだそういうことか、勘違いしてたわ
599 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 11:55:08.69 ] 変数に互換性がない別の型の値を 再代入できる言語はクソです。
600 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 12:10:48.87 ] >>586 Scalaって事前(?)にコンパイルする以外になんか実行方法あったっけ?
601 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 12:18:53.17 ] >>600 >>581 はコンパイルしたらエラーがでます。
602 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 12:21:46.03 ] コンパイルしない場合は、そのまま動きます。
603 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 12:31:37.65 ] >581はscalaスクリプトだから、コンパイルする場合は -Xscript XXX オプションをつける必要があるかと
604 名前:デフォルトの名無しさん mailto:sage [2012/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 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 12:42:30.36 ] >>599 それで、代入を禁止するのと共用体を禁止するのは、どっちが良いんですか
606 名前:デフォルトの名無しさん mailto:sage [2012/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 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 12:48:20.97 ] >>605 両方いいです。
608 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 12:51:30.57 ] >>597 よく見れ。 msgにtrueを代入してる。
609 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 12:53:31.56 ] >>608 どのtrueを代入してるんですか? 全文を引用して、該当のtrueを【】でくくって下さい。
610 名前:デフォルトの名無しさん mailto:sage [2012/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 名前:デフォルトの名無しさん mailto:sage [2012/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 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 13:56:15.31 ] >>608 お前が良く見た方がいい
613 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 14:10:28.74 ] 括弧を省略する言語は危険 式と文を区別しない言語も危険
614 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 14:12:28.08 ] >>613 蛇の国からようこそおこしやす
615 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 14:22:29.08 ] Lisp系から見るとHaskellも括弧省略言語だな
616 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 19:36:04.13 ] λ式に比べたらLispだって
617 名前:デフォルトの名無しさん mailto:sage [2012/04/30(月) 00:25:42.19 ] >>616 Lispの関数は apply = foldl ($) (((f x) y) z) == (apply f) [x, y, z] 省略ではなく、式を変形している (x, y, zの型が異なる場合、Haskellは上の式が間違っていると主張する)
618 名前:デフォルトの名無しさん mailto:sage [2012/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 名前:デフォルトの名無しさん mailto:sage [2012/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 名前:デフォルトの名無しさん mailto:sage [2012/04/30(月) 01:42:08.34 ] やっぱり手続き型のC言語が こういうのは一番早いね。