【激突】関数型言語 VS オブジェクト指向言語2
■ このスレッドは過去ログ倉庫に格納されています
0001営利利用に関するLR審議中@詳細は自治スレへ
2012/04/07(土) 21:26:47.61一部には関数型言語を崇拝している人もいます
どちらが上なのか、この際はっきりさせましょう
前スレ http://toro.2ch.net/test/read.cgi/tech/1331328955/
0524デフォルトの名無しさん
2012/04/24(火) 12:35:28.990525デフォルトの名無しさん
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世代目を算出するのにかかった時間(無理なら、算出可能な
世代数とその時間)を計測して示せ。
0526デフォルトの名無しさん
2012/04/25(水) 13:54:49.010527デフォルトの名無しさん
2012/04/25(水) 14:03:57.26javaもマルチパラダイム化が進むな
OOPLが関数型言語の特徴の一部を取り込む中
スレタイの通り言語比較した場合
「副作用の有無」が一番重要なんじゃないかと思ったけどどうだろう?
機能を取り込むことはあっても無くすことはしないだろうから
副作用の有無が、開発速度や可読性、保守性にどのように影響してくるか・・・
と考えても良いお題は思いつかないんだけどね
0528デフォルトの名無しさん
2012/04/25(水) 15:26:58.18関数型言語使うようになってから、nullを持たない参照型とか、イミュータブルな値型がいかに重要か思い知った。
しかも、イミュータブルな値型を基本として、nullを持った参照オブジェクト型、nullを持たない参照オブジェクト型って形で扱えないと厳しい。
これは言語仕様として取り込まれていないとどうしようもない。
そういう意味では、C++は結構惜しいところまで行ってたと思う。
0529デフォルトの名無しさん
2012/04/25(水) 16:37:33.03値型でも仮想関数があったら元も子もない。
仮想関数をやめてswitchを使う覚悟がないと厳しい。
関数型言語のパターンマッチはswitchと同じ方式だ。
0530デフォルトの名無しさん
2012/04/25(水) 16:43:26.430531デフォルトの名無しさん
2012/04/25(水) 17:35:29.26Squeak 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) "
0532デフォルトの名無しさん
2012/04/25(水) 20:45:17.23翻訳の手間を省くのに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) } }
0533デフォルトの名無しさん
2012/04/25(水) 22:15:29.46import 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]
0534533
2012/04/25(水) 22:20:37.27show (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
0535デフォルトの名無しさん
2012/04/26(木) 20:54:15.370536デフォルトの名無しさん
2012/04/26(木) 20:56:38.970537デフォルトの名無しさん
2012/04/26(木) 21:25:38.01個別の実装は始まってなかった
0538デフォルトの名無しさん
2012/04/27(金) 01:17:14.79life <- 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)
}
0539デフォルトの名無しさん
2012/04/27(金) 08:45:31.152chで世間が判った気になり始めたら色々ヤバイな。
0540デフォルトの名無しさん
2012/04/27(金) 10:14:19.97500x500 500世代で測ったら 1.8GHz Core i7 で 68秒だった。けっこう速いね。
0541デフォルトの名無しさん
2012/04/27(金) 11:00:18.10>>525は次世代を返す関数としてるけどオブジェクト指向側は
lg = new lifegame(500,500);
for(i=0;i<500;i++)lg.life();
console(lg);
って感じでいいの?
そうしないと関数型 vs 手続き型みたいなことになるよね
0542デフォルトの名無しさん
2012/04/27(金) 11:37:20.76本物のOOは言語に依存しない
関数型言語と対立するようなOOは偽物
0543デフォルトの名無しさん
2012/04/27(金) 12:00:12.21ライフゲームは単純だけどパラダイムの特徴をかろうじて出せるくらいの規模はあるんじゃない?
お題にあるlifeという関数名(メソッド名)にこだわらなくていいと思うよ。
要は小さな例での正常動作と、500x500セル 500世代(必要なら50世代とかに軽減して)
にどのくらいかかるかが示せていればOKかと。
0544デフォルトの名無しさん
2012/04/27(金) 12:17:25.49規模の大きさは良いと思うけど、
データの破壊的操作ができると有利な御題のほうが
違いが出て良いと思った
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
0545デフォルトの名無しさん
2012/04/27(金) 14:36:04.79ソースの長さ汚さは勘弁してください。
http://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
0546デフォルトの名無しさん
2012/04/27(金) 20:27:45.31500回はさすがに秒数制限に引っかかったけど、50回で0.69秒
http://ideone.com/a7mH5
0547デフォルトの名無しさん
2012/04/27(金) 22:35:14.09let 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)
0548デフォルトの名無しさん
2012/04/27(金) 22:37:08.83let 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
0549デフォルトの名無しさん
2012/04/28(土) 00:03:43.28仕様が全状態の配列から配列への変換なのね。
0550デフォルトの名無しさん
2012/04/28(土) 00:54:50.29べつにこだわらなくてもいいでしょ。組みやすいように組めば。
要は小さな例での動作確認出力結果と、
500x500セル 500世代(必要なら50世代とかに軽減して)の計測結果を示せればOK。
0551デフォルトの名無しさん
2012/04/28(土) 04:39:34.800552デフォルトの名無しさん
2012/04/28(土) 06:37:42.910553デフォルトの名無しさん
2012/04/28(土) 07:45:09.180554デフォルトの名無しさん
2012/04/28(土) 09:32:38.01オブジェクト指向で設計されたライフゲーム、頼む。
0555デフォルトの名無しさん
2012/04/28(土) 09:44:59.90オブジェクト指向をどういうもんだと思ってんだよw
0556デフォルトの名無しさん
2012/04/28(土) 10:37:13.100557デフォルトの名無しさん
2012/04/28(土) 10:51:25.73class 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
全部は長いのでこっち
http://ideone.com/3WKkG
0558デフォルトの名無しさん
2012/04/28(土) 11:05:27.26500*500の500世代で1秒切ったわw
0559デフォルトの名無しさん
2012/04/28(土) 12:11:25.24他スレで遊んでる内に作られてしまった…
0560デフォルトの名無しさん
2012/04/28(土) 12:13:20.34ライフゲームは生物が単純だから変に思えるかもしれないけど、
これがゲームのキャラクターと考えればごく普通の考え方。
ライフゲームはどの生物も同じ能力だけど、セルがオブジェクトなら
実際の生物みたく、オブジェクトごとに能力を変えることだって出来る
というかそういうゲームがあったね。
マルチプレイヤー・ネットワーク・ゲームTerrarium
http://www.atmarkit.co.jp/fdotnet/wwebserv/wwebserv010/wwebserv010-001.html
> プレイヤーは各自プログラミングした動物を持ち寄り、フィールド上で動物同士を戦わせる。
0561デフォルトの名無しさん
2012/04/28(土) 12:23:40.64逆に言えば、規模が大きい場合は
オブジェクト指向が有利ってことか。
0562デフォルトの名無しさん
2012/04/28(土) 12:42:19.17個々人では把握できないままでも比較的扱いやすいのがOOPLだと思ってる
0563デフォルトの名無しさん
2012/04/28(土) 12:57:03.02Objective-C++/CLIのような状態
0564デフォルトの名無しさん
2012/04/28(土) 16:19:14.44>実際の生物みたく、オブジェクトごとに能力を変えることだって出来る
大抵のOOPLにはマルチメソッドすらないのに、
良くそんな大口たたけるな。
0565デフォルトの名無しさん
2012/04/28(土) 16:24:25.86マルチメソッド自体は実装できるからね。
0566デフォルトの名無しさん
2012/04/28(土) 16:25:24.90突然何言い出してんのこの子(´・ω・`)
0567デフォルトの名無しさん
2012/04/28(土) 16:28:06.39気にすんな
0568デフォルトの名無しさん
2012/04/28(土) 18:10:20.59関数型言語でも実装できる
パラダイムじゃなく言語間の比較スレなんだから
そんなこと言っても意味ない
0569デフォルトの名無しさん
2012/04/28(土) 18:15:28.58仮に「OOPだと規模が大きくなる」が真だとしても
そこから「規模が大きいとOOPは有利」は導けない
0570デフォルトの名無しさん
2012/04/28(土) 18:53:58.34こういうニーズに関数型言語が応えてるから使ってるだけで、
関数型言語使ってる奴が皆OOを嫌ってるわけでも
設計レベルで使わないわけでもないんよ
争いは不毛だ
0571デフォルトの名無しさん
2012/04/28(土) 19:06:33.77なんとなくC#を思いだしたけどC#で書く人いないね
0572デフォルトの名無しさん
2012/04/28(土) 19:31:55.120573デフォルトの名無しさん
2012/04/28(土) 20:25:37.43C#のジェネリックってダックタイピングできないんでしょ?簡潔かなぁ。
0574デフォルトの名無しさん
2012/04/28(土) 20:41:49.41ライフゲームのセルっていう文脈だからねぇよって言ったわけで
ゲームのキャラクターのオブジェクト化まで否定はしてねぇよw
>>564
またホーミングの子www
0575デフォルトの名無しさん
2012/04/28(土) 21:39:52.98Scalaがそう。
静的言語で、簡潔に書けることを
証明した言語。
0576デフォルトの名無しさん
2012/04/28(土) 21:45:24.53このスレでまだ一回もScala出て来てないぞ
ライフゲームで良いからコードで証明してみてくれ
0577デフォルトの名無しさん
2012/04/28(土) 23:03:24.87どんなコントだよwww
0578デフォルトの名無しさん
2012/04/28(土) 23:11:10.960579デフォルトの名無しさん
2012/04/28(土) 23:31:57.42細かい違いを無視すれば 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}} "
0580デフォルトの名無しさん
2012/04/29(日) 00:22:22.02たとえば乱数とか、参照した時点の現在時刻を値として持ってる変数とか
0581デフォルトの名無しさん
2012/04/29(日) 00:31:18.37case 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の機能を余り活用できていない感じ。
0582デフォルトの名無しさん
2012/04/29(日) 01:14:20.15val msg = if (true) "true dayo" else "false dayo"
0583デフォルトの名無しさん
2012/04/29(日) 01:27:13.41case 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の分割が不要になったので少し短くなったか
0584デフォルトの名無しさん
2012/04/29(日) 01:30:58.02本当に短いコードは動的型付け言語だけの特権じゃないことを
証明してしまったな。
0585デフォルトの名無しさん
2012/04/29(日) 02:11:32.74500x500 500世代で動的な >>579 が 112秒なのに、>>581 は 196秒。
0586デフォルトの名無しさん
2012/04/29(日) 02:18:22.73それ事前コンパイルしてないだろ?
0587デフォルトの名無しさん
2012/04/29(日) 02:35:44.97これって一回のlifeのコール後、
すべてのセルがアップデートを終えるのをどこで待ち合わせているの?
0588デフォルトの名無しさん
2012/04/29(日) 06:27:13.54そんなんで感動できるとか何時の時代の人?
OCaml : let msg = if true then "true" else "false"
Haskell : let msg = if True then "true" else "false"
0589デフォルトの名無しさん
2012/04/29(日) 06:30:26.820590デフォルトの名無しさん
2012/04/29(日) 07:52:20.17C++11 : auto msg = true ? "true dayo" : "false dayo";
C#(3.0) : var msg = true ? "true dayo" : "false dayo";
0591デフォルトの名無しさん
2012/04/29(日) 08:14:29.69メリットがなくなっていくね。
0592デフォルトの名無しさん
2012/04/29(日) 08:47:25.44…それでmsgの型を推論しろってか。
0593デフォルトの名無しさん
2012/04/29(日) 09:24:13.53この戦いが終わったら全ての武器のメリットがなくなるんだ
0594デフォルトの名無しさん
2012/04/29(日) 09:42:55.390595デフォルトの名無しさん
2012/04/29(日) 09:43:05.44スクリプト言語はこれからも残るよ
0596デフォルトの名無しさん
2012/04/29(日) 10:59:45.94変数trueに再代入できたりしないとあんま意味なくね?
いや違ってたらすまんが
0597デフォルトの名無しさん
2012/04/29(日) 11:11:11.60"true dayo"も"false dayo"も文字列リテラルなので
三項演算の条件のtrue/falseを問うことなくmsgの型を文字列と確定できる
0598デフォルトの名無しさん
2012/04/29(日) 11:27:23.87ああなんだそういうことか、勘違いしてたわ
0599デフォルトの名無しさん
2012/04/29(日) 11:55:08.69再代入できる言語はクソです。
0600デフォルトの名無しさん
2012/04/29(日) 12:10:48.87Scalaって事前(?)にコンパイルする以外になんか実行方法あったっけ?
0601デフォルトの名無しさん
2012/04/29(日) 12:18:53.17>>581はコンパイルしたらエラーがでます。
0602デフォルトの名無しさん
2012/04/29(日) 12:21:46.030603デフォルトの名無しさん
2012/04/29(日) 12:31:37.65-Xscript XXX オプションをつける必要があるかと
0604デフォルトの名無しさん
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 シングルコア
0605デフォルトの名無しさん
2012/04/29(日) 12:42:30.36それで、代入を禁止するのと共用体を禁止するのは、どっちが良いんですか
0606デフォルトの名無しさん
2012/04/29(日) 12:48:02.58time 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
コンパイル時間の分、スクリプト実行だと起動に時間がかかるね
0607デフォルトの名無しさん
2012/04/29(日) 12:48:20.97両方いいです。
0608デフォルトの名無しさん
2012/04/29(日) 12:51:30.57よく見れ。
msgにtrueを代入してる。
0609デフォルトの名無しさん
2012/04/29(日) 12:53:31.56どのtrueを代入してるんですか?
全文を引用して、該当のtrueを【】でくくって下さい。
0610デフォルトの名無しさん
2012/04/29(日) 13:04:26.07コンパイル通らないので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スクリプトなんてモードがあるんですね。
実行オプションでそんなに差が出るものなんですか?
0611デフォルトの名無しさん
2012/04/29(日) 13:31:36.87>>608
$ cat hello.cs
class Program {
public static void Main() {
var hoge = true ? "*true*" : "*false*";
System.Console.WriteLine(hoge); } }
$ mono hello.exe
*true*
0612デフォルトの名無しさん
2012/04/29(日) 13:56:15.31お前が良く見た方がいい
0613デフォルトの名無しさん
2012/04/29(日) 14:10:28.74式と文を区別しない言語も危険
0614デフォルトの名無しさん
2012/04/29(日) 14:12:28.08蛇の国からようこそおこしやす
0615デフォルトの名無しさん
2012/04/29(日) 14:22:29.080616デフォルトの名無しさん
2012/04/29(日) 19:36:04.130617デフォルトの名無しさん
2012/04/30(月) 00:25:42.19Lispの関数は
apply = foldl ($)
(((f x) y) z) == (apply f) [x, y, z]
省略ではなく、式を変形している
(x, y, zの型が異なる場合、Haskellは上の式が間違っていると主張する)
0618デフォルトの名無しさん
2012/04/30(月) 01:24:53.48core 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。
まだまだ遅いけど。
0619デフォルトの名無しさん
2012/04/30(月) 01:28:51.62遅くなって悪い。確かに待ち合わせが抜けてるね。
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) }
}
0620デフォルトの名無しさん
2012/04/30(月) 01:42:08.34こういうのは一番早いね。
0621デフォルトの名無しさん
2012/04/30(月) 06:36:40.190622デフォルトの名無しさん
2012/04/30(月) 08:02:32.770623デフォルトの名無しさん
2012/04/30(月) 09:21:02.55from __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)))
■ このスレッドは過去ログ倉庫に格納されています