前スレ
>>1000 > それならそれでFILTERでも変更できるインターフェースを付け加えればいいだけ。
そういう変更/拡張のし易さも議論の対象
ちゃんと変更したコードを提出しないと比較にならない
負け惜しみじゃないんだろ?
>>3 本来はフィルタでやることではないよ。
それわかってる?
まあやるなら、
class Filter {
private i = 0;
private m = 0;
begin(awk) {awk.RS=';'}
filter(line) {i++; m = max(m, line.length()); }
end() {print "最大文字数は"+m+"文字でした"}
}
こんな感じだろうw
>>4 いいから「改行コードを変更する拡張をする」に対して
OOPでやるとどれくらい簡潔になるか、コードを出せって
疑似コードじゃなくて動くヤツな
beginの引数が変わるのが好ましくない場合は
こんな感じかな。まあこの例ならsetuupでやればいいことだけど。
class Filter {
private i = 0;
private m = 0;
private awk;
setup(awk) {this.awk = awk}
begin() {awk.RS=':'}
filter(line) {i++; m = max(m, line.length()); }
end() {print "最大文字数は"+m+"文字でした"}
teardown() {this.awk = null}
}
>>5 肝心の部分はどうしたんですか?
どうやってセパレートしたんですか?
そうやって誤摩化すってことは、関数型言語で一瞬で書けるコードが
OOPでは難しいってことですね?
>>6 OOPでやると簡潔になるんじゃなくて、
変更の範囲を極小化出来るんだよ。
該当のフィルタだけの修正で、
それ以外の場所は何も変えないで変更できる。
いいから代表的なコードは貼りなおせよ
使えないな
>>8 え? 行フィルタなのに、ファイル全体をセパレートするのはおかしいでしょ?
ここにないのは、ここにあるべきじゃないコードだからだよ。
じゃあ、問題をはっきりさせよう
「標準入力から文字列を読み込んで、カンマ区切りで改行して、
各行の文字数を数えて最大文字数を標準出力に表示せよ」
これを書いて
設計がおかしいって指摘されて
ファビョってきたなw
全部関数なんかでやろうとするから
設計ができないんだ。
>>12 それ問題が不適切。
「標準入力」から文字列を読み込んで、「カンマ区切りで改行」して、
「各行の文字数を数えて最大文字数」を「標準出力」に表示せよ
ただし、カッコの中は一例であり
容易に変更できる設計にしておくこと
○から文字列を読み込んで、△で改行して、
各行に対して□を処理をして、その結果を☆に表示せよ
抽象化するとこんな感じか。
またこういう例題か…
オレ何度も書いたし、もういいや今日は。
コードが出ても議論が進まないことがはっきりしただけかw
まず、リーダーインターフェースが必要。
そのリーダーインターフェースを実装した、
標準出力リーダークラスを作る。
行セパレータインターフェースが必要
その行セパレータインターフェースの実装として、
\r\nセパレータを作る
その後フィルタインタフェースが必要で
そのフィルタインタフェース(begin、filter、end)を実装した、
「各行の文字数を数えて最大文字数」はfilterで文字数を数えて
endで結果を出力する。
あとは、同様にライタインターフェースを実装した
標準出力ライタクラス。
どうせなら、parottをJapaで書いたらこーんなに見通しのよいプログラムが短期間でできましたよ
とかそんくらいの成果聞いてみたいもんだわ
結局拡張性をもたせようとすると、
こんな感じになるわけ。
例外が悪いという意味がわかったかな?
能書きからして冗長までは良くわかった。
関数型は実装の一つを書いているだけ。
オブジェクト指向は様々な実装を書くための仕組みを
提供するもの、つまり設計の部分なので
やることの対象が違うんだよ。
オブジェクト指向で枠組み設計を行い
関数型言語でその枠組みの中身を書く
冗長というか、単にオブジェクト指向は、単処理よりも
広範囲な部分、処理の連携部分を記述する言語ってことなだけでしょ。
この程度の例題で広範も減ったくれもない気がす
>>22 > オブジェクト指向で枠組み設計を行い
> 関数型言語でその枠組みの中身を書く
こんな感じ?
{-# LANGUAGE RecordWildCards #-}
import System
import Control.Monad
data Filter a b = Filter { begin :: a, body :: a -> String -> b, end :: b -> IO () }
awkLike Filter{..} = end . body begin
countFilter = Filter {
begin = Nothing,
body = \_ -> maximum . map length . lines,
end = \p -> putStrLn $ "最大文字数は" ++ show p ++ "文字でした"}
splitBy _ [] = []
splitBy p xs = a : (splitBy p $ drop 1 b) where (a, b) = break p xs
countFilterSplitBy sep filepath = countFilter {
body = \_ -> maximum . map length . splitBy (== sep),
end = \p -> writeFile filepath $ "最大文字数は" ++ show p ++ "文字でした"
}
main' = awkLike countFilter =<< getContents -- 例1: 標準入出力使用、普通にカウント
main = mapM_ (awkLike (countFilterSplitBy ',' "test.txt") <=< readFile) =<< getArgs -- 改行コードを変えて入出力先も変更
なんかお株奪われた?
>容易に変更できる設計にしておくこと
ソースにパッチを当てて変更するのは容易ではないの?
パッチが容易ではないというのは、もしかして
「CUIは容易ではない」「GUIは容易」みたいな思想と関係あるのか
> ソースにパッチを当てて変更するのは容易ではないの?
ソースにパッチ当てるといってもいろんな意味がある。
インターフェースを変更するようなソースの修正は容易ではない。
影響があちこちに波及するからだ。
OOが使えそうなところにはOOの機能を使うし、
関数型が使えそうなところには関数型の機能を使う。
両方使えそうにないところは普通の手続き型の格好に。たったそれだけのことだろ?
「関数型 vs オブジェクト指向」 からは、「if文 vs for文」並みのナンセンスさを感じるね。
OOも関数型も単なる一機能なんだから、状況に合わせて 使う/使わない すればよいじゃない。
なにも言ってないレスされても
>>30 「関数型 vs オブジェクト指向」ならその通りなんだけど、
ここは「関数型言語 vs オブジェクト指向言語」なんだわ
そういや関数型指向ってないよねw
>>29 パッチの意味は追加と削除の二種類しかない。
マクロな視点でいうと、最新版を出す影響と古い安定版を切り捨てる影響の二つ。
現に大きな影響が出ているが、
関数型とオブジェクト指向の人間はこの問題についてなにも言ってない。
なぜなら、古い仕様が優遇されてしまうと手続き型が圧倒的に有利だから。
>>33 functional (programming)
一口にパッチと言っても
・ソースコード自体を書き換える方法
・ソースコードはそのままに静的に書き換える方法(マクロ、テンプレート)
・ソースコードはそのままに実行時に書き換える方法(モンキーパッチ)
などがあるのですが
>>37 文字列自体を操作する方法と、文字列に代わるものを操作する方法があるよね
>>33 個人的に、関数型言語は「型指向」だと思う
どう言う型受け取って、どう言う型を変えしたいのか考えると、自然と答えが出て来る
個人的には、OOPLだと設計がしっかりしてないと拡張するとき困ること多いけど、関数型言語だと、設計を意識しなくても(行き当たりばったりでも)拡張しやすい感触がある
納期に迫られ、ろくに設計できる環境も、人材も無い現場では関数型言語の方が向いてると思うんだが・・・
checkPermu ns = and.concat $ check ns
where
check [] = [[]]
check (x:xs) = map (x/=) xs : check xs
allPattern 0 _ = [[]]
allPattern _ [] = [[]]
allPattern n (ns:nss) = [x:xs | x <- ns, xs <- allPattern (n-1) nss]
-- 普通に作ったpermutations(使用例:permutations [1..3])
permutations ns = permutations' (length ns) ns
where
permutations' 0 _ = [[]]
permutations' _ [] = [[]]
permutations' n ns = [x:xs | x <- ns, xs <- permutations' (n-1) ns, checkPermu (x:xs)]
-- 汎用的なallPatternを作って、それに差し替えたpermutations
permutations2 ns= filter checkPermu $ allPattern (length ns) (replicate (length ns) ns)
-- allPatternを使った拡張版permutations(使用例:permutationsEx 3 [[1..3],[1..3],[1..3]])
permutationsEx n ns= filter checkPermu $ allPattern n ns
>>18の方針でJavaで実装したら100行超えた……
やっぱOOPはウンコだわ……
でも関数型でも50歩100歩だったよ・・・
>>41 俺は
「設計を意識しないとそもそも書けない」のが関数型言語で
手続き型言語やOOPLはメチャクチャな設計でも書けるor書けてしまうが
ちゃんと意識すると関数型言語にも通ずるようなコードが出来上がる
…と感じる
じゃあRubyで実装しましょうよw
俺は
設計・・・オブジェクト指向
実装・・・関数型言語
って感じるな。
UMLがアップを始めました
単なる型スイッチに夢おいもとめんなって。
OOだって実装の道具にすぎん。ハンマーやカンナの類だ。
実装の道具は、OOPLだよ。
OOにはOOA(分析)やOOD(設計)があって
開発プロセス全体をカバーするものなんだ。
OOPLはOOによる開発プロセスを素直に実装するための言語
分析や設計がなぜOOなのかというと、それが一番
システム開発に適しているから。
そしてその分析、設計に一番適している実装がOOPL
関数型による分析や設計が出てこないことには
関数型は実装のみにしか適用されずに終わるよ。
OOPLが先にあって、それを生かす形でOOAやOODが生まれたわけで。
夢見ちゃったって感じだね。
>分析や設計がなぜOOなのかというと、それが一番
>システム開発に適しているから。
正しくはこうだね。
分析や設計がなぜOOなのかというと、使う言語がOOPLだから。
結局無記名で議論すると個人の感想の叫びあいなんだよね
関数型における分析と設計が出ない時点で
実装のみの技術ってことだろうね。
関数と述語による形式的仕様記述やZ言語は?
OOP より FPのほうが響きがいい よってFPの勝ち。
>>59 今Haskell版読みながらRuby版書いてみてるんだけど、やっぱ適当に書かれてる印象はないなあ
発想自体がよく練らないと出てこないというか
「自分が手作業でやるならこう」を素直にコード化する手続き脳ではいきなりは出てこないコードだと思う
ああ、適当っつーか原文に倣えば「行き当たりばったり」か
どちらにしても行き当たりばったりにも見えないんだよ、それがサクッと出て来る時点でもう設計できてんじゃん、みたいな
>>55 そうは言っても関数型言語での記述は、仕様をそのまま記述してるだけだしな・・・
クイックソートの記述が有名だけど、マージソートはもっと仕様そのまま書いてるだけなのがハッキリする
-- ソート済みのリストの小さい方をリストに追加して、他方を元のリストに戻して、リストのどちらかが空になるまで比較とリストへの追加、他方のさし戻しを繰り返す
merge xs [] = xs
merge [] ys = ys
merge (x:xs) (y:ys) | x < y = x:merge xs (y:ys)
merge (x:xs) (y:ys) = y:merge (x:xs) ys
-- 1要素または空になるまで半分に分割を繰り返してからmergeによる結合(1要素のリスト、または空リストはソート済みのリスト)
mergesort [] = []
mergesort [z] = [z]
mergesort zs = merge (mergesort xs) (mergesort ys)
where
(xs,ys) = splitAt (length zs `div` 2) zs
分析については、プログラミングHaskellの最後の方に書いてるプログラムの論証を読むと参考になると思う
>>41も、設計もへったくれも無く、こうしたいなと言う脳内仕様をそのまま書いたし、checkPermuを外に追い出して差し替えられるようにしたいな。とか、長さの異なるリストも扱えるようにしたいな。という気まぐれでどんどん変更してた
(そもそも設計が必要な規模じゃないが)
ちなみに数分で、行き当たりばったりで書いてみたRubyのコードはこんな感じ
手作業でやる場合の手順をそのままコードに書いた、非常に手続き的な思考回路だと思う
class Array
def my_permu
return [] if empty?
return [ns] if size == 1
result = []
each do |n|
without_n = reject{|x| x == n }
without_n.my_permu.each do |ary|
result.push( [n] + ary )
end
end
return result
end
end
p (1..3).to_a.my_permu
>>60-61 ruby挫折したりプログラマとしても挫折した(半年で才能無いと悟って辞職)私が褒められてる・・・
設計経験Zeroですよ^^;
ごめんテストしてからレスすべきだった…
>>64 手続き的なやり方が合わなかったんじゃね?
俺は逆に、そういう式的というか関数的というか…そういう発想が出てこない
まず最初に「それをやるなら、あれをやって、これをやってから…こうかな」と考えて、それをコード化してしまう
その例で言えば俺の脳内ではまず「数字の書かれたカードを並べていき、並べたらメモる」という作業が行われる
いきなりリストを組み合わせ分増やし、フィルタを掛けるなんて発想が出てこない
>>63 を修正
class Array
def my_permu
return [] if empty?
return [self] if size == 1
result = []
each do |n|
without_n = reject{|x| x == n }
without_n.my_permu.each do |ary|
result.push( [n] + ary )
end
end
return result
end
end
p (1..3).to_a.my_permu
褒められてイイナァ…
オレのコードは誰も褒めてくれなかった。それどころかオセロの難解コートと同列扱いされる始末…orz
でもまあ、この程度の規模ではオブジェクト指向が
出てこないのはやっぱりって感じ
オブジェクト指向・・・設計部分の実装
関数型 or 手続き型 ・・・ 一処理の実装
といわれるのはこういうとことか
>>66 発想の基点は恐らく、リスト内包表記でしょうね
勝手に全ての組み合わせを生成してくれますし、条件で生成される組み合わせを絞り込める
それを柔軟に扱えるようにしない手は無いな。と
じつは、昔、別のスレでリスト内包表記と再帰の合わせ技は見掛けてたんですよ
発想だけ貰って、自分で自作しました
関数脳の作り方は今も昔も、どう言う関数?どう動くべき?です
このメソッドを使ってとか、ここはポインタで・・・とかの発想は無いです
最初にベタな発想があって、流用できる関数があれば、流用する
Q:lengthは何をする関数?
A:リストを受け取って、長さを返す関数
Q:lengthはどう動くべき?
A:先頭から、1ずつ足して行くべき
Q:リストが空っぽになったら?
A:足しても変わらない0を返す
length [] = 0
length (_:xs) = 1 + length xs
流用版
length xs = sum [1 | _ <- xs] -- 上のQ&Aと、要素数と同じ数だけ1が入ったリストを生成して足し合わせるのは等価
多分、手続き脳ですでにプログラミング出来てる人は、最初から抽象的に考える素養はあると思うので、仕様をそのまま書いてる感覚さえ分かれば、一気に関数脳になると思います
昔Smalltalkという言語があったけど普及しなかった。
これは局所的なコードは手続き型のほうが恩恵あることを示している。
C++やJavaが受け入れられたのは局所的でないところでは
OOの援用が有効だということを示している。
関数型と対峙するのは手続き型。
受け入れられるとしたらOOと手続き型の中間地点なんじゃないかな。
>>70 俺の場合、まず
>>67 のように書いてから、それを発展させて初めて関数的コードになる感じになる
実は前スレの
>>172 を書いたのも俺なんだが、同じようなコードをまず書いて、それを inject に直した
そこから更に発展させると関数型言語のコードとして成り立つようには出来ると思うが(inject→foldlの変換は難しくないし)
本当に関数型な人のアプローチとはやはり違う形になってしまうんじゃないかなと思う
>>70 関数に焦点があたってるけどさ、
それより大きな範囲のオブジェクトはどうするのさ?
>>71 昔は、手続き型とか関数型とかの選択肢より、切実にメモリやCPU速度が足りなくて、Cが選択されて、速度を損なわずOOP出来るC++が選択されてきた(OOPも最初はメモリの無駄が多いと敬遠されてきた)
PCの進化とともにLLが選択される場面が増えて来たのと同様に、関数型言語が選択される場面が増えても不思議ではない
・・・けど、C系列の言語が多く選ばれるんだろうな
do記法も、モナドが何となく分かってくると順番が重要な処理をこれまた仕様通りに書いてるだけって気付くし、手続き型を見事に矛盾無く関数型言語でエミュレートしてる事に気付いて鳥肌立つんだが
順序の無い関数の世界で順序の概念をエミュレートしてるって凄い!って
前スレの「テキストファイル読み込んで、行番号つけて表示せよ」ってのを読みやすく?書いてみた
import System.Environment
numbering xs = unlines $ map (\(x,y) -> show x ++ y) (zip [1..] (lines xs))
main = do
fnames <- getArgs
fstrings <- mapM readFile fnames
let numfstrings = map numbering fstrings
putStr $ unlines numfstrings
速度やメモリの問題はJavaやJavascriptが普及した時点で終わってる。
とくにJavascriptは関数型風にも書けるけどただの趣味の範囲で終わってる。
何を持って趣味なのかわからんけど、
ブラウザで動く言語はJavaScriptで決まりだよ。
副作用なしラムダ計算だけで記述するJavascriptって意味なんだが
順序をリストにしてるだけだと思うんだが
速度やメモリからすれば
関数型言語は無駄が多いからね。
>>71 Objective-CとC#は局所的であることを怖れないが、そういうのは受け入れられにくい
C++とJavaが受け入れられたのは、局所化でないところが実在するのではなく
漠然と、どこかそういうところに行きたいという願望があっただけだろう
何言ってるかさっぱりわからんw
>>73 意味が分からない
親が動物クラスで子が犬クラス・猫クラスとかのあれ?
型の性質を引き継ぐと言うのは型クラスとか有るけど・・・
ええと・・・で、そのオブジェクトで何をしたいの?どう拡張したいの?それって、オブジェクトである必要あるの?
犬か猫かに合わせて泣き声変えるんなら
data Animals = Dog | Cat deriving (Eq,Show)
voice a | a == Dog = "wan wan!"
voice a | a == Cat = "nya- nya-!"
これで十分なんだけど・・・そして、どっちもanimals型
犬は猫じゃないし、猫も犬じゃない
taroは犬で、taroという名前で、7歳
taro = (Dog,"taro",7)
miiは猫で、miiと言う名前で、3歳
mii = (Cat,"mii",3)
taroは猫じゃないし、miiは犬じゃない
let animalCategory (x,_,_) (y,_,_) = x == y
animalCategory taro mii
>False
>>80 全部受け入れられている言語だと思うが・・・
言語なんて金になるかどうかで受け入れるかどうかが決まるもんだよ
関数型言語で金になる話が無いだけ
と言うわけで関数型言語でスマフォアプリ作れる環境を(ry
>>82 犬とか猫を
どうやって関数型言語で表現するの?
>>84 犬とか猫を
どうやってオブジェクト指向言語で表現するの?
まさか class Dog のインスタンスが犬なの?www
>>83 言いたい事は分かったが、なんでUMLで分析しないの?
金銭の概念をオブジェクト指向分析すればいいのに、なぜ犬と猫なんだ?
>>88 もちろん
だからクラスではなくインスタンスだって言ってるだろ
>>84 え、表現できてるでしょ?
むしろ、DogもCatもAnimalsに属してるのであって、オブジェクト指向のDogとCatがAnimalの子って言う関係の方が不自然だよ
そして、SnakeやLionが増えても、Animals型である限り、同じ関数が使えるし、せいぜい1つの機能に付き、一つの関数書き換えで済む(泣き声変えるために、いちいちクラスごとにvoiceメソッドを書く必要も無い)
OOPLでもジェネリックやテンプレートで型ごとにメソッド書くでしょ?
でもそれって、OOPLの利点じゃないと言うか、むしろ関数型言語の方が強力
voiceメソッドがAnimalクラスや、その子クラスにあるのは良いけど、animalCategoryメソッドをAnimalクラスが保持するのは不自然。そうなると、関数型では存在しない第3のクラスを作る必要が出てくる(Categoryクラスみたいな?)
関数型言語のデータはデータ。関数は関数。という関係の方が、シンプルに思える
争いは、同じレベルの者同士でしか発生しないのAA
>>90 それって、関数型言語でオブジェクト指向やってるだけですよね?
>>82 一応さ、型クラス使った方が良いと思うので貼っとくね
Animalに動物足すたびに代数データ型を変更するのはアレなんで
class Animal a where
voice :: a -> String
data Dog = Dog deriving (Eq, Show)
instance Animal Dog where
voice _ = "wan wan!"
data Cat = Cat deriving (Eq, Show)
instance Animal Cat where
voice _ = "nya- nya-!"
taro = (Dog, "taro", 7)
mii = (Cat, "mii", 3)
>>87 いや、プロじゃないんでUML触ったこと無い
名前しか知らん
プロの視点で関数型言語とオブジェクト指向言語の生産性の比較とかやって欲しいところ
素人視点(=感覚的)では、LLとの比較でも、rubyやpythonは記憶力勝負(多くのメソッドを記憶してれば効率的。むしろ、何もメソッド知らない状態だとほぼ何も出来ない)
Haskellは少ない知識で割と素人でも何とかなる(既存の関数知ってる方が効率的なのはLLと変わらないが、何も知らない状態での開発効率に雲泥の差がある)
初学者へのモチベーション維持と言う意味では、関数型言語の方が向いてると思う
そして、最終的な生産効率はLLと変わらないか若干劣る(読みやすさ重視だとほぼ差がなくなる)
昔、length関数をrubyでどう書くの?と言う質問に対して、メソッドとクロージャ駆使して短いコードが返ってきた
素人じゃとても書けないと思った
Haskellなら基本的な再帰関数の作り方覚えるだけで作れるものが、LLだとそれなりの知識を必要とするのだと感じた瞬間だった
>>73 Haskellばかり話題に登るのでMLに触れておくと、
MLにはモジュール(関数とデータの集合)というものがあり、
さらにモジュールを引数に取ってモジュールを返す関数(Functor)がある
これはOOPでいうとクラスからクラスへの関数を定義できるようなもの
カプセル化?差分プログラミング?全部余裕ですよ
別に完全否定してるわけじゃないのにできますよって
余計なこと考えるだけのメリットが聞きたいのに
メソッドをどのクラスに入れるか迷うようなことは無くなるね
例えば文字列のリストのjoinを
",".join(strlist) とするか
strlist.join(",") にするかみたいなね
>>92 ・・・・え?
オブジェクト指向設計って事?
意識したこと無いけど、これがそうなのか・・・
まあ、関数型言語は色んな角度の視点を許容する感覚はあるかな
何だろう。破壊的な代入が出来ない分、そのものの性質を見ようとする体質に自然となるような・・・
Haskell でリストの要素を swap する 9 つの方法
http://jutememo.blogspot.jp/2011/04/haskell-swap-9.html >>70のlengthも視点の角度が違うだけで等価なものだしプログラミングHaskellの付録Aに書いてるlengthの定義もまた違う視点
length = foldl (\n _ -> n + 1) 0 -- 初期値0とリストの先頭要素を受け取るが、初期値に+1を繰り返すだけ、リストが空になったら蓄積変数(初期値0のもので、リストが空になるまでひたすら+1されてた変数)を返す
仕様の表現の仕方に色んな表現があるけど、OOPLや手続き型は表現自体を制限されてる感じ
だから、そのまま仕様をコードに落とせないと感じるのかも・・・
OOも知らないで語ってたのかw
ライムゲームを関数型で設計したら間違いなく不便
すっぱそうだな
>>99 でも、ぶっちゃけOOの定義定まってないだろ、このスレで
下手すりゃデータと関数を一纏めにしたらOO、くらいの勢いだぞ
>>95 HaskellでもFancterやArrow使うと表現が広がるってのは良く見かけます
自分もMonadoやFancter・Arrowを自作できると楽しみが広がりそうで楽しみに学習続けてます
(でも現時点でさえ、Rubyでどう書くの?って処理もHaskellで書けてるのですでに関数型言語マンセーですが)
短く書けても、そもそも知識がないんじゃ書けないなら意味がない(と言うのは言い過ぎだが、学習コストが高い)
と言うのが私の持論です
>>100 んなこたー無い
そもそも、ライフゲームはプログラミングHaskellで載ってる
入門書でライフゲーム書かせるOOPLの入門書って何があるよ
ちゃんと読めばdo表記やIOモナドの洗練されてる事が分かる
最小公倍数は間違いなくあるだろ。
OOはオブジェクトを起点としたプログラミング(設計)
関数型ならλ計算を起点としたプログラミング
OO側は最小公倍数を前提してるものが多いのに対し
関数型は言語サポートでそれもできるというレスが多い(Haskeller以外のことね)
俺は関数型のメリットは副作用の排除の明示にあると思ってるから
OOベースの言語に相当の機能追加すればいいんじゃないのっていうスタンス
状態をベースにしないということはモナドで状態を表現して状態を引数
実際D言語はpureキーワードあるけどね
細部の状態を追い出すのは本末転倒(メリットが少ない)だと思うし
GUIやOSを見れば分かるように大枠から状態ベースをやめるのは直感的じゃないと思う。
状態を排除する方向じゃなくコーディングレベルで状態を追い出せる記述力を持たせる。
>>104 もちろん読んでるから知ってるし自分で書いたよ
あれ書いててあれば作りやすいというならば完全に平行線だし
おれの感想は「うそつき」だね
ちなみにライフゲームはOOで書く必要ない。
「状態」をオブジェクト分割する必要性がほぼ無いから
しかも「無理があると思える対話型プログラムを自然に書く」
というお題の章に乗ってるんだけどな。
つまり書けますよといっているだけでよりメリットがあるとは言っていない。
「無理がある」がかかってるのは「対話的プログラミング」の
部分であってライフゲームじゃない
そしてHaskellでもIO使えば無理じゃないことを学ぼう、という
内容になってるのはちゃんと読んだなら知ってるな
いやだからメリットが無いでしょって言ってるんだがなぜそこに触れないw
間違いなく手続きでシンプルにかけるんだが
>>105 それを言うなら、手続き型ベースに、OOと関数型が乗っかる、だ。
だって、関数型OO言語は嫌なんだろ?
ちなみに関数型でメリットがまったく無いとは思ってない。
状態を引数に追い出すことにより副作用がなくなるというのは
分かりやすくなる場面が必ずある。
ただ今のところD言語のpureキーワード以上のメリットはあまり感じられない。
>>105 オブジェクトを起点としたプログラミングって何?
ていうか、オブジェクトって何?
関数型言語では関数は第一級オブジェクトなんですが、その場合
関数を起点にしたらその時点でオブジェクト指向なんですかね?
それとも「第一級オブジェクト」でいうところのオブジェクトとは違う
別のオブジェクトの定義があるんですかね?
>>111 うーん別にそれでもいいが、
歴史的にはC言語のグローバル連発からC++のオブジェクト分割って流れだし
設計の面でもフローチャートよりオブジェクト指向分析のほうが大枠だし。
粒度で見ればオブジェクト指向>手続き/関数型が自然な解釈だと思うよ。
>>113 そこの見分け方は「メモリ」です。
>関数を起点にしたらその時点でオブジェクト指向なんですかね?
オブジェクト指向として捉えれば正しいとみることもできるけど
(関数オブジェクトや関数ポインタをオブジェクトとして解釈する)
それは関数型の視点ではない。
関数型特有の視点は一級オブジェクトを「引数」にできるという視点であって
ここでの関数を起点というのはそういう意味。
これが納得いかないのならOOPLにも関数型言語にも両方のフレーバーはあるねというだけ。
別にオブジェクト指向のメリットを取り入れている関数型言語を全否定しないし
関数型の考え方を利用しているOOPも否定しない。
>>113 あーはいはい。俺が変わりに答えるよ。
オブジェクトは日本語で「対象」とか「目的語」とかに訳されるね。
そんで何に対しての「対象/目的」かというと、それは述語、つまり、関数。
だから、
func1( a, b ); の func1 はオブジェクトとして扱われてない。
func2( func1 ); のfunc1 はオブジェクトはオブジェクトとして扱われてる。
つーわけで、引数に取れる=第一級オブジェクトってわけ。
>関数型言語では関数は第一級オブジェクトなんですが
引数に取れる訳だから、第一級オブジェクトで間違いないが、「指向」はしてない。
引数によって関数の呼び出し先がスイッチして始めてOO。
な、OOってつまらねーだろ。
>>116 それでは f x を x の型で(型クラスで)スイッチしたらOOなんですね
ただ型を集合で括っただけでオブジェクトを指向した記憶は無いんですが
確かにつまらないというか、ただの多態ですね
今北。前スレの行番号+カンマ化のやつ、SmalltalkのリクエストがあったのでSqueakで。
| fs |
fs := {
[| n | n := 0. [:str | (n := n +1) asString, ' ', str]] value.
[:str | str, ',']
}.
FileStream fileNamed: 'text.txt' do: [:file |
[file atEnd] whileFalse: [
Transcript show: (fs inject: file nextLine into: [:line :f | f value: line])]]
OO=多態のレッテル貼りで話題ずらし
>>117 そそ。
関数型言語でも、型システムがあったりして、
引数の型によって呼び出し先がスイッチするんなら、OOってことになるな。
だから、関数型言語のOOってのも普通にあるわな。(知ってるだろうけど)
>>119 違うのですか?
違うなら説明してもらわないと分かりませんよ
あ、それと f x y z で x と y と z の型でスイッチするときに
OOPで良くある x.f y z という表記は分かり難くないですか?
なんで x だけ f の前に来てるんですか?
>>122 だからオブジェクトを起点にしてるとだけ言われても分かりませんよ
なんとなくの気分の問題なんですか?
>>124 正直それで分からないときついと思うんだけど。
オブジェクト指向分析とかイメージできる?
オブジェクトを起点にしたか否かなんて
設計者の心の中にしか無いのではないですか?
設計/分析されたものだけを見てオブジェクト指向か否か判定できるのですか?
いや、
>>92を見ると判定はできるようですね
その基準を教えてください
>>126 それは正しいとも言えるし正しく無いとも言える。
設計者本人がどう設計したかを100%証明することはできないという意味では正しいが
OOPLで書かれたコードをみてどう設計したかったを推測することは可能。
正直君のレスは哲学レベルの話でソフトウェア工学の話じゃない。
>>129 じゃあどこが理解できないか説明してもらえるかな
あまりに共通言語なさそうだから説明は無理かもしれないけど。
>正直君のレスは哲学レベルの話でソフトウェア工学の話じゃない。
お前のことだろw 自分で
>>105 読み直してみろよw
>>130 「起点にする」を正しく定義してください
それはソフトウェアの機能として定義できますか?
プログラマの心理状態として定義するのですか?
それとも哲学的な何かとして定義するのですか?
>>134 その定義は大分
>>105や
>>115と違いませんか?
それはともかく、それでは関数がオブジェクトの関数型言語では
関数が相互作用してるのでオブジェクト指向ですね
こう言っては何ですが、議論に負けないために
より一般的な、より抽象度の高い何かとして
オブジェクト指向を定義しようとするあまり
ナンセンスの域に到達してると思いますよ
主語も述語も不明なレス
結局のところオブジェクト指向で
システム開発は行われるんだよ。
たとえ関数型言語を使ったとしてもね。
だって考えるでしょ?
関数型言語で多態を実装するにはどうしようか?とか。
ルールを厳密に適用すれば何でもOOになってしまうので、
結局OOか否かは本人の胸先三寸で決まる
伊達にオブジェクト"指向"を名乗ってないな
他にないもんな"指向"なんて付いてるの
アスペクト指向さんがアップを始めました
>>139 オブジェクト指向言語で使うのは inclusion polymorphism
関数型言語でよく使うのは parametric polymorphism で、
あと Haskell なら ad-hoc polymorphism も使う(type class)
さて、parametric polymorphism や ad-hoc polymorphism を使ったところで
オブジェクト指向と言えるのかい?
JavaのGenericsやC++のtemplateやオーバーロードがOOの機能ではないって言うんならそうなんじゃね?
OOPにある機能は皆OOの機能なら
クロージャも関数も変数も条件分岐もループも再帰も
全部OOの機能だね、すげぇ
>OOPにある機能は皆OOの機能なら
そうは言ってないだろ。
GenericsやtemplateやオーバーロードをOOの機能と認めないなら、
parametric polymorphism や ad-hoc polymorphism を使ったところで
オブジェクト指向といえないし、
逆に、GenericsやtemplateやオーバーロードをOOの機能と認めるのなら、
parametric polymorphism や ad-hoc polymorphism を使ったら
オブジェクト指向といえる。
>>139 考えねぇよ
リストとかが多態なだけで、自分はあくまでリスト型を受け取って何かを返す関数作ってるだけ
>>145 JavaやC++よりもMLにparametric polymporhismが入った年のほうが早くね?
それなのにオブジェクト指向が起源になっちゃうの?
リストに対する(多相な)map
map f [] = []
map f (x:xs) = f x : map f xs
を定義しただけでOOとは、OOの範囲はすごいなぁw
lispのプログラムの特徴を「全てリスト」とするなら、OOは「全てOO」なんだよ
誰も起源なんて書いてないんじゃね?
parametric polymorphism と ad-hoc polymorphism がOOの機能なら
モナドは両方使って定義されてるからOOの機能だな
>>149 「全てobject oriented」って何だよ意味分からん
「全てオブジェクト」って言いたいのか?
だとしても、Javaのようにブロックすらオブジェクトでない言語も
OOPを名乗ってるから事実と異なる
parametric polymorphism と ad-hoc polymorphismがOOの機能なら
モナドは両方使って定義されてるから、モナドにはOOが使われている、が正解。
圏論にはOOが使われている(キリッ
>>154 あちらさんの言葉で言うところで、だよ。
JavaはGenericsが入る前からオブジェクト指向言語を名乗ってた
=> parametric polymorhism は OOPL の必要条件じゃない
オーバーロードが無いRubyがオブジェクト指向言語を名乗ってる
=> ad-hoc polymorhism は OOPL の必要条件じゃない
手続き"型"言語、関数"型"言語
そして、オブジェクト”指向”言語
名前からして比較するべきものじゃないんだよ。
オブジェクト指向は、指向って書いてあるとおり考え方。
手続き型言語を使ってオブジェクト指向が出来るように
関数型言語を使ってもオブジェクト指向が出来る。
ではオブジェクト指向言語とは何か?
答えは、オブジェクト指向を素直に表現するのに
便利な構文を持っている言語
だから必須条件なんてものは存在しない。
オブジェクト指向を代表する機能が一つでもあれば
それはオブジェクト指向言語
まあ極端な話すれば、C言語はオブジェクト指向じゃないけど、C89でもOOP自体はできるわけだし
今どきOOを手放しで絶賛する椰子は、今までコンピューターサイエンスが発展してきた流れとか知らないんだろうな
Simula,Smalltalkから1985年ころのflavorまでの流れ、その後C++1.0がcfrontとして登場しオブジェクト指向が一旦退化、
C++はその後複雑化の一途を辿っていること。
また、当初アプレットのためにC++を単純化したようなJavaが登場ししばらくはぱっとしなかったこと。
その後2000年ころのITバブルを機会にtomcat,WSDL,UDDIと合わせてWEBサービスで使われるようになり、
Java自体がが中庸のプログラマ向け言語としてソフトウエア開発分野の裾野へ普及していったこと、
素人向けの誤ったのOO本が入門者に誤解を与えいま変なOO感が普及し弊害が目に付くようになったこと、
それとは別の流れとして、haskellのparottなどでの成功を契機に関数型の利点の認識が広まってきたこと…
時代の節目かな。
基本的な流れとして手続き型も、関数型も
オブジェクト指向を取り入れる方向で進化してるよね。
オブジェクト指向言語は
関数型言語の利点を取り入れ、
関数型言語はそれだけではアプリを作りにくと
現実的な選択肢としてオブジェクト指向を取り入れる。
>>159 最近楽しいなと思うのは10年くらい前に産声を上げたオデスキーのScalaがここ近年
実用に使われるようになってきたこととか、Clojureというもう一つの選択肢がでてきたこととかetc
>>162 あ、いや成功したのはparottでは(まだ)なく、parottの実装でhaskellが注目されたこと
絶賛というか、今のOOPは単なる常識でしかない
関数型もまた、珍しい技術から単なる常識になりつつある
ただそれだけのことだろ
メソッドをメッセージと捉えるのは、その多くの場合の使われ型から無理を感じる
なれればどうってこと無い
OOも関数型も単なる一機能なんだから、
それをもって〜言語って言い張るのは無理があるんだよ。
>>169 でも、マルチスレッドや分散処理の論文は関数型や論理型の推奨する永続データモデルばかりだよ?
シングルスレッドならともかく、マルチスレッド意識したら純粋関数型や論理型じゃないと厳しい時代になってくると思うんだけど
>>170 今は普通にマルチスレッドの機能は
オブジェクト指向言語に搭載されてる。
>>170 分散したいならデータも共有しないのが基本なので
永続データの共有を推奨するのはおかしいと思う
>>170 あんま最近は追いかけてないから知らないけど、
汎用手続き型+トランザクショナルメモリの研究はもう止めちゃったのかね。
デッドロックのみならず、例外処理もしやすくなるから期待していたんだけど。
トランザクションで思い出したけど、SQLは宣言的言語と言われてたはずだったんだけど、
今どきはストアドプロシージャとかも使うらしいね。
結局欲しいのは副作用の管理
>>161>>163 オブジェクト指向の何を取り入れたの?
Haskellのどの機能がオブジェクト指向由来なのか教えてくれ
OOで見るべきところがあるのはメッセージング(徹底的な動的性)とtraitsのみ
他はゴミ
OCaml のことを言ってるんじゃないのか?
あとジェネリックプログラミングとかは、中途半端に型があるオブジェクト指向系の
言語でやるより、がっちり型のある関数型言語でやったほうがいいし、ST モナド
使えば、本物の「状態のカプセル化」ができる。
関数型ではオブジェクト指向なんてできない、というのは初心者が陥りがちなデマ。
そういや、関数型でOOPLでいう継承ってどんな形になるの?
>>179 OCamlで高階ファンクター
F はモジュール X,Y を引数にして新しいモジュールを返す
module type S = sig end
module type T = sig end
module F (X : S) (Y : T) =
struct
include X
include Y
end
やろうと思えばCでもできること
自然に書けるかなんだけどな
不自然なものを自然にしたいという需要は確かにあるね
科学的に有害か無害かは関係なく、自然か不自然かだけで商売になる
ただし自然かどうかはOO信者のさじ加減ひとつで決まります
セマンティクスとしては x の評価を 2 度する、というのは変わらんじゃないのかな。
その評価が状態に対して idempotent かどうかという違いであって。
(誤爆w)
>>183 自分はHaskellのリバース関数が自然だと感じて入門当時は感動したな
reverse [] = []
reverse (x:xs) = reverse xs ++ [x]
もちろん、組込み関数のreverseは速度重視の直感的ではないコードなんだが・・・
>>187 演算子とコンストラクタの違いが直感的に分からない
英単語だったら先頭が大文字かどうかで分かるんだが
>>188 コ、コンストラクタ!?
Haskellを例に出した私にレスされましても・・・
クラスの生成時に呼び出すメソッドと演算子に直感的な違いも何も無いと思いますが・・・
Cons演算子のことでしたら、リストという構造に対する演算子だと理解しておけば良いと思います
[1,2,3] = 1:[2.3] = 1:2:[3] = 1:2:3:[]
関数の引数にリストの全部の要素を書きたければ(要素数固定になりますが)書けますよ
sum3 (x:y:z:[]) = x+y+z
(x:xs)の部分の理解はghci上で
let (x:xs) = [1..5]
とかしてxとxsの値を調べると良いです
リストを引数に取る時の表記は、Haskellの中では特別な表記法と言う訳ではないです
+演算子もこう言う書き方は出来ま・・・廃止になったけど、ちょっと前までは出来たんです
dec (n + 1) = n
>クラスの生成時に呼び出すメソッドと演算子に直感的な違いも何も無いと思いますが・・・
右辺で使う演算子を左辺に書いてみれば違いが分かるよ
reverse (xs++[x]) = x : reverse xs
実際には xs++[x] というパターンマッチはできない
ユーザ定義のデータコンストラクタは頭大文字で始まるから
そんな混乱せんだろ
むしろコンストラクタを関数としても使えるのは便利だ
まあリストやタプルのコンストラクタは記号だが、それくらい覚えとけ
関数型言語ってようするに、
関数がクラスになる。
言ってみればJavaScriptからprototypeがなくなったようなもの。
prototypeがなくなっても効率が悪くなるだけで
オブジェクト指向できるでしょ?
それが関数型言語。
オブジェクト指向言語ってようするに、
オブジェクトがクロージャになる。
言ってみれば関数型言語から代数データ型やパターンマッチやカリー化が無くなったようなもの。
代数データ型やパターンマッチやカリー化が無いと効率悪いけど
関数型スタイルでプログラミングできるでしょ?
それがオブジェクト指向言語。
> 代数データ型やパターンマッチやカリー化が無いと効率悪いけど
それはないな。
>>194 それはチョット違うだろ。
クロージャーはlexical scope内にある変数をバインドして保持している関数オブジェクトで、あくまで関数オブジェクト。
オブジェクト指向のオブジェクトは、主に構造を持ったデータオブジェクト(単純スカラーでも可)またはクラスscopeにメソッドやインスタンス変数を
従属させモジュラレティーを確保する事に加え、インヘリタンス/mixin/treitなどで共有または階層関係を持たせ、データドリブンなインターフェースを提供する。
似たところもあるけれど、分けて考えるべきかと。
>>196 いや、マジレスされると困るわw
つーか、そこ突っ込むなら
>>193の方が違いすぎるだろ
> 関数がクラスになる
>>197 じゃあ、関数の戻り値がオブジェクト(インスタンス)になる。でいいか?
オブジェクトを作り出すもの = クラス
戻り値を作り出すもの = 関数
言ってることは同じだけどなw
>>198 カリー化されてんだから関数の戻り値も関数だろ
クラスとインスタンスのような関係はねーよ
それともあれか?関数もオブジェクトだから
関数型言語はオブジェクト指向ってやつか?くだらねえ
気持ち悪いアナロジーで無理矢理OOに対応付けて
理解しようとしなくても
ドカタの人生で関数型言語を使う機会なんて来ないから
安心しろよ
お前にとって運悪く関数型言語が普及してしまったとしても
その頃にはお前の仕事は無くなってるよ
>>197 >>193も突っ込もうと思ってたw
JSがらprototype削ったらinfix notationなlispみたいなのになっちゃうから。
ドカタ以下のトイプログラマー
オレ
>>169>>201だけれど、
関数をOOのオブジェクトとみなすところにはそれ程違和感無かった。
言語によっては、関数オブジェクトにもメタ情報設定してOOのオブジェクトみたいにmethodを従属させたり、他のmethodをmixinさせることもできるものがあるから。
ただしhaskellではないが。
関数型が自己満足以上のメリットがあると感じたこと無い
>>203 あ、でもやっぱ違うか、勘違い。
クラスは静的な物(ともかぎらないclassすらもオブジェクトという概念の言語もあるけれどちょっとおいて置いて)
オブジェクトの生成はコンストラクタってのが昨今普及している概念だから。
>>205 こめ、あんか間違えた。えーとどれがオレのレスだったっけw
ぶっちゃけいうと
関数型は今仕事がない。
将来はあると信じてる。
オブジェクト指向は今仕事がある
将来はなくなって欲しいと、関数型厨は思ってる。
>>200とかそうだなw
スパコン向けのプログラム書いてる人とかなら関数型を使う機会があるかもだが、
求められるのはプログラミング技術じゃなくて、対象問題の専門知識だわな。
あとは、大学教授が自分の論文に必要な計算をキャンパスのコンピュータを使って並列計算しました的な。
関数型は並列化が容易だから、実行速度が求められる分野に適していそうだが、
手続き型で並列化したほうがもっと速くなるから、結局なんだかなーな。
クラスタを電卓代わりに使う人用かと。
>>209 本気で並列化に取り組むとその考えかたは変わるよ。
関数型の並列化はタスク?データ?どっちのparallelだと思う。
スパコンは徹底的に性能重視だし。
まいいや2chでマジレスカコワルイオレw
>>210 関数型で出来ることが手続き型で出来ないってことはないんで。
FPGAとかは別としても、主流のノイマン型は手続き型がネイティブなんで。
>>211 できるできないまで話を広げればパラダイムなぞ何でもいいんだよ。
性能を徹底的に追及するにはCPUの命令レベル並列化SIMD並列化core間メモリ共有離散並列化ネットワーク分散並列化
徹底的に実効効率(≒GFLOPS)と性能を追求する。
一方の関数型で一部取りざたされる並列化は、並列化のしやすさ=参照透過による並列依存解析の簡便さなどで
まだ止まっている段階であり性能の追求に関してはマッタク解になっていないンジャマイカ?
だからデータパラレルorタスクパラレルか上で訊いてみた。その答えでどのくらい深く考えている椰子かわかるから。
簡便さは無視できず大切なことかもしれないが、それで数値解析がいままでより早くなっていないのであればつかわれなくてもしょうがない。。
安易に並列化に研究成果を求めて逃げるのは愚。
で、FPGAって何の話だ?と小一時間w
もしかしてハード・ソフト両面でずぶの素人さんをオレは相手にしてしまった?
上のクロージャーもしかりだけれど2chでマジレスあまりしたくない。
あーわかったわかった。
関数型が並列化に向いてるって書き込みに噛み付いてたのか。そりゃ食い違うわ。
でも、参照透過性って並列化以外に上手い生かし方が無いと思うんだが。
遅延評価も言語レベルでサポートが欲しいかと言われると、別にねぇ。
>>213 参照透過性はプログラムコードの理解しやすさ、バグの入りにくさなどに少なからず貢献あるんじゃマイカ
でも、副作用のないプログラムが読みやすいのは、手続き型でも同じことだしなぁ。
言語レベルでサポートしていることの意味は、自動化、
つまりは自動遅延評価や自動並列化になるとおもうんよ。
>>215 副作用を禁止しちゃっても十分ソフトウェアは記述できるという数学的な原理に基づき
そのための仕組みを言語レベルの機能でちゃんとサポートし副作用を低減しようとする意義はあるのでは?
そんな蓮舫さんみたいなこと言われても。
副作用のある部分をコードの一部に隔離したとき、
それが他に漏れてないことを静的型検査できるのがメリット
静的型検査なんて要らないし、副作用の有無なんて
コメントにでも書いとけば分かるだろ
というプログラマにはメリット無い(批判する意図はないので注意)
ただし、
>>218は特定の言語(HaskellとかD)のメリットであって
関数型言語のメリットでは無い
中身無いなぁ。
普及率は人気の度合い。なぜ人気があるのか考える必要がある。
誰かさんの思い込みより価値ある。
>>216 仮にIOを禁止しても、IOと殆ど同じモナドを簡単に作れる
だから禁止していいんだという解釈もあるが、禁止しても無意味だという解釈もある
Haskellが、いずれかの解釈を一方的にサポートすることはない
あくまで中立
モナドって副作用の定義を限定的にして副作用なくしたと主張してるだけで
ソフトウェア工学上で問題になる事項をすべて解消しているわけではいないと思うんだけど
どう思う?
問題を定義した本人には、自己解決しましたと主張する権利があると思う
>>221 全くもってその通り!!
中国語だって世界中で大人気だからな!!
>>223 現実のコンピュータが副作用必須の設計で、モナドは副作用解決に使えるというだけ。
モナドが副作用解決のために作られた訳じゃない。
モナドは何のために作られたの?
人工知能だけに限らず人間の知能にも起こり得るフレーム問題は、ジョン・マッカーシー
らの提案したフレーム問題と区別して一般化フレーム問題と呼ばれている。
ソースはwikipedia
>>223 限定的なフレームを選択しないと、フレーム問題に対処できない
関数型は問題資源を乱獲してあっという間に死滅させる蛮族の手法
対して従来のやり方は問題を死滅させず適宜再生産もする
農耕・牧畜をおぼえた文明人の手法
は?
単に生産性が低いものを賞賛してるだけのバカですねw
OOを使ったプロジェクトは次の二つに分類される
・プロジェクトが成功した場合 => 成功したのはOOのおかげ
・プロジェクトが失敗した場合 => 設計者やプログラマがOOに未熟だった
以上の詭弁により、OOはソフトウェア工学の全ての問題を解決した
え、関数型って生産性あったんですか。
どんな被害妄想だよ。成功も失敗も設計者の腕次第だろ。
解決はするけど生産はしない
>>232 生産性については職業プログラマの人に比較して貰うとして、少なくとも、rubyで入門書のサンプル以上のものが作れなかった自分が、haskellでは
>>41,
>>74のコードを書ける様になった
初心者には、rubyよりhaskellの方が自力でコード書ける様になり易いんじゃ無いかと思う
せめて一ファイル千行ぐらいのものを
数十ファイルからなるアプリを作ってから
書けるようになったといって下さい。
短い関数一つと程度、
あんなの誤差でしかない。
プログラムが書けるようになったといえる最低ラインは数万行のアプリを作れてから・・か。
OpenDylanは処理系が80万でIDEが100万stepだったっけ、失念
gccが少し前は30~40万行あった、いまの4.6,47はもっとだろうな
>>236 書きたいものを書ける様になったら行数関係無い気がするけど・・・
そもそも、私の場合、Rubyではどう書けばいいかすら思い浮かばない
(学習が足りないと言われればそうだけど、どっちも入門書読みかけ状態での知識でしかない)
Haskellは入門書読みかけの状態でも結構色々書けるから、入門者のモチベーション維持にも良いんじゃないかな
(少なくとも、自分のモチベーション維持には良い効果がある)
書きたいものを書けるのは
プロである以上最低限のことです。
>>241 間違えた、The compiler includes an IDE (Win32 only, sorry), CORBA, OLE, all in all 850000 lines of code. This is (nearly) all Dylan code.
>>243 書きたくない物でも金を受けとる以上書き上げるのが…(ry
>>245 あんたプロや。プログラマー(ry)や。
>>243 プロじゃないと言うか、プロの卵として就職して半年で諦めたんですが・・・
そんな奴が、Haskellでなら、ちょっとは書ける様になったですよ
それで気付いたのは、やってる事はどの言語も同じなのかもなぁー・・・と
で、関数型言語はそのやってる事は同じ。の部分を気付きやすい言語だな・・・・と
他の言語で何やってるのか分かんなくて挫折した人は、一度、関数型言語に挑戦してみてほしいかも
>>248 一緒に頑張りまっしい
多分、私はそもそものググルための用語を知らないのが、そもそもの才能の無さな気がする
なので、そもそもググらず自分で作っちゃえ!派な自分には関数型言語の方が性に合うっぽい
(不器用なのは自覚してる)
そういうセリフは関数型言語を作ってから言って下さい。
作らずに言語を使ってるだけのくせに
>>249 > なので、そもそもググらず自分で作っちゃえ!派な自分には関数型言語の方が性に合うっぽい
初心者なら当然のことだよ。
俺なんかだと、見ただけで簡単な処理と分かるようなもの、
自分で作れると分かっているものは、作っても時間
を浪費するだけで何の経験値にならないし、自慢にもならない。
でも初心者にとっては、そんなものでも
挑戦する価値がある課題なのだから。
自分で作ったんだって自慢げになるでしょ?
何万行とかで脅されても気にする事無いよ
ドカタ仕事で書くコードなんてAPI呼び出すだけ、コピペコード満載の
頭悪いコードなんだから
疑うなら適当なコード書く御題出してみ?Javaのコードとか出てこないから
253 :
252:2012/04/13(金) 06:57:36.95
多分、「そんなの意味ない」「もっと規模が大きくないと本当の事は分からない」
とかその手の言い訳を、御題のコードの10倍くらいの長さの文章で
必死に語ってくれるよ
本当は2chのレスに収まる規模のコードも書けないんだけどね
>>252 じゃあお題。
プログラマーなら「FizzBuzz問題」解けるよな?
http://kohada.2ch.net/test/read.cgi/prog/1209467166/401 401 :仕様書無しさん:2012/04/09(月) 23:59:48.08
FizzBuzzクイズ
1.fizz.buzz #=> 1
3.fizz.buzz #=> "Fizz"
5.fizz.buzz #=> "Buzz"
15.fizz.buzz #=> "FizzBuzz"
となるようなメソッドfizz、buzzは定義可能か?
可能である場合、同様にgizzを追加定義し、
7.fizz.buzz.gizz #=> "Gizz"
21.fizz.buzz.gizz #=> "FizzGizz"
35.fizz.buzz.gizz #=> "BuzzGizz"
105.fizz.buzz.gizz #=> "FizzBuzzGizz"
105.fizz.gizz.buzz #=> "FizzGizzBuzz" と拡張・応用ができるか?
メソッドのコールに()が必須の言語では 3.fizz().buzz() 形式でも構わない。
オープンクラス機構やメソッドのない言語では関数(buzz(fizz(3)) #=> "Fizz" など)で。
>>252 ありがとうです
では、仕事があるので明日私は書くと思いますが(飲んで帰るので、今日は無理)
ファイルと検索したい文字列をコマンドから入れて、見つかった行と列のリストを表示すると言うのはどうでしょう?
全くなんの工夫もないが
$ cat fizzbuzz.hs
import Control.Monad (mapM_)
main = mapM_ (runFizzBuzz . gizz . buzz . fizz) [1, 3, 5, 7, 15, 21, 35, 105]
runFizzBuzz (n, s)
| s == "" = putStrLn $ show n
| otherwise = putStrLn $ show s
fizz n
| n `mod` 3 == 0 = (n, "Fizz")
| otherwise = (n, "")
buzz (n, s)
| n `mod` 5 == 0 = (n, showString s "Buzz")
| otherwise = (n, s)
gizz (n, s)
| n `mod` 7 == 0 = (n, showString s "Gizz")
| otherwise = (n, s)
$ runghc fizzbuzz.hs
1
"Fizz"
"Buzz"
"Gizz"
"FizzBuzz"
"FizzGizz"
"BuzzGizz"
"FizzBuzzGizz"
この場合の顧客がのぞむもの。
map (gizz . buzz . fizz) [1, 3, 5, 7, 15, 21, 35, 105]
-- [1, "FIzz", "Buzz", "Gizz", "FizzBuzz", "FizzGizz", "BuzzGizz", "FizzBuzzGizz"]
map (buzz . gizz . fizz) [1, 3, 5, 7, 15, 21, 35, 105]
-- [1, "FIzz", "Buzz", "Gizz", "FizzBuzz", "FizzGizz", "GizzBuzz", "FizzGizzBuzz"]
整数と文字列が同じリストにフラットに入らなきゃ嫌だという主張?
struct filter_t{ int e; const char *t; };
struct fizzbuzz_t
{
int in; std::string out;
fizzbuzz_t &operator >>( filter_t &f )
{ if( 0==in%f.e ){ out.append( f.t ); } return *this; }
operator const char *()
{ if( out.length() ) return out.c_str(); static char tmp[50]; itoa( in, tmp, 10 ); return tmp; }
};
fizzbuzz_t operator >>( int i, filter_t &f ){ fizzbuzz_t fb; fb.in = i; fb>>f; return fb; }
filter_t fizz = { 3, "Fizz", };
filter_t buzz = { 5, "Buzz", };
filter_t gizz = { 7, "Gizz", };
int main(){ 105>>fizz>buzz>>gizz>>endfb; return 0; }
fizz buzz gizz (とその合成)で完結する。
合成順が結果に反映される。
結果は標準出力ではなく関数の戻り値として欲しい。
というのが要件だろう。
関数縛りがなければマクロですぐなんだが。
ごめんごめん途中で送信してしまった。
読まなくても良いくらいC++でのスタンダードな回答。
struct filter_t{ int e; const char *t; };
struct fizzbuzz_t
{
int in; std::string out;
fizzbuzz_t &operator >>( filter_t &f )
{ if( 0==in%f.e ){ out.append( f.t ); } return *this; }
operator const char *()
{ if( out.length() ) return out.c_str();
static char tmp[50]; itoa( in, tmp, 10 ); return tmp; }
};
fizzbuzz_t operator >>( int i, filter_t &f ){ fizzbuzz_t fb; fb.in = i; fb>>f; return fb; }
filter_t fizz = { 3, "Fizz", };
filter_t buzz = { 5, "Buzz", };
filter_t gizz = { 7, "Gizz", };
int main(){ 105>>fizz>buzz>>gizz; return 0; }
スタンダードっていうより姑息だな。(←褒め言葉)
とはいえ、関係ない演算子をしれっとまぎれこませちゃったら失格じゃまいか?
>>260 マクロを使わなくても、型クラスと多値とモナドが賢い言語なら関数でも書けるんじゃね?
>>257 map でそれをやれ、というのは無理。
それに hoge を追加することを想定して、
map (hoge . gizz . buzz . fizz) [1, 3, 5, 7, 15, 21, 35, 105] について考える。
関数合成と map の性質より、
map (f . g) [...] = map f (map g [...]) であるから
map (hoge . gizz . buzz . fizz) [1, 3, 5, 7, 15, 21, 35, 105]
= map hoge (map (gizz . buzz . fizz) [1, 3, 5, 7, 15, 21, 35, 105])
= map hoge [1, "FIzz", "Buzz", "Gizz", "FizzBuzz", "FizzGizz", "BuzzGizz", "FizzBuzzGizz"]
よって hoge が書けない。===== 終 ===== 了 =====
-- という風に論破されちゃうのが嫌な自称上流には嫌われるだろうなぁ、
-- Haskell や形式手法はw
メソッドの追加は副作用よりも難しい
代入しても型は不変だがメソッドを追加したら型が変わる
マクロも型クラスも多値もモナドも無いけどSqueak Smalltalkで。
Trait named: #FizzBuzz uses: #() category: 'FizzBuzz-Trait'
FizzBuzz >> fizzBuzzPrep
self value isString ifFalse: [thisContext sender receiver: self -> ''].
FizzBuzz >> fizzBuzzReturn
| method nextByte type |
method := thisContext sender sender method.
nextByte := thisContext sender sender method at: thisContext sender sender pc.
type := nextByte // 16.
^(type = 13 and: [FizzBuzz selectors includes: (method literalAt: nextByte \\ 16 + 1)])
ifTrue: [self] ifFalse: [self value ifEmpty: [self key]]
FizzBuzz >> fizz
self fizzBuzzPrep.
(self key isDivisibleBy: 3) ifTrue: [self value: self value, 'Fizz'].
^self fizzBuzzReturn
FizzBuzz >> buzz
self fizzBuzzPrep.
(self key isDivisibleBy: 5) ifTrue: [self value: self value, 'Buzz'].
^self fizzBuzzReturn
FizzBuzz >> gizz
self fizzBuzzPrep.
(self key isDivisibleBy: 7) ifTrue: [self value: self value, 'Gizz'].
^self fizzBuzzReturn
Integer uses: FizzBuzz. Association uses: FizzBuzz.
105 fizz gizz buzz. "=> 'FizzGizzBuzz' "
>>256 は runFizzBuzz に渡す前までは文字列の蓄積で通してるから、
putStrLn を削るだけでリストになるんじゃね?
継続使える言語なら書けるんじゃね?
Scheme使いの登場を待ってるわけ?
てか継続をどう使うことを想定してるの?
join fs n = case concatMap (\f -> f n) fs of
"" -> Left n
s -> Right s
fizzT f s n | f n == 0 = s
fizzT _ _ _ | otherwise = ""
fizz = fizzT (`mod` 3) "Fizz"
buzz = fizzT (`mod` 5) "Buzz"
gizz = fizzT (`mod` 7) "Gizz"
main = print $ join [fizz, buzz, gizz] 105
こっちのほうが join を入れ子に出来て良いかも
import Data.Either
join fs n = case concat $ rights $ map (\f -> f n) fs of
"" -> Left n
s -> Right s
fizzT f s n | f n == 0 = Right s
fizzT _ _ _ | otherwise = Right ""
fizz = fizzT (`mod` 3) "Fizz"
buzz = fizzT (`mod` 5) "Buzz"
gizz = fizzT (`mod` 7) "Gizz"
main = print $ join [join [fizz, buzz], gizz] 105
join とか無しで gizz buzz fizz 105 で "FizzBuzzGizz" をさくっと返す方法はないの?
ここまでruby/python無し
LLに有利っぽいのに
gizz buzz fizz 105 という式が、ちゃんと型を持っているとする。
また、fizz 105、buzz fizz 105 という式も、同様になんらかの型を持つとする。
すると、
fizz の型は
Int -> a
buzz の型は
(Int -> a) -> Int -> b
gizz の型は
((Int -> a) -> Int -> b) -> (Int -> a) -> Int -> c
というような型でなければならない。無理。というか、どう頑張っても、
先頭に do か何かが要る。
型システムに制約を受けないパワフルな関数型言語ってのはないもんかね。
Perlしか読めないから誰かPerlで書いて
>>273 つーか元出題者が Ruby だとオープンクラスやらなんやら使ってできるぜ、
って言いたいだけで作った問題なのがかなり見え見えなんだが。
書き込み行数がオーバーするんで適当に圧縮した
module FizzBuzz
SYM_HASH = {} ; def self.add_fizz sym, n ; SYM_HASH[sym] = n ; end
def self.do_it sym, n, prefix ; if m = SYM_HASH[sym]
if n % m == 0
s = sym.to_s ; s.capitalize!
if prefix.kind_of? String then s[0, 0] = prefix end
s.fizzbuzzval = n ; s
else prefix end else nil end
end
end
class Integer ; def method_missing sym
if it = FizzBuzz.do_it(sym, self, self) then it else super end
end end
class String ; attr_writer :fizzbuzzval ; def method_missing sym
if it = FizzBuzz.do_it(sym, @fizzbuzzval, self) then it else super end
end end
FizzBuzz.add_fizz :fizz, 3
FizzBuzz.add_fizz :buzz, 5
FizzBuzz.add_fizz :gizz, 7
p [1, 3, 5, 7, 15, 21, 35, 105].map{|n|n.fizz.buzz.gizz}
>>276 突貫工事だけれど…
package FizzBuzzGizz;
sub new {
my ($c, $n) = @_;
bless {n => $n, s => ''}, $c
}
sub fizz {my $t = shift; $t->{s} .= 'Fizz' if 0 == $t->{n} % 3; $t}
sub buzz {my $t = shift; $t->{s} .= 'Buzz' if 0 == $t->{n} % 5; $t}
sub gizz {my $t = shift; $t->{s} .= 'Gizz' if 0 == $t->{n} % 7; $t}
sub result {my $t = shift; $t->{s} ? $t->{s} : $t->{n}}
1;
package main;
do {
my $fbg = new FizzBuzzGizz($_);
print "$_:" . FizzBuzzGizz::result($fbg->fizz->buzz->gizz) . "\n"
# あるいは print "$_:" . $fbg->fizz->buzz->gizz->result . "\n"
} for qw{1 3 5 7 15 21 35 105};
$ perl p_fizzBuzzGizz.pl
1:1
3:Fizz
5:Buzz
7:Gizz
15:FizzBuzz
21:FizzGizz
35:BuzzGizz
105:FizzBuzzGizz
>>280 objectのmethodが返す値はまたobjectだけれど、
printで評価すると判定結果文字列を返すには、
こんな書き方くらいしかないのかな…?
多値のリスト返しでやってみようと思ったけれどうまい方法が思いつかなかったぜよ
>>281 package FizzBuzzGizz;
sub new {
my ($c, $n) = @_;
bless \"$n."
}
sub fizz {my $t=shift; $_=$$t; bless do { /(^\d+)/; 0 == $1 % 3 ? \"${_}Fizz": $t }}
sub buzz {my $t=shift; $_=$$t; bless do { /(^\d+)/; 0 == $1 % 5 ? \"${_}Buzz": $t }}
sub gizz {my $t=shift; $_=$$t; bless do { /(^\d+)/; 0 == $1 % 7 ? \"${_}Gizz": $t }}
1;
package main;
do {
my $fbg = new FizzBuzzGizz($_);
print ${$fbg->fizz->buzz->gizz} . "\n"
} for qw{1 3 5 7 15 21 35 105};
>>272 何縛りのゲームなのかわからんけど、関数合成演算子でも駄目かね?
import Data.Either
import Prelude hiding ((.))
(.) f g n = case concat $ rights [f n, g n] of
[] -> Left n
s -> Right s
fizzT f s n | f n == 0 = Right s
fizzT _ _ _ | otherwise = Right []
fizz = fizzT (`mod` 3) "Fizz"
buzz = fizzT (`mod` 5) "Buzz"
gizz = fizzT (`mod` 7) "Gizz"
main = print $ fizz.buzz.gizz $ 105
>>282 package FizzBuzzGizz;
sub new {
my ($c, $n) = @_;
bless \"$n."
}
sub comm { my ($t, $r, $s) = @_; $$t =~ /(^\d+)/;
0 == $1 % $r ? \"${_}$s": $t }
sub fizz {bless comm((shift), 3, 'Fizz')}
sub buzz {bless comm((shift), 5, 'Buzz')}
sub gizz {bless comm((shift), 7, 'Gizz')}
1;
package main;
for (qw(1 3 5 7 15 21 35 105)) {
print ${new FizzBuzzGizz($_)->fizz->buzz->gizz} . "\n"
}
Ruby のカオスな部分を前面に押し出して書いてみた
class String
attr_accessor :srcint
private
def f(n,s); (@srcint % n == 0) ? (self << s) : (self); end
end
class Integer
private
def f(n,s); (self % n == 0) ? (s.srcint = self; s) : (self); end
end
class Object
def fizz; f(3,'Fizz'); end
def buzz; f(5,'Buzz'); end
def gizz; f(7,'Gizz'); end
end
p [1,3,5,7,15,21,35,105].map{|n| n.fizz.buzz.gizz }
# => [1, "Fizz", "Buzz", "Gizz", "FizzBuzz", "FizzGizz", "BuzzGizz", "FizzBuzzGizz"]
p [1,3,5,7,15,21,35,105].map{|n| n.fizz.gizz.buzz }
# => [1, "Fizz", "Buzz", "Gizz", "FizzBuzz", "FizzGizz", "GizzBuzz", "FizzGizzBuzz"]
>>284 ${_}$s←バグ
package FizzBuzzGizz;
sub new {
my ($c, $n) = @_;
bless \"$n."
}
sub comm { my ($t, $r, $s) = @_;
0 == $$t % $r ? \"$${t}$s": $t }
sub fizz {bless comm((shift), 3, 'Fizz')}
sub buzz {bless comm((shift), 5, 'Buzz')}
sub gizz {bless comm((shift), 7, 'Gizz')}
1;
package main;
for (qw(1 3 5 7 15 21 35 105)) {
print ${new FizzBuzzGizz($_)->fizz->buzz->gizz} . "\n"
}
>>286 オッチャン、どうせ書くならこうやろ
package FizzBuzzGizz;
sub new { my ($c, $n) = @_;
bless \"$n." }
sub com { my ($t, $m, $s) = @_;
bless 0 == $$t % $m ? \($$t.$s): $t }
sub fizz {com(shift, 3, 'Fizz')}
sub buzz {com(shift, 5, 'Buzz')}
sub gizz {com(shift, 7, 'Gizz')}
1;
package main;
for (qw(1 3 5 7 15 21 35 105)) {
print ${new FizzBuzzGizz($_)->fizz->buzz->gizz} . "\n"
}
大差ないか…
new FizzBuzzGizz($_) している時点でダメだろ。
関係ないオブジェクトにもfizz buzz gizzが継承されてしまう気持ち悪さを除けば、
ちゃんと書けているのは今のところRubyだけって感じか。
文字列オブジェクトにインスタンス変数(状態)を持たせられるのが強みだなぁ。
Smalltalkのはやってることが「独立した関数(メソッド)」と呼ぶにはどーよという内容だから失格。
関数型は型システムの制約でこういう仕様の関数モドキは書けないっていうことでFA?
>>290 でも実際のところ、こんな書き方したくないけどね
実際にやるなら、何らかのコンテナにラップしてからmapして
それが終わったら、文字列や数値として取り出すと思う
原文がいきなり数値に対してメソッド呼んでるから、容赦なく組み込みクラスを弄ったが…
JSならやれそうじゃね?
>>291 まあクイズだからね。言語機能をどう使って無茶な要件をクリアするかのパズルみたいなもん。
数値がobjectとしてmethodを持たない言語ではどうするかってお題だったのかよ…
>>290 自分の足を自分で撃ちたいなら、それに向いた言語ある、という話、でFA
>>290 RubyはメソッドチェインOKなのに
関数型言語はfizz(buzz(gizz))しか認めないんだろ?
そりゃ静的型じゃ無理っつーか制限する意味が分からん
後からgizz等を追加できる拡張性あるコードを
書けないならともかく、そうでもないしな
>文字列オブジェクトにインスタンス変数(状態)を持たせられるのが強みだなぁ。
-- String "has-a" Integer
data HasA = HasA String Integer
instance Show HasA where show (HasA s n) = if s == "" then show n else show s
fizz (HasA s n) = HasA (s ++ if mod n 3 == 0 then "Fizz" else "") n
buzz (HasA s n) = HasA (s ++ if mod n 5 == 0 then "Buzz" else "") n
gizz (HasA s n) = HasA (s ++ if mod n 7 == 0 then "Gizz" else "") n
main = print $ map (gizz . buzz . fizz . HasA "") [1,3,5,7,15,21,35,105]
>>298 似たようなコード書いてたら先に張られてた
個人的には hasA = HasA "" を定義しておくのが好み
それはともかく、.演算子使ってるからケチ付けられると思うぜ多分w
ここまでJava無し
JavaScriptできた。俺の使ってるブラウザ以外で動くかどうかはわからん。
var def_fizz = function (name, m) {
var fun = function () {
var tp = typeof this.valueOf();
var n = (tp === 'number') ? this : this.fizzbuzzval
if (n % m === 0) {
var s = name.charAt(0).toUpperCase() + name.slice(1);
if (tp === 'string') {
s = this + s;
}
s = new String(s);
s.fizzbuzzval = n;
return s;
} else {
return this;
}
} ;
Number.prototype[name] = fun;
String.prototype[name] = fun;
} ;
def_fizz('fizz', 3);
def_fizz('buzz', 5);
for (var i = 1; i <= 30; ++i) {
document.writeln(i.fizz().buzz());
}
>>305 ΟΓΖ
基本データ型のリテラル単独でクラスのインスタンスになり得ない言語である以上、new しないことにははじまらない‥‥。
いやいや。基本データ型がオブジェクトでなかったり
組み込みクラスにメソッドを追加できない言語では
普通に関数で実装すればいいと思うよ。gizz( buzz( fizz( n ) ) )みたいに。
>>308 それが一番シンプルだと思う。
速度も早いだろうしね。
>>309 それがね、gizz() buzz() fizz()の三関数をどれも特別扱いせず、
いずれの戻り値もいずれの引数となり得る柔軟さを備える仕様にし、かつ
print gizz( buzz( fizz( n ) ) )で
1
"Fizz"
"Buzz"
"Gizz"
"FizzBuzz"
"FizzGizz"
"BuzzGizz"
"FizzBuzzGizz"
という出力を得るのは、以外とマンドくさいのよ。
gizz()だけは文字列を返すなどそれぞれの関数のIFを個別に制約すれば子供の使いなみに楽。
つかこういう要求仕様でnewは使うなとか制限もうけること自体が仕様策定の段階でミスなんだろ。
その意外と面倒くさいところをどう回避するかがこのクイズの味噌なんだが。(´・ω・`)
>>299 > .演算子使ってるからケチ付けられると思うぜ多分w
志村! HasA! HasA!
>>311 そしたら、こうだな。
sub com {
my ($mod, $zz, $num, $str) = @_;
$str .= $zz
if 0 == $num % $mod;
$str ? ($num, $str) : $num
}
sub fizz {com(3, 'Fizz', @_)}
sub buzz {com(5, 'Buzz', @_)}
sub gizz {com(7, 'Gizz', @_)}
print "$_: " . gizz(buzz(fizz($_))) . "\n"
for qw(1 3 5 7 15 21 35 105);
実効例:
$ perl p_FizzBuzzGizzAret.pl
1: 1
3: Fizz
5: Buzz
7: Gizz
15: FizzBuzz
21: FizzGizz
35: BuzzGizz
105: FizzBuzzGizz
perlのscalar context/list contextを巧みに?利用してるんで、
それを知らない人には分かりにくいかもしれず、申し訳ないんだか…
※もうちょっと考えて出題して欲しいな、言っちゃ悪いがこういった仕様策定ミスをcodeでカバーすることに何の意味が…
perlのscalar context/list contextの説明。
関数の引数にフラグを一個追加したもの
つまり、
foo(value, false) ・・・ スカラ呼び出し
foo(value, true) ・・・ リスト呼び出し
foo(value, flag)関数の説明
flagがfalseの場合、スカラタイプの値を返します。
flagがturの場合、リストタイプの値を返します。
まあ、こんなもん。
>>314 志村、ここ、ここ。
my ($mod, $zz, $num, $str) = @_;
↑
$str ? ($num, $str) : $num
sub xxx {com(3, 'Fizz', @_)}
↑
print "$_: " . gizz(buzz(fizz($_))) . "\n"
と
print "$_: " , gizz(buzz(fizz($_))) , "\n"
の動作の違い
なんか、中途半端に知っている人が出てきたな…
寝るか…。ノシ
核の部分はこれだけか
sub com {
my ($mod, $zz, $num, $str) = @_;
$str .= $zz if 0 == $num % $mod;
$str ? ($num, $str) : $num
}
sub fizz {com(3, 'Fizz', @_)}
sub buzz {com(5, 'Buzz', @_)}
sub gizz {com(7, 'Gizz', @_)}
Perlは良く知らないのだが、
print が ($num, $str) の $num を都合よく読み捨ててくれるのは何故?
print fizz(3) の出力は、3Fizz になりそうに思うんだが。よーわからん。
>>317 結局 Perl のはこのクイズの要求には到達できてなくて(関数単体では完結できていない)、
出力時の文字列との結合でごまかしているってカラクリ。map とかすればズルが露呈する。
>>319 ズルはしてないよ。返戻contextの何番目を数値、何番目を文字列とし後続を省略時はundefとなる
利用しているだけでこういうやり方は使うときは使う。
でも、こういうズレたクイズはもういいよ。
関数型言語、オブジェクト指向言語の比較としてこの題材がどういう意味を持っているの?
これ単に
>>297とか排除して特定の機能を持った言語を有利に導きたかっただったんじゃない?
じゃあ、map版です。
use 5.12.0;
sub com {
my ($mod, $zz, $num, $str) = @_;
$str .= $zz ;if 0 == $num % $mod;
$str ? ($num, $str) : $num
}
sub fizz {com(3, 'Fizz', @_)}
sub buzz {com(5, 'Buzz', @_)}
sub gizz {com(7, 'Gizz', @_)}
map{say "$_: " . gizz(buzz(fizz($_)))} qw(1 3 5 7 15 21 35 105);
>>321 しくったorz、ifの前の;が余計だった。
use 5.12.0;
sub com {
my ($mod, $zz, $num, $str) = @_;
$str .= $zz if 0 == $num % $mod;
$str ? ($num, $str) : $num
}
sub fizz {com(3, 'Fizz', @_)}
sub buzz {com(5, 'Buzz', @_)}
sub gizz {com(7, 'Gizz', @_)}
map {say "$_: " . gizz(buzz(fizz($_)))} qw(1 3 5 7 15 21 35 105);
そっちじゃなくて、print時の文字列連結による$numの読み飛ばしの件についてでしょ。
print "$_: " , gizz(buzz(fizz($_))) , "\n"
だと 3: 3Fizz とかなる。
>>323 「gizz,buzz,fizzの三関数をscalar contexで評価すると判定文字列が得られ
list contextで評価すると数値と判定文字列のリストが得られる関数である
ただし数値が3,5,7の倍数でない場合は返戻リストの第二要素の判定文字列は
undef(文字列として評価すると空文字列)」
という仕様の関数として書いている。
のだよ。code嫁よ。
>>297の主張もじっさい意味不明なんだけど。。。
メソッドチェーンっていうのは関数の入れ子の呼び出し gizz(buzz(fizz(n))) と実質同じだろ?
組み込みの関数合成関数の使用を禁じている訳ではないのだから、要求通り関数で完結できてさえいれば
それらを合成しようがぜんぜん問題ないし、型システムのモデルが足を引っ張っている以外、
なにが不利なのかさっぱり分からん。Perl のズル同様で、関数で完結できてないくせに
合成関数のオーバーロードでつじつまを合わせようとするからなんだかなーとなる。
>>322 "$_: " . ってのを無しでやっみてくんない?
>>325 ずれてないよ。
値と評価文字列をlistdで返戻する。
scalarで評価するかlistで評価するかで
返戻を両方参照するか、そのうちの判定文字列だけを印字出力などのために使うか
選択しているだけだよ。
>>326 sub com {
my ($mod, $zz, $num, $str) = @_;
$str .= $zz if 0 == $num % $mod;
$str ? ($num, $str) : $num
}
sub fizz {com(3, 'Fizz', @_)}
sub buzz {com(5, 'Buzz', @_)}
sub gizz {com(7, 'Gizz', @_)}
map {print gizz(buzz(fizz($_))) . "n"} qw(1 3 5 7 15 21 35 105);
ニヤニヤ
Perlは醜いラクダどころか白鳥だったのか
他の言語の立場がないな
天然?
いや、コピペミスw
多数値の返り値の、主値かそれ以外か、を使う手があるわけか
>scalarで評価するかlistで評価するか
そんなの認めるんなら、C++だと型キャストのオーバーロードがあるから楽勝じゃねーか。
operator const char*();
operator const int();
こんなんすりゃ良いんだろ?
ちなみに当たり前にオーバーロードがあるから、Fizz(3)とFizz(FizzBuzzObj)との区別もつくし。
C++ですら出来るんなら、この話もう終わりになっちまうじゃねーか。
しかし、ruby以外はズル、という結論にしたくて必死らしいが、
むしろrubyやJavaScriptがチートだろw
リフレクション使いまくってるしw
>>335 書け書け。だれもC++をけなしてないぞw
後出しじゃんは、なしね。
C++の
>>261がありなら
Haskellの
>>283もありだよな
ていうか、
>>325がズルと言ってるの理由がさっぱり分からん
演算子オーバーロードのある言語でそれ使って何が悪いの?
別にmapもできるぜ?
main = print $ map (fizz.buzz.gizz) [1,3,5,7,15,21,35,105]
340 :
339:2012/04/14(土) 05:12:10.70
まあいいや、関数合成のオーバーロードは無しで
>>312の言う通りHasAも隠蔽すれば良いんだな?
data HasA = HasA String Integer deriving Eq
instance Show HasA where
show (HasA s n) = if s == "" then show n else s
instance Num HasA where
(+) (HasA r m) (HasA s n) = HasA (r ++ s) (m + n)
(-) (HasA r m) (HasA s n) = HasA "" (m - n)
(*) (HasA r m) (HasA s n) = HasA "" (m * n)
negate (HasA s n) = HasA s (-n)
abs (HasA s n) = HasA s (abs n)
fromInteger n = HasA "" n
signum (HasA s n) = HasA s (signum n)
fizz (HasA s n) = HasA (s ++ if mod n 3 == 0 then "Fizz" else "") n
buzz (HasA s n) = HasA (s ++ if mod n 5 == 0 then "Buzz" else "") n
gizz (HasA s n) = HasA (s ++ if mod n 7 == 0 then "Gizz" else "") n
main = print $ map (gizz . buzz . fizz) [1,3,5,7,15,21,35,105]
F#で演算子オーバーロードなし。
let threadLocal = new System.Threading.ThreadLocal<_>()
let makeFizzBuzz name condition (x : obj) =
match x with
| :? int as number ->
threadLocal.Value <- number
if condition number then box name else box number
| :? string as names ->
box (if condition threadLocal.Value then names + name else names)
| _ -> failwith "ロジックエラー"
let fizz = makeFizzBuzz "Fizz" (fun x -> x % 3 = 0)
let buzz = makeFizzBuzz "Buzz" (fun x -> x % 5 = 0)
let gizz = makeFizzBuzz "Gizz" (fun x -> x % 7 = 0)
> [1; 3; 5; 7; 15; 21; 35; 105] |> List.map (fun x -> gizz(buzz(fizz x)));;
val it : obj list =
[1; "Fizz"; "Buzz"; "Gizz"; "FizzBuzz"; "FizzGizz"; "BuzzGizz"; "FizzBuzzGizz"]
さーて、また関数型言語が不利になるルールが追加されるよー
次は関数型言語使いがお題を出したらいいんじゃないか
Rubyじゃこんなの書けないだろ的なのを
スレタイの趣旨にも沿ってる
それ以前に「使える言語機能を恣意的に制限する」アホを
排除しておかないと比較にも議論にもなんねーんだよ
じゃあ、型的に間違ってるプログラムをコンパイルエラーにしてください、という問題はどうだろうか。
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))))
ループ禁止で再帰だけで書いてください、とかでも良いな
末尾再帰最適化の無い実装じゃスタックオーバーフロー
>>325 組み込みクラスを弄るのはOK
組み込み演算子を弄るのはNG
何故?
初学者といっても
1.プログラミングを学ぶことが目的
2.作りたいものがあって、その手段としてプログラミングが必要
で違う。
1なら関数型言語は良い選択
2ならオブジェクト指向言語やLLの方が早い
こういうスレの喧嘩は
1の人の多くは、プログラミングを座学として勉強しただけで実は何も作れない
2の人の多くは、作りたいものが動けばいいというだけでプログラミングに対する向上心がない
という現実を反映しているだけ。
そしてモマエは
3向上心のカタマリのオレ様にケンカうってんのかーーー
カワネーゾ
>>343 いまは人工的に作ったお題の信用がなくなってるんだよ
そこでまた中立でない人間がお題を出しても、紙屑のように無視されるんじゃないの
>>350 >>290や
>>325のような上から目線で変なルール押し付けてくるウザいヤツが
居なければ、言語ごとのアプローチの違いが見れて
遊びとしては面白いんだがなぁ
しかもウザいのに限って口だけでプログラム書けないんだ
あ、もしかして
>>290や
>>325がこのスレに書いたコード在る?だったら謝るけど
すまんけどちょっと確認させてください。これまで出てきた関数型言語の回答で、
関数合成演算子(あるいは関数)を定義が必須な場合でも、関数 fizz だけ用いた
fizz 1 や fizz 3 はちゃんと組み込み型の数値や文字列である 1 や "Fizz" を返せるのでしょうか?
これって一応要件だと思うんですよね。C++ の回答についても同様です。
Ruby や JS 、Smalltalk の回答はすべてこれが出来ているみたいなんだけど。
C++は型キャストをカスタマイズできるからそれで対応したら良いと思う。
FizzBuzzオブジェクトから文字列型と数値型へのキャストをそれぞれ用意すればよし。
>>352 今でも十分おもしろいと思うよ。せっそうのない動的言語(OOといえばOOだけど、
ストラウストラップの抽象データ型OOでなくて、ケイの動的OO寄りの考え方)では
可能だけど、理論的にきっちりした関数型言語では実現不可な境界がはっきりしてきてて。
出来ないと分かっていることを出来ないときちんと理由付きで示せる勇気も見れるし。
他方で、動的言語でもすんなりできるとは限らないから各言語での工夫の仕方も興味深い。
>>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"]]
あ、すいません。F#さんを見落としていました。
F#以外の関数型言語の回答で、ですね!
わざわざの検証、いたみいります。
スレッドローカルに状態を保持するのはいいアイデアですね。
いいアイデアですねw
>>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]]
>>353 ついでに
>>283もテスト
正しく動かなかったので修正
fizzT f s = (\x -> Left x) . fizzT'
where
fizzT' n | f n == 0 = Right s
fizzT' _ | otherwise = Right []
これで
>>360と同じコードが動いた
362 :
361:2012/04/14(土) 15:07:31.88
面白かったのは
>>283に
>>360を試して動かなかったとき
ちゃんとコンパイル時に型エラーになったこと
Haskellの型システムやるじゃん、みたいな
ねえねえ、1 から 3 までの fizz n の戻り値に対して、文字列なら全大文字化、整数なら 10 倍にして
map するコードを [1, 2, "Fizz"] に対して同じことをするコードとまったく同様に書いて
問題なく実行できるかどうか試しみててよ! クイズの要件をみたしていればできるよね!
もちろんいうまでもなく追加定義や修正は無しだよ。Ruby や F# のはもちろんできるよ!
364 :
340:2012/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:2012/04/14(土) 16:02:40.14
あ、ごめん
>>363だった
それはさておき、後だしでルール追加するの本当に好きだね
>>363 じゃあ、組み込みクラスをグローバルに汚染するのも禁止しようぜ
classbox等で一部に制限できるならアリ
というか、ここのHaskellerはどうしてこうも要求仕様を読み取れないくせに
あまつさえ勝手な解釈で適当なコード書いてドヤ顔なの? バカなの? 死ぬの?
>>367 誰もお前の頭の中なんて知らないし興味ないんだから
言わないと分からないっつーの
ここはお前の要求仕様を満たす場じゃねーし
馬鹿はお前
あと、まさかコードも書かずに議論参加してたとか無いよな
書いたコードのレス示せよ
俺は
>>340書いたぞ
(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)
>>367 > ドヤ顔なの?バカなの? 死ぬの?
w
いまどき、こんな台詞をわざわざ書くやつがいるんだww
勘違いしたふりして頓珍漢なコード出してきて、
言語や自分の発想の限界とかクリティカルなところはなんとか避けようとしているんだよ。
仕様を取り違えてるよってやんわりチェック方法をしめすと、
ルールを増やすな、後出しだ、仕様が欠陥だってなんやかやクレームつけて
相手が根負けして要求仕様のほうが変わるのを粘り強くじっと待つ戦略なんだ。
ある意味、賢いよ。
お題提出者の解答ってもう出てるの?
>>363 > map するコードを [1, 2, "Fizz"] に対して同じことをするコードとまったく同様に書いて
Haskellは静的型付けだから数と文字列を同じリストには入れられないんだ
そんなことも知らずに議論してたんじゃないよね?
>>371 >>368 > あと、まさかコードも書かずに議論参加してたとか無いよな
> 書いたコードのレス示せよ
って書いてるのに示さないってことは、まさか本当にコード書いてなかったの?
まさかの口だけ野郎説浮上www
>>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]
>> 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"]
◆QZaw55cn4c が出てきて有耶無耶になってるけど
「Javaドカタはコード書けない」説はまだ有効
◆QZaw55cn4c はドカタではないとでも
Haskellでコード書くだけで天才になれた気がした15の夜
敵はハスケラだけと思ってるところがウケるw
どんな言語使いから見ても口だけ野郎は最底辺のゴミだぞwww
おまえもなw
コード書けないドカタは「なでしこ」使えば良いんじゃないか?
運が良ければ日本語で書いた戯れ言が
実行されるかもしれないぞ
>>383 お前は詳しそうだな、その言語。
興味持って使ってみたのか?w
まだ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]]
F#、さすがだな。
>>385 可能なら、
gizz(buzz(fizz(105))) is "FizzBuzzGizz" となるようなヤツをお願いします。
>>387 理由を聞いても良い?
Pythonでは
>>385のほうがデコレータでも使えて良いんだけど……
@fizz
@buzz
def bizz(x):
if x % 11 == 0: return 'Bizz'
else: ''
静的型言語にIntを返したりStringを返したりする関数って縛りがそもそも無理
PerlとかSchemeの、多値をうまく使ったのが一番エレガントかな。
RubyとかJSは、同じようなコードをStringとNumberの両方に生やすとか、
見事に汚い解だw
関数を返す関数(カリー化されてりゃ普通)にケチがつくとか
スゲーなこのスレ
>>390 ちゃんと「など」って書いてるぞー
> オープンクラス機構やメソッドのない言語では関数(buzz(fizz(3)) #=> "Fizz" など)で。
それとも高階関数は関数じゃないんですかー
>>389 それだけじゃない。
継続の状態如何で関数に振る舞いを変えさせるとか
関数型には無理な事ばかり要求している。
悪意に満ちたクイズだ。
>>394 素直に考えれば、オープンクラスのある言語が良いという
意見に持っていきたい問題だからね
でも出てきた解はRubyが一番汚いという
>>389 型クラスとかってこういう時には使えないの?
要求による。
問題の「#=> "FizzBuzz"」が意味しているものが、REPLでそのように表示されるもの、
という意味なら、Show型クラスでいいんだけど、String型([Char]型)を要求してるなら無理。
静的型 vs 動的型スレ向きの問題だよね
>>391 いやあ俺は
>>341のF#(er)が一番エレガントだと思うぞ。
無茶な要求仕様も黙ってすべて満たしつつ、簡潔できれいなコード出してきてるし。
>>399 ThreadLocalが一番エレガントって
どういうセンスしてんだよ
401 :
デフォルトの名無しさん:2012/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))));}
>>368 >あと、まさかコードも書かずに議論参加してたとか無いよな
>>395 >でも出てきた解はRubyが一番汚いという
このスレの特徴まとめ
>>399 グローバル変数ではまずいと考えてThreadLocalにしたみたいに見える
まずいという認識がありながら、それを上に報告しないのはおかしい
結局、要求に対する不平不満は正直に言えばいいんだよ
コード書けないドカタとプログラマでは綺麗さの認識が違う
そうだね
お前のコードかけないドカタって概念がおかしいけどねw
>>405 あれ?まだこのスレに居たの?
派遣仕事で使い慣れたJavaを使って良いから
早くエレガントな解を出してくださいよwww
くやしいんだねw
仕事しろ。言語の勉強はするだけ無駄。
求められているのは動くアプリだ。
そもそも関数としての体をなしてないのだから、
副作用を使わずにこのクイズは解けない。
よって純粋な関数型パラダイムでは対応不可。終了。
Scalaならいろいろ駆使して書けそうだけどな
>>393 この場合の「など」は、関数呼び出しにもいろいろありますよね、
buzz(fizz(3)) 、 (buzz (fizz 3)) 、buzz fizz 3 など―とかの「など」だと思われ。
関数じゃないものを
関数型言語で作るには
どうしたらいいのだろうか?
>>409 副作用なしに解いたSchemeさんが涙目です
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"]
新ルール「カリー化禁止」
>>417 main { return ... } 部分をただのコードブロックとみせかけて
実は戻り値を変換しているという作戦だったのに、バレたか。
Smalltalkが流行らないように関数型メインは流行らないよ
ついに「流行らない」以外に縋るものがなくなっちゃったか
副作用ありとは言え、唯一まともな解出しててF#△だったのに
この期に及んで汚ないチートとかなにこのものすごい残尿感。
.NET発表時のHaskell.NETはどこに行ったんだよ?
マクロ使っていいならそもそも多値なんぞ使わんでも楽勝だろ。
FizzBuzzって流行ってるけど何が面白いの?
低能はFizzBuzzすら書けないという事実が面白い
オープンクラスとか副作用有り等の
汚いコードだけが「合格」www
勝手に判定してる(コード書けない)バカのセンスが露呈してますな
>>423 perl書いたのオレなんだけれどもさ、その通りなんだよな…
C#とかも関数型言語のエッセンスを取り入れるけど
すげえ無理矢理くさくて笑えるw
関数型がオブジェクト指向を取り入れるのはもっと自然なのに
オブジェクト指向っていうかC系列はもう駄目なんだと思う
守らなければならない資産がたくさんあるからな
そりゃ無理やりくさくもなるさ
後付で入れなきゃならなくなる時点で失敗だったはずなんだけどなぁ。
最近のC#の機能なんてC#以前から概念として存在してたはずなのに。
必要ないという当初の目論見は外れてるわけだ。
というか、資産っていうのはC風の構文そのものなんだよね・・・
C風じゃないとヤダヤダいう人が多すぎてD言語とかいちいち作られてる気がする。
C++、Java、C#、D言語
このへんは全て老害でしょ。
C#、D言語は設計に一貫した思想がないからアホっぽくなるのは仕方ない。
fizz 1 -- "1"
fizz 3 -- "Fizz"
buzz 5 -- "Buzz"
buzz fizz 15 -- "FizzBuzz"
だったらHaskellでも解ける?
可変長引数とかさーー
>>432 C#はどんどんダメな方向に向かってる気はするわー。
Javascriptは結構好きなのよん > C系文法族
>>431 後付で入れてもらったのがScala、Clojure、F#でしょ
なんで後付を悪く言うのかな
C#は言語設計に一貫性がなく節操のないところが最大の魅力
偉い人にはそれがわからんのです
>>440 アホか
それらは最初から関数型言語として作られてるでしょ。
関数型は糞、オブジェクト指向最高ってスタンスで作ってたはずのもんが
なんで今更関数型の要素を入れようとするんだよ。
>>439 オーバーライドした toString() を println() に暗黙に呼ばせるとかいう
使い古されたチートをキメ顔で出してこられても…。
new myInteger(3).fizz() が "Fizz" を返せるとか少しは挑戦しようよ。
「.Netファミリーに関数型言語入ったからC#でも使えるようにすっか!」
くらいのノリだろ。たぶん
dynamic型導入したときもそんな感じだったし
いやC#の場合は「C#で〜が出来ないと言わせない」という一貫した姿勢があると思う。
もともとJavaへの嫉妬から始まった言語だし。
>>442 手続き型言語がまずあって、
そこへOOの機能を取り入れた。
こんどはさらに関数型の機能も取り入れようとしているだけ。
C#厨ってVB.NETをVB厨のための言語って馬鹿にしてたけど
C#だってCっぽくないとヤダヤダっていう老害のために
無理矢理作ってるんだから全然人のこといえねーわ。
ラムダとかそんなに良いんならなんで最初から関数型言語使わないんだよw
>>442 > 関数型は糞、オブジェクト指向最高ってスタンスで作ってたはずのもんが
> なんで今更関数型の要素を入れようとするんだよ。
オブジェクト指向最高はそうかもしれないが、
関数型は糞なんて言ってないだろ。
現実世界における物質(オブジェクト)に対応づけやすい
自然な発想に基づくオブジェクト指向。
そこに便利な関数型を取り入れただけ。
りんごの方程式とは何か?を考えれば
オブジェクト指向と関数型の関係がわかるだろう。
C#作った奴らはvoidを型と思っていなかった。
だから、C#じゃクロージャ作るのに引数や戻り値にvoidがあると作れないw
やるには予めデリゲートを定義しなきゃならん。
クロージャを使うのを考えさせられる。
ありえん。手軽さが全然ない。
F#はローカル変数(厳密には違うが)を定義するのもクロージャを定義するのも同じ手間しかかからない。
クロージャをバンバン使っていけるのでクロージャの応用もどんどん閃ける。
F#やった方がC#が上手くなるという現実。
C#はやればやるほど馬鹿になる言語。
速度やメモリ・言語ごとの風習で最適かどうかは変わるのだろうけれど、
関数型でOOPをするときは、返り値として変更したオブジェクトを返すより、新たなオブジェクトを返したほうが関数型ぽいのかね?
関数型言語でWindowsアプリを開発したいっつー需要がどれだけあるかだな
>>442 どちらが糞でどちらが最高かなんて、問い詰められても答えなくていいと思うんだが
沈黙が正解って小学生でも知ってる奴は知ってるだろ
>>443 >>443 がんばってみたんですが、糸口がみえてきません。もしよろしければアドバイスをいただけないでしょうか。
>new myInteger(3).fizz() が "Fizz" を返せる
@ これは、「メソッド fizz() が副作用として "Fizz" を出力する」ということですか?
この場合、fizz(), buzz(), gizz() を通過してきて 3 でも 5 でも 7 でもわりきれなかった場合に元の数字を出力する、ということが不可能だと思います。
>>303 では妥協して endl() というメソッドを準備してこの処理を行うしかありませんでした。
A それとも「メソッド fizz() の返り値が String("fizz") であるべき」ということですか?
String にメソッド fizz() を追加したいのであれば、 String から新しいクラスmyString を継承して、そこにメソッドを定義するということだろうと思いますが、
(new myString(3).fizz() が myString("Fizz") を返す)
A-1 java.lang.String は final。
A-2 メソッド fizz() が "Fizz" を返してしまうと、もとの String("3") を忘れてしまい、buzz(), gizz() が処理できない。多値を返したいのですが
>>304 で精一杯。
>>304 の toString()#Object をオーバーライドする、ってこういうときには普通にすることだと思っていたんですが、何かまずい問題でもあるのでしょうか?
トイプログラムしか書かない奴は言語なんて何でもいいだろw
苦しいねぇ
>>454 > fizz() が "Fizz" を返してしまうと、もとの String("3") を忘れてしまい、buzz(), gizz() が処理できない
その一見回避不可能な問題を解決する方法を考えるのがこのクイズがクイズたるゆえんです。
言語によっては型システムの制約によりどうやっても実現できないこともあります。
>>450 関数型に限らず、GCのあるOOPLだと
属性変更をせずに新規オブジェクトをサクサク作るやり方も結構使うね
>>458 OOとPFの言語比較としてこのようなクイズを出したのは、
どのような観点からこれら両者のパラダイムの優劣を比較しようとしたのか
聞きたい
もうこのお題はcloseでいいんじゃないの?
このクイズではせっかくの労力を生産的でないことに費やしている
>>462 クイズなんかそんなもんだろ。しょせん暇つぶし。
つーか、こんな程度のクイズ解くのに「労力」なんか大仰なもん必要か?
このクイズのくだらなさはかなり問題。
くやしいのうw
全然くやしくないぜよ。perlでobjectのnew版も多値版もさらりと書いた。
tieとマクロ使ったのも書こうと思ったけれど手間がもったいなくなってやめた。
パラダイム比較としてもうすこし書く値打ちのあるテーマ出せよ、
このクイズじゃ再帰は使いどころないし
javaのnewだめ静的型システムダメ
何を有利に誘導したいんだか
せめて前スレのpermutationレベルのテーマを出題の下限レベルとしてクレヨ
467 :
466:2012/04/16(月) 02:18:35.03
大体fizz buzzってのが下らないんだよ
プログラムプロムナード、ナノピコ教室、Cマガ課題、オイラー4、AIアルゴリズム、OR最適化、
パーサ、マッチング、グラフ問題あたりの
小問題で再帰・高階/部分適用、遅延・カーリー化vsOOの比較できる題材が妥当かもな
step数は2chの1レスに収まるくらいの小問題でいいからサ
468 :
466:2012/04/16(月) 02:26:58.99
最悪、基本アルゴリズムの再実装でもいいや
たとえばqsortはperlやhaskellでpivotを適当に選択して再帰した短いコードと
pivot選択くどくど頑張ったCやjavaの長いコード比較してファンクショナルの再帰はマンセーみたいな
サイトがあちこちにあるだろ、
あのレベルでも今回のFizzBuzzGizzよりましだろ
469 :
466:2012/04/16(月) 02:35:35.13
あと、言い出しっぺの法則はナシだぞw
470 :
466:2012/04/16(月) 02:44:04.67
つか、OOとPFの単純比較って何か意味あるのか?
どのみち記述する言語の特徴または弱点、癖の比較レベルの議論に落ちがちな稀ガス
ズット前スレでヨンだが、意味論的にはOOとPFは相容れない物らしい
しかし生々しい実装レベルではいまんとこ清濁併せ呑んで実現するし
まあいいや寝るか。ノシ
多値使うアイデアはイケてたはずなのに、仕上げの文字列との結合やprintとの併用で
ズル呼ばわりされるわ、Rubyの
>>377の挙動も再現できなかったしで散々だったしね。
なぜか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:2012/04/16(月) 02:54:29.65
>>471 あれはね最初に書いたnewはだめって言われて仕方なくの面はあるのよ
$scalar = 関数(関数
と明示的にscalarで主値だけを受けとるように明示するのがホントは作法なんだ。
Rubyの
>>377に関しては読んでなかったから挙動の再現にそもそも着手してないよ。
rubyは文法がかなりカオスになって来ちゃって残念だね
474 :
466:2012/04/16(月) 02:59:22.51
fizzbuzzgizzはいいんだどうでも。
それより前スレのpermutaion perl版はwebなど参照せず一から考えて書いて
オレなりに結構な自信作だったのに
なんの反応もなかったことの方が寂しかったな
何このスレ
ruby無双をしたかった奴が、もっとエレガントな解を他言語で出されて、
涙目でdisるスレです
Rubyと違う解法が出る度に
必死に難癖付けてて笑ったわww
頭が固くて馬鹿だから
数や文字列に状態持たせる以外の方法が
理解できないんだろう
頭が固くて馬鹿だから
数や文字列に状態持たせる方法が
許容できないんだろう
世の中は状態がある世界なのにねw
じゃあFixnumのインスタンスに特異メソッド定義してみろRuby厨
元ネタのCLのEQLスペシャライザならそういうことできたよな。
Haskellとかでコンストラクタ無しで1以外の引数をとるとコンパイル時に
型エラーになる関数って定義できたっけ?
template< int n > void func(){int i="";}
template<> void func<1>(){}
・・・
func<2>();//エラー
> 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 に変えるとコンパイルエラー
>>474 あれ覚えてるよ、実は感心してた
ていうか、このスレでPerlの評価が結構変わったよ(もちろん高い方へ)
でも、読み易さ優先で書いてあれとは
Perl使いとは分かり合えないな...と思ったけどw
>>479 許容はしてるだろう
エレガントさから程遠いと言ってるだけで
俺の基準における
エレガントってやつかw
488 :
285:2012/04/17(火) 00:46:48.85
正直、あの問題は無いと思うよ
問題があれだし書き捨てだからやったが、実際には絶対にやりたくないな
>>487 FizzBuzzすら書けない口だけ野郎の基準よりマシだろwww
お前はこのスレでは最底辺のカスなんだから敬語使えw
>>481 ぶっちゃけ
>>479のバカが理解できたのが
たまたまRubyのコードだっただけでRuby厨ですらねーと思うぜ
むしろバカにクソコード褒められてRuby可哀想ってなもんだ
あの問題出したのぶっちゃけPython使いだと思う(陰謀説)
492 :
466:2012/04/17(火) 01:35:17.45
>>491 アレは学部・卒研レベルの課題をここに投げたのかなーと
オレは感じた。(真相はシラネ)
もしかしてオレ様はボクちゃんに利用されたのかなとww
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'.
>>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"
っていうか問題どこだよ
スレタイに惹かれて開いたけどゴミスレだった・・・
$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";
同じく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 「数値と文字列の組」と「数値または文字列」の違いが不明瞭だった。
リフレクションや継承で二つのクラスを一組にしたいのか、
それとも一つのクラスを数種類に分けたいのか明示されていなかった。
どうしてもスレッドローカル変数が必要になったとき
関数的にはどう記述したらいいのかよかったら教えてください。
そもそもスレッド自体が処理系に依存した、言語パラダイムとは関係ない概念だから、
関数型的にもオブジェクト指向的にも、どう記述したらいいかとか答えようがない。
Readerモナドでグローバル変数っぽいことをするには
どうすればいいのでしょうか。たとえば、状態をfizzとかbuzzから
(引数として渡すことなしに)参照したり更新したりしたいのです。
個人的に、関数型でスレッドとかハードに近い領域の制御はしたくないな。
>>504 それは基本的にStateモナドの領域。
Readerモナドの中で、さらにサブルーチン的に他のReaderモナドを呼び出す時に、
一時的に書き換えたように見せかけたい、っていう場合ならばlocal関数が使えるけど。
Readerモナドで更新したいって、読み取り専用変数に書き込みたいって言ってるのと同じ事なのはわかってるよな…?
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)
>>500 あるときは a
またあるときは m a
m a -> (a -> m b) -> m b
なんつーか、FizzBuzzしたいんならHQ9F+使えばいんじゃね?
お題出していい?
・コンソール上で動く、カード(つーてもただの数字を表示するだけだが)を使ったミニゲーム
・1〜9のカードを各4枚ずつ用意、それをシャッフルして「ストック」とする
・ストックから7枚のカードを引く
・引いたカードの中から、プレイヤーは合計が15になるように数枚を選んで捨てる
(選ばせ方はプログラマが考える、ギブアップ手段も用意)
・捨てなかったカードと合わせて再び7枚になるか、もしくはストックが空になるまでストックからカードを引く
・また15になるように捨てる
・引いては捨ててを繰り返し、ストックと手札が共に空になったらおめでとう的な言葉を吐いて終了
つまらない。
>>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: 'おめでとう!'
>>514 なぜこの人は今どきSmalltalkの末裔を使っているのか理由をうかがいたいので
おしえてくださいです
# 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 !'
>>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 "おめでとう!"
Squeakは入れたことあるが(てか今も入ってるけど)何をどうしたらいいのか判らん
>>514 のコードをどこに入力して、どう実行したら動くんだ?
>>518 1.
http://sourceforge.jp/projects/squeak-ja/ から 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以降であれば動作するようです。
ただし公式英語版などでは日本語が化けますので適宜英語などに置き換えてからペーストしてください。
日本語版であってもペースト時にエラーがでるようならそのときの対処も同様です。
// 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 []
>>519 ありがと。何か前に入れたバージョンでやってみたら「[ | input |」の行の左に「Period or right bracket expected ->」とか出たけど、実行の仕方自体は判ったから色々試してみる。
ああ、インデントを一旦削って入れ直したら動いたわ。thx
あ、動的にいたスモールトーカーだ。よろしく!
日本語でおk
お題:
コンウェイのライフゲームで、
配列の配列(あるいはリストのリスト)で表わされた格子を受け取り
次世代を返す関数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世代目を算出するのにかかった時間(無理なら、算出可能な
世代数とその時間)を計測して示せ。
くだらん
Java8でラムダ式が言語仕様に入るようだね
javaもマルチパラダイム化が進むな
OOPLが関数型言語の特徴の一部を取り込む中
スレタイの通り言語比較した場合
「副作用の有無」が一番重要なんじゃないかと思ったけどどうだろう?
機能を取り込むことはあっても無くすことはしないだろうから
副作用の有無が、開発速度や可読性、保守性にどのように影響してくるか・・・
と考えても良いお題は思いつかないんだけどね
Javaって今でも組み込み型以外は参照型でしか扱えないの?
関数型言語使うようになってから、nullを持たない参照型とか、イミュータブルな値型がいかに重要か思い知った。
しかも、イミュータブルな値型を基本として、nullを持った参照オブジェクト型、nullを持たない参照オブジェクト型って形で扱えないと厳しい。
これは言語仕様として取り込まれていないとどうしようもない。
そういう意味では、C++は結構惜しいところまで行ってたと思う。
C++にはpure virtual function callというのがあって、仮想関数がnullを持つ。
値型でも仮想関数があったら元も子もない。
仮想関数をやめてswitchを使う覚悟がないと厳しい。
関数型言語のパターンマッチはswitchと同じ方式だ。
>>528 関数型言語はむしろ全てが参照型とも言えるんだが
>>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) "
>>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) } }
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: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
(_, _) (`mod` 2) (\x _ ->
最近Lispさんを見かけないけどもう廃れちゃったの?
言語仕様を共通にするというトレンドは終わった
個別の実装は始まってなかった
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)
}
>>536 2chで世間が判った気になり始めたら色々ヤバイな。
>>538 500x500 500世代で測ったら 1.8GHz Core i7 で 68秒だった。けっこう速いね。
ライフゲームで関数型とオブジェクト指向の何を比較したいんだろう?
>>525は次世代を返す関数としてるけどオブジェクト指向側は
lg = new lifegame(500,500);
for(i=0;i<500;i++)lg.life();
console(lg);
って感じでいいの?
そうしないと関数型 vs 手続き型みたいなことになるよね
例えばF#とC#を比較したら関数型言語と手続き型言語の比較になる
本物のOOは言語に依存しない
関数型言語と対立するようなOOは偽物
>>541 ライフゲームは単純だけどパラダイムの特徴をかろうじて出せるくらいの規模はあるんじゃない?
お題にあるlifeという関数名(メソッド名)にこだわらなくていいと思うよ。
要は小さな例での正常動作と、500x500セル 500世代(必要なら50世代とかに軽減して)
にどのくらいかかるかが示せていればOKかと。
>>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
javascriptで書いてみた。破壊的操作有りで。
ソースの長さ汚さは勘弁してください。
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
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)
手続き型言語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
OOPならセルごとにオブジェクトで、と思ったが、
仕様が全状態の配列から配列への変換なのね。
>>549 べつにこだわらなくてもいいでしょ。組みやすいように組めば。
要は小さな例での動作確認出力結果と、
500x500セル 500世代(必要なら50世代とかに軽減して)の計測結果を示せればOK。
まあ出題者が関数的なアタマなんだろう
セルごとにオブジェクトとかねぇよww
問題領域がどこかわかれば何処をオブジェクトにしたら良いか分かるよ
なかなか面白いじゃないか。
オブジェクト指向で設計されたライフゲーム、頼む。
この題じゃ
>>541くらいにしかならんだろ
オブジェクト指向をどういうもんだと思ってんだよw
セル毎にオブジェクトか、面白そうだしちょっとやってみるかな
セル毎にオブジェクトってこんなの?(コードは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
全部は長いのでこっち
http://ideone.com/3WKkG
8coreのXeonマシンでOpenMP使ってCのコードを並列化したら
500*500の500世代で1秒切ったわw
>>557 他スレで遊んでる内に作られてしまった…
やっぱりオブジェクト指向だと規模が大きくなる。
逆に言えば、規模が大きい場合は
オブジェクト指向が有利ってことか。
大規模で全貌の把握がしづらいものを
個々人では把握できないままでも比較的扱いやすいのがOOPLだと思ってる
全体を統一しづらい規模になると言語は一つではなくなる
Objective-C++/CLIのような状態
>セルがオブジェクトなら
>実際の生物みたく、オブジェクトごとに能力を変えることだって出来る
大抵のOOPLにはマルチメソッドすらないのに、
良くそんな大口たたけるな。
無いのはマルチメソッドを実現するための言語仕様であって、
マルチメソッド自体は実装できるからね。
>>564 突然何言い出してんのこの子(´・ω・`)
ホーミングミサイルの話でボコボコにされたやつだ。
気にすんな
>>565 関数型言語でも実装できる
パラダイムじゃなく言語間の比較スレなんだから
そんなこと言っても意味ない
>>561 仮に「OOPだと規模が大きくなる」が真だとしても
そこから「規模が大きいとOOPは有利」は導けない
静的型付けの割に簡潔に書けて、かつ型チェックも厳しくやってほしい
こういうニーズに関数型言語が応えてるから使ってるだけで、
関数型言語使ってる奴が皆OOを嫌ってるわけでも
設計レベルで使わないわけでもないんよ
争いは不毛だ
> 静的型付けの割に簡潔に書けて、かつ型チェックも厳しくやってほしい
なんとなくC#を思いだしたけどC#で書く人いないね
争わなかったらスレの存在意義がないだろ
>>571 C#のジェネリックってダックタイピングできないんでしょ?簡潔かなぁ。
>>560 ライフゲームのセルっていう文脈だからねぇよって言ったわけで
ゲームのキャラクターのオブジェクト化まで否定はしてねぇよw
>>564 またホーミングの子www
>>570 Scalaがそう。
静的言語で、簡潔に書けることを
証明した言語。
>>575 このスレでまだ一回もScala出て来てないぞ
ライフゲームで良いからコードで証明してみてくれ
「Scalaは簡潔に書けると証明した」=>「じゃあチョット書いてみて」=> 逃亡
どんなコントだよwww
ん? Scala知らないの?
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}} "
純粋な関数型言語って、参照するたびに値が変化する変数みたいなのは作れるの?
たとえば乱数とか、参照した時点の現在時刻を値として持ってる変数とか
>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の機能を余り活用できていない感じ。
これで静的型付け言語なんだぜ。
val msg = if (true) "true dayo" else "false dayo"
せっかくなのですべてのセルが並行に動くように>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の分割が不要になったので少し短くなったか
これで静的型付け言語なのか。
本当に短いコードは動的型付け言語だけの特権じゃないことを
証明してしまったな。
ただ静的型にしては遅いよね。
500x500 500世代で動的な
>>579 が 112秒なのに、
>>581 は 196秒。
>>583 これって一回のlifeのコール後、
すべてのセルがアップデートを終えるのをどこで待ち合わせているの?
>>582 そんなんで感動できるとか何時の時代の人?
OCaml : let msg = if true then "true" else "false"
Haskell : let msg = if True then "true" else "false"
どうせ、RubyとかLLばっかり使ってる人だろw
C++,C#にも導入されたね
C++11 : auto msg = true ? "true dayo" : "false dayo";
C#(3.0) : var msg = true ? "true dayo" : "false dayo";
最近どんどん動的型付け言語の
メリットがなくなっていくね。
>>591 この戦いが終わったら全ての武器のメリットがなくなるんだ
機械語のメリットがなくなってゆくね、とか言ってる奴の同類だよなぁw
でも静的型はコンパイルが必要でREPLももっさり、型推論も万能じゃない
スクリプト言語はこれからも残るよ
trueって名前の変数を作って、遅延評価によってmsgを参照したときの変数trueの値によりmsgの値も変わるってことでいいんかの
変数trueに再代入できたりしないとあんま意味なくね?
いや違ってたらすまんが
>>590は型推論の話じゃないの?
"true dayo"も"false dayo"も文字列リテラルなので
三項演算の条件のtrue/falseを問うことなくmsgの型を文字列と確定できる
>>597 ああなんだそういうことか、勘違いしてたわ
変数に互換性がない別の型の値を
再代入できる言語はクソです。
>>586 Scalaって事前(?)にコンパイルする以外になんか実行方法あったっけ?
コンパイルしない場合は、そのまま動きます。
>581はscalaスクリプトだから、コンパイルする場合は
-Xscript XXX オプションをつける必要があるかと
動くね
$ 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 シングルコア
>>599 それで、代入を禁止するのと共用体を禁止するのは、どっちが良いんですか
スクリプト実行
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
コンパイル時間の分、スクリプト実行だと起動に時間がかかるね
>>597 よく見れ。
msgにtrueを代入してる。
>>608 どのtrueを代入してるんですか?
全文を引用して、該当のtrueを【】でくくって下さい。
>>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スクリプトなんてモードがあるんですね。
実行オプションでそんなに差が出るものなんですか?
Javaの実行環境に詳しくないとまともにベンチとれないんじゃないかと思う
>>608 $ cat hello.cs
class Program {
public static void Main() {
var hoge = true ? "*true*" : "*false*";
System.Console.WriteLine(hoge); } }
$ mono hello.exe
*true*
括弧を省略する言語は危険
式と文を区別しない言語も危険
Lisp系から見るとHaskellも括弧省略言語だな
λ式に比べたらLispだって
>>616 Lispの関数は
apply = foldl ($)
(((f x) y) z) == (apply f) [x, y, z]
省略ではなく、式を変形している
(x, y, zの型が異なる場合、Haskellは上の式が間違っていると主張する)
>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。
まだまだ遅いけど。
>>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) }
}
やっぱり手続き型のC言語が
こういうのは一番早いね。
つまりCの関数を簡単に呼べる言語が優秀
なんだ。Rubyが最強ってことか。
>>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)))
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]]
速度が必要な極一部の処理だけ
速い言語(C/C++/Java)で書けば良いのに
クソ遅い言語で速度競っててワロタwww
なんだJava厨か
Ruby「実行速度とかそんなの求めてませんから(キリッ」
関数型言語で書くとどうしてもボトムアップになる,
そこが問題,
小さい処理ならそれでいいが,大きなシステムだとはなしにならん
関数型言語はトップダウンでもボトムアップでも組む事が出来る
出来ないのはそいつが未熟なだけ
>>630 自分は逆に関数型言語でトップダウンだが・・・
入れ子になった関数を変更するときぐらいだな。ボトムアップな感じになるのは
マクロな関数(処理)から書き始め、マクロな関数から呼ばれる
ミクロな関数は入出力の型だけ決めて実装は後回し
なんでこんな簡単なことが
>>630には出来ないの?
トップダウンはどうしても車輪の再発明になる
再利用はどうしてもボトムアップになる
え?
>>634 実感として、トップダウンとボトムアップの出会うところでうんうんうなっています。
>>634 ボディを違う色で塗って「ニューモデル」っていうだけだろ
638 :
デフォルトの名無しさん:2012/05/01(火) 19:35:01.49
simonpj先生の勤務先都合仕事だからだまされないで!
騙されるも何も、内容は事実じゃん。
スプレッドシート猿によるアホな決定というリスクマネジメントのための学会?
現実には使えないExcelの拡張の話だけどなw
拡張せずとも、普通に計算するだけで関数型だろ?
何言ってんだ?
A1=3
A2=A1-32
A3=A2*5/9
これは静的単一代入 (SSA) です。
SSAは関数型に入りますか?
y = x + 5 は一次関数。あとは説明要らんよな。
そもそも、型に入るとか入らないとかいう型の理論が要らない
型がないと、実行時にしかメソッド名の解決ができない。
これは開発工数が伸びる原因になる。
なんという緻密な分析
関数"型"の話してんだろコミュ障
型だよ型。
型の話しようぜ。
653 :
uy:2012/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
ぶっちゃけ関数型もオブジェクト指向もどうでも良くて
自分が使ってる言語以外をdisりたいだけだよね
>>653 まだpermutationやってんのかよ、こんなもんがそんな面白いか?
perm [] = [[]]
perm xs = [x:y | x <- xs, y <- perm $ filter (/=x) xs]
main = print $ perm [1,2,3]
こっちは要素の重複を取り除かないバージョン
import Data.List
perm' [] = [[]]
perm' xs = [x:y | x <- xs, y <- perm $ delete x xs]
657 :
uy:2012/05/02(水) 13:23:15.71
>>655 Rubyのpermutationって誰も知らないのか話題にならないから俺が最初に2chにコード投下したやつじゃん(半年前くらいに)
67の冗長ゴミカスRubyソースコードを添削しただけだよ
へえー、これ良いね。
>>658 いやHaskellでもRubyでも標準添付や組み込みのライブラリに入ってますし…
>>655 要素の重複を取り除くところでバグるかもしれない点は面白い
>>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)) "
>>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
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})))
未だに関数型言語の機能が欲しいと思ったことがない。
俺みたいな奴は案外多いんじゃないかね。
そんなことよりトランザクショナルメモリはよ。
欲しいと思う機能はそれほど多くない
だが変な機能をゴリ押しされるとそれに対抗するものが欲しくなる
ゴリ押しを断るために、先約があるとかいって他のを抜擢するみたいな話は案外多い
うむ。関数型言語というより
コレクションライブラリがあれば
十分だったりするw
Guavaおすすめ
ム板の関数型言語派の大半は「関数型言語派」ではなく「型推論派」だろ
スレタイが無知だな。
手続型 vs 関数型
構造化設計 vs オブジェクト指向設計
>666
メタプログラミングなんてどう?
LISPのように構文を犠牲にしないMPといえば、OO系が主流だろう。
コレクションにもpush型とpull型があって
push型は一昔前のOO
pull型は遅延評価できるので関数型に近い印象がある
最近はpull型も普及したので、まだ売れ残っている型推論の方が関数型らしく見える
メタプログラミングは、共通のVMまたはC言語の上に好きな言語を乗せるのが主流
メタオブジェクトプロトコルみたいな話は最近どうなったのか
>>671 一昔前がよくわからないのでpull型とpush型の違いがよくわからんです
>>673 getterを呼び出したり成功か失敗か調べたりするのがpull型
getter反対派はpush型
言語はなんでもいいので具体例をプリーズ。
pushとかpullなんて名前は知らないけどこんな感じなんじゃね?
サンプルはJava。上がきっとpushで下がpull
http://www.akirakoyasu.net/2011/01/15/218/ 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);
}
});
いまさらだけど、
>>671の
pullとpushの言葉の使い方逆じゃね?
>>677 放置したほうがいい人だと思うがどうか?
"Push-Pull Functional Reactive Programming"風に、
pull: demand driven
push: data driven
ってことでいいかと。
言葉のままに捉えればよいんじゃない?
pullは引く。
result = hoge( piyo( huga() ) );
pushは押す。
huga( result );
piyo( result );
hoge( result );
>>678 遅延評価はdemand drivenだから、671は合ってるだろ
一箇所だけ取り上げてそんな事言われても困りますよ。
>>677は0箇所ですよ
0箇所よりも1箇所の方がいいんじゃないか
pullとかpushって
>>671が作った言葉だろ?
手続きタイプと、コールバックタイプとかでいいんじゃね?
なんだ、オレオレ用語かよ
>>682 まあそりゃそうだねw
push/pullは、上に上げたようにFRPでも取り上げられてるし、
他にはWebアプリフレームワークとかXML系APIとか、
いろいろなところでAPIデザインの選択肢として語られてる。
大げさに騒ぐような概念じゃないけど。
http://ja.wikipedia.org/wiki繊維強化プラスチック 繊維強化プラスチック(せんいきょうかプラスチック、Fiber Reinforced Plastics、FRP)は、
ガラス繊維などの繊維をプラスチックの中に入れて強度を向上させた複合材料のこと。
単に FRP と書いて、ガラス繊維強化プラスチックを指すことも多いが、
ガラス繊維であることを明示したい場合は GFRP または
GRP (Glass fiber reinforced plastics, Glass-reinforced plastics) と書かれる。
でも、FRP自体は明らかに関係ない概念だよね?
pullとpushの概念引っ張ってくるためだとしても。
それに、Getter/SetterをPull or Pushに分類しようとするのは
独自解釈が過ぎるでしょ
>>671 はオレオレ定義すぎ。
>>676 の下がpush。上はシラネ。
だろ。普通にpull/pushを考えるなら。
>>688 > でも、FRP自体は明らかに関係ない概念だよね?
ちょっと難しい例でごめんね。
>>691 難しい例もなにも、普通にFRP関係ない例しかでてないぞ。
関係あるんなら関係ある例になるコードをださんと。
>>688 つまり、まず質問をして、独自ではない回答が出るまで待っていればいいんですかね
関数型言語がgetterの使用を制限しない理由は何でしょうか
関数型ってパターンマッチとか、再帰とか、モナドとか、そんな程度のものなの?
もっとすごい秘密兵器があるんじゃないかなぁと期待しているんだけど、イマイチ見えてきません。
型クラスのメリットは、クラスを使った不完全な抽象データ型オブジェクト指向より
定式化され優れているとわかるとしても、両者は必ずしも背反するものではないですよね?
参照透明性にしても抽象度やモジュラリティは上げられる反面、直感的でない回りくどい処理や
そのための記述を強いられたりする局面も少なからずあるし、そうしたやり難さと引き換えに
関数型でゴリ押しするメリットってどこら辺にあるのでしょうか?
高階プログラミングではないかと昨夜から今朝にかけて思った。
いわゆるメタプログラミングや自己反映計算を実現する方法として、
自己書き換え→テンプレやマクロ→...というように発展してきて、
関数合成とかでプログラミングをするようになった、というか。
関数合成はメタプログラミングに入りますか?
>>694 代入を制限する関数型が、get/setの両方を制限するオブジェクト指向よりも回りくどい
と言われるのは何故ですか?
Smalltalkが普及しなかったようにHaskellは普及しない
「get/setの両方を制限」のところがよくわからないので具体的にお願いします。
あとなんでその「get/setの両方を制限」が関数型の再代入制限に対応すると
思われたのでしょうか?
こうかいかんすう
高階関数って関数オブジェクトがファーストクラスなら
どうということなく使えますよね。それでもやっぱり
関数型の秘密兵器なんでしょうか?
カリー化が自動だったり関数合成演算子が組み込みなのは嬉しいけど、
OOPLであっても関数オブジェクトがそうであればいいだけって気もしますし、
ポイントフリースタイルで書こうとしてパズルみたいになるのも
何だか本末転倒な感も否めません。
OOPLでもできるって
頑固なOOPLのスタイルを変えさせることができるなら凄い兵器だ
頑固なOOPLのスタイルってどんなの?
>>701 別に秘密兵器でも何でもなく、関数型の思想のうち
手続き型でも適用出来そうな部分は既に受け入れられてるってことさ
>>694 「ゴリ押しする」ってのは、あなたの心の問題じゃないの?
関数型の主力は副作用が無いこと
手続き型の主力は副作用が有ること
OOPは副作用の局所化を目指すもの
異論は認める
副作用があるのはsetterだけ
getterの局所化には副作用以外の目的があるだろう
そうかしら?
>>707 一体いつからgetterに副作用が無いと錯覚していた?
getで内部キャッシュを生成,保持しても良く
副作用は外から分からずとも、仕様(期待)通り動作すればいい
しかし実際にはオブジェクトが他のオブジェクトの参照を握ってたりして、
一回のメソッド呼び出しがどんどんたらい回しされてって。
特にオブジェクト指向では多態のためにメソッドのシグネチャを固定化するから、
オブジェクトが他のオブジェクトの参照を握る傾向は強い。
つまり、オブジェクト指向で副作用の局所化はされないし、元々狙っても無い。
オブジェクト指向はオブジェクトに関するコードや変数の依存関係を纏めたってだけ。
これを手続き型で実行すれば、処理がオブジェクトを跨いであちこちに飛び回る。
このとき、副作用は局所化されない。
副作用の局所化するためには、処理がオブジェクトを跨がないように
する必要がある。
しかし、それはオブジェクト指向とは関係無く、手続き型一般における、設計のテクニックだ。
・シグネチャを固定化 → 他のオブジェクトの参照を握る
・副作用の局所化するため → 跨がないように
この辺前後の関連がよく分からないので詳しくお願いします
どう言えばよいんだろうね。
オブジェクト指向はオブジェクト単位で色々纏めるが、これらは変数やコードといった、
静的な要素を分類したに過ぎない。
言い換えれば、「ソースコード」をオブジェクト単位で分類したに過ぎない。
一方で副作用はソースコード上には現れない。
実行時に「処理」にくっ付いて現れる。
だから、副作用を局所化するためには、処理の流れそのものを
局所化する必要があって、これは手続き型一般の設計の問題で、
OOだからどうこうという話ではない。
OOはあくまでソースコードをオブジェクト単位で局所化するだけで、
それ以上は助けてくれない。
>>709 それはgetterを作って良いし副作用が有って良いという意見だな
そういう自由な考え方が定着すれば、OOに反対する人はいなくなると思う
そんでついでに言うと、
オブジェクト指向は処理の流れに関して凄く無頓着な一面がある。
というのも、仮想関数だ多態だといってな。
そんで、むしろソースコードみたいな静的なものは怖くねーよ、
こんなの綺麗に分類するより、
処理の流れとその副作用の方がよほど怖えーよ、そっち整理しろよ、
って考え方もあって、OOは使いどころが難しく、2chなんかで議論もこじれる。
だから皆だんだん嫌になってきて、
処理の流れそのものを気にしなくて良い関数型に白羽の矢が立ったってわけ。
俺にとっての副作用を局所化というのは
「この変数を触るのはこの処理だけ」といった
スコープを小さくしたり責任範囲の壁を作ったりすることなんだけど
>>712にとっての副作用の局所化というのは
何かのメソッド呼んだときに変化するN個のオブジェクトのN個の変数とか
その辺りに言及してるのかな?
メソッドの中で自身(A)が持ってる別のオブジェクト(B)のメソッドを呼んだとして
そこから先でファイルアクセスが発生しようと
それはBの範疇なのでAの中での局所化には関係無い
というスタンスかな、俺はね
>処理の流れに関して凄く無頓着
そうかもね
他のオブジェクトは外面(インターフェイスと仕様)しか見ないので
処理の内容は「あとは任せた」って感じだし
>>715 これは物凄く悪い例なんだけど、
AがBのメソッドを呼び出して、
そのメソッドの中でBがAのメソッドを呼び出したら、
カプセル化は壊れるんだよね。
そんな設計はするな、と言われそうだが、
これが結構良くあるんよ。
親が子の参照を持ってて、子も親への参照を持ってるとか。
循環参照は注意だが、カプセル化は別に崩れてなくね?
カプセル化は言葉が悪かった。
整合性だね。
AがcallするならBはreturnすればいいのに、なぜかBもcallしようとするんだな
なぜreturnを避ける設計をしてしまうのか
>719 てめぇ、CPSさんDisってんのか?
>>716 >これが結構良くあるんよ。
わかる・・・
イベントハンドラとかのインターフェイスの実体として子に自身を渡すとか
木構造で高速化のためAが別のA(親)を持つとかは許容出来るけど
一つずつ順にコンパイル出来ないような定義レベルでの循環参照は俺も嫌い
>>720 末尾呼出しなら問題なさそうだ
問題は、Aのメソッドの途中でAが参照されること
>>718 言葉が悪いんじゃない。関係ないんだよ。
それぞれのオブジェクトがメッセージを投げ合い、
その結果でたらめな順序で副作用が起こっても問題が無い
仮に問題あっても例外投げときゃ無問題
そういうイイカゲンなシステム開発にオブジェクト指向は最適
さすがにそこまでいい加減なシステムは品質を確保できないだろ。バカにし過ぎ。
「そのように組むことができる」ことと「実際にそうする」は別問題。
Haskellでも副作用が発生する処理と、そうでない処理をごちゃ混ぜにすることは可能は可能だし。
ここの人らなら詳しそうだから教えてくれ。
0 :: Integer
0 = 0
みたいな感じで、数値を関数化できる言語ってないの?
0関数にラムダ与えたら、ラムダの実行を無視して、
0以外の数値関数にラムダ与えたらラムダを実行するようにしたい
は?
関数なら 'a -> 'b みたいな型を持ってるはずだけど。
Integer という型は整数の型であって、関数じゃないよ。
別にそこの式は、数値を関数化したいって例であって
関数を返すとかとは関係ないよ
「数値を関数化」ってのが、たとえば「文字列を虚数化」みたいに意味不明。
むしろ、
> 0関数にラムダ与えたら、ラムダの実行を無視して、
> 0以外の数値関数にラムダ与えたらラムダを実行するようにしたい
こっちをソースコードで表現できたら、少しはなんとかなるかもしれない。
あ゛?チャーチ数ディスってんのかメーン
>>727 「0」というシンボルと、何らかの関数を結び付けたいということ?
関数型ならそもそも、既に何かに結び付けられてるシンボルに
別の値を結び付けるのは再代入そのものだろうし
手続き型関数型問わず、特定リテラルの意味だけを変更するのはちとマズくないかな
common lispに変数としての値と関数としての値を区別するということなのか
ごめん、脱字した。
common lisp(のよう)に変数としての値と関数としての値を区別するということなのか
>>732 Smalltalkなら実現してたべ
value := 0.
value message.
こんな感じで、数値にメッセージを送ると、
数値に紐付いたメソッドを呼ぶ事ができた。
1にメッセージを送れば、1のメソッド。
2にメッセージを送れば、2のメソッドみたいにね。
本のお題がどういうものだが今一歩ピンとこないが、
チャーチ数を計算する型なしラムダ式処理系なら結構転がってる。
数値や真理値は短形表示できるが。
>>735 何が言いたいのか分からん
value message と function value は語順が違うだけじゃね?
>>737 Smalltalkが解らないとなるとlispなら解るかい
(0 arg) 0関数を実行
(1 arg) 1関数を実行
別バージョン
( (lambda ( x arg ) ( x arg ) ) 0 arg ) 0関数を実行
( (lambda ( x arg ) ( x arg ) ) 1 arg ) 1関数を実行
>>738 なるほど分かった
0や1といったリテラルに関数を割り当てたいってことだね
どっちかというと関数型 vs. オブジェクト指向じゃなくて
静的型 vs. 動的型になりそうな気配
ところで
>>727のいう「ラムダ」の引数は何?
それは何時渡すの?
>>740 値が関数だって事の説明用だから引数はなんでもいいんですが
>>741 意味論的には関数型言語の値は「ゼロ引数関数」という関数
いずれにしろ 0 :: Integer では、関数になってないから
OO信者の俺ですら数値クラスにメソッド追加するような
コードは勘弁して頂きたい
オープンクラスではしゃぐのは初心者時代で終わらせてほしい
>>735>>738 シングルディスパッチでは第一引数を特別扱いしてるだけで
x.foo y z と foo x y z に本質的な差は無い
シングルディスパッチ脳には理解出来ないかもしれんけど
難しい問題だね。
func( o1, o2 )
こういった関数は後からいくらでも追加できるけど、
o1.func( o2 )
との本質的な違いはスコープだけだからな。
多態出来る出来ないの違いは有るけど、それは言語上の制約ってだけだからね。
クラスの外のスコープにいくらでも関数が定義できるのに、
クラスの中のスコープにメソッドを追加することは出来ません、
って制約に一体どれほどの意味があるかって言われると、ねぇ。
特に動的言語では。
あんたの恣意的な分類で「本質」とか「言語上の制約ってだけ」とか言われても
わかりませんわ。
別に恣意的ではないと思うけど。
本来、どこのスコープに何を追加しようが勝手なものなんじゃないの?
静的言語では実行効率の理由で制限がかかってくるのも分かるけどさ。
0がどうのこうのの話は、まだ続いてたの?
0と1は同じ型だろうから、同じ関数にディスパッチされるのが当たり前だしさ。
このスレには時代遅れのSmalltalkを使ってる
奇特な人が居るから質問するんだけど、
あのIDEモドキを立ち上げずにプログラム実行する方法無いの?
それと動的型付けで実行が遅いから、せめてボトルネックだけでも
C/C++で書いて実行できないとトイプログラムでしか
使いモノにならないと思うけど、簡単にC/C++のライブラリとリンクできるの?
たとえばVisualWorksやPharoといったSmalltalk処理系には
headlessといって、サーバーなどの用途に使う目的でIDE抜きで起動したり、
その際に指定した.stファイルを読み込んだり実行できる機能があります。
またGNU Smalltalkのように、標準入出力から使うことに特化して開発された
特殊な処理系もあるのでこういう処理系を最初から選ぶのもよいでしょう。
ただIDE抜きの使い方は他の言語と同様の使い方ができるというメリットがあると反面、
Smalltalkの独自の機能や優位性をかなりスポイルする使い方ということにもなるので
他の言語が選択できる状況であるならば、よほどSmalltalkを使い慣れた人でもなければ
そこまでしてSmalltalkを使うメリットはあまりないような気もします。
GNU SmalltalkやAmber Smalltalkといった特殊なSmalltalk処理系を使っての
Smalltalk入門があまり推奨されないのも同様の理由です。
SmalltalkからC/C++で書いた関数をコールするにはいくつか方法がありますが、
たとえば、商用のSmalltalkであるVisualWorksにはDLL and C Connectという方法が使えます。
http://www.cincomsmalltalk.com/pdf/DLLandCConnectGuide.pdf PharoやSqueakではVMプラグインを書いてバイトコードを拡張したり、FFIが使えます。
http://wiki.squeak.org/squeak/1448 http://wiki.squeak.org/squeak/1414
727です。
なぜかOOの話がでてますが関数型の話でOOは関係ありません。
OOPLでも同じ表現ができるというだけです。
で、本題ですが、最終的な目的としては下のようなラムダ演算ができる言語は
存在しないのかという話です。
( 0 (lambda () "true" ) ) 0関数はlambdaを評価せず、nilを返す
( 1 (lambda () "true" ) ) 1関数はlambdaを評価し"true"を返す
( 2 (lambda () "true" ) ) 1関数はlambdaを評価し"true"を返す
( (- 1 1 ) (lambda () "true" ) ) 0関数を評価する事になるのでlambda
755 :
727:2012/05/13(日) 19:54:33.33
間違えて途中で書き込んでしまいました。すみません。
( 0 (lambda () "true" ) ) 0関数はlambdaを評価せず、nilを返す
( 1 (lambda () "true" ) ) 1関数はlambdaを評価し"true"を返す
( 2 (lambda () "true" ) ) 1関数はlambdaを評価し"true"を返す
( (- 1 1 ) (lambda () "true" ) ) 0関数を評価する事になるのでlambdaを評価しない
( (+ 1 1 ) (lambda () "true" ) ) 2関数を評価する事になるのでlambdaを評価しない
数値を関数化できないかというのは、数値を評価したとき、このような
振る舞いをするように数値を定義できなる言語は無いかという事でした。
尤も、言語レベルで最初から数値をチャーチ数と同じように評価できるなら
新たに関数として数値を再定義できる必要は無いんですが。
>>752 時代遅れってアホか、通信・製造・金融・保険・政府。
お前がしらんだけで第一線で新規開発されとるわ。
国内企業なら、東洋ビジネスエンジニアリングとかが導入してんだぞ。
F#でやってみた。
拡張メソッド定義してるだけなので、実質「Execute(0, fun () -> printnf "zero")」と同じ
type System.Int32 with
member x.Execute func = match x with 0 -> () | n -> func()
> (0).Execute (fun () -> printfn "zero");;
val it : unit = ()
> (1).Execute (fun () -> printfn "one");;
one
val it : unit = ()
> (1 - 1).Execute (fun () -> printfn "zero");;
val it : unit = ()
>>755 Integer と () -> Bool は違う型なので、
同じ数値(関数)の型が文脈に応じて変化する言語でなければ不可能。
759 :
727:2012/05/13(日) 20:19:44.31
むちゃくちゃになっていたので直します。何度もすいません。
( 0 (lambda () "true" ) ) 0関数はlambdaを評価せず、nilを返す
( 1 (lambda () "true" ) ) 1関数はlambdaを評価し"true"を返す
( 2 (lambda () "true" ) ) 2関数はlambdaを評価し"true"を返す
( (- 1 1 ) (lambda () "true" ) ) 0関数を評価する事になるのでlambdaを評価しない
( (+ 1 1 ) (lambda () "true" ) ) 2関数を評価する事になるのでlambdaを評価する
>>758 できる言語はあるかと聞いているのですが?
あとboolは関係ないですよね
>>760 じゃあ Integer と (() -> a) -> a
それはともかく、関数型とか全然関係なくって
まともな静的型なら無理って言ってるんだけど、
動的型しか使った事無い馬鹿には分からないかな?
>>761 だから、できない言語の事は聞いてなくて、出来る言語はあるかと聞いてるんですけど。
>>762 スレ違いだし問題としても糞詰まらんから
どっか行けって言ってんだけど?
何か値を返さなきゃならないみたいなので、
>>757を修正
nilと値じゃなくてoption型使ってるけど
type System.Int32 with
member x.Execute func = match x with 0 -> None | n -> func() |> Some
> (0).Execute (fun () -> "zero");;
val it : string option = None
> (1).Execute (fun () -> "one");;
val it : string option = Some "one"
> (1 - 1).Execute (fun () -> 1 - 1);;
val it : int option = None
>>763 NGにしたいんでトリでも付けてもらえます?
スレ違い以前に話が通じないので
>>763 まず日本語の通じないお前がどっか行けよ
>>764 オブジェクトで出来てもあんまり嬉しくないんですが・・・
>>761 「コンセントの付いている車はありますか?」
「軽トラなら無理です」
お前が言ってるのはこういう事だという自覚は有るのか?
普通は「あります」「ありません」この2択だろ
頭おかしいな
>>767 Int32はラッパークラスとかではなく、プリミティブかつオブジェクトなんだけど。
まぁそれでもダメというならどうしようもない。
>>764 のような Execute 的な関数を使うのってダメじゃね?
これアリなら難しくも何ともないじゃん
(|.) 0 _ = Nothing
(|.) x f = Just $ f ()
main = do
print $ 0 |. (\_ -> "zero")
print $ 1 |. (\_ -> "one")
print $ (1 - 1) |. (\_ -> "zero")
print $ (1 + 1) |. (\_ -> "two")
>>770 すいません。
関数と互換性をもってて欲しいんですよ。
>>771 >>772 てっきり拡張メソッド的なものを要求してるのかと思ってた。
Scalaなら暗黙型変換あるからできそうな気がする。
>>773 なるほど。Scalaですか、調べてみます。
で、Scalaなら出来たの?
マイナー言語使い共が
可読性皆無のコード書く御題で
型付けの弱さを競うスレはここですか?
時代に逆行してて笑えるwww
誰だって0と1は同じ型だと考えるのに、違った振る舞いをさせたいってのは、
何か前提がおかしいんだろうね。
元々何がしたかったのか聞ければよいんだけど、
彼にそういった振る舞いが出来るとも思えないしなぁ。
うーん。一番良く分からんのは、
>>767を読むと出題者は
>>764を見て
オブジェクトとしてなら「出来ている」認定してるっぽい処だな。
出題者がOOP厨だからオブジェクトには甘いだけだろ
別に不思議でもなんでもない
もちろん出題者は底なしのアホだけど
お題:
等確率N種類のカードをコンプするのに必要なガチャ回数のM回試行時の頻度分布から、
最小および最大のガチャ回数と最多頻度のガチャ回数を抽出して出力するコードを書き、
N=10、M=1000000のときの結果とその算出にかかった時間を示せ。
遅い処理系ではMを減らした際の結果を示しても構わないがその旨を明記すること。
OOPLでもメソッドの中は大体手続き型みたいなもんだから
関数型 VS 手続き型 って感じになりそう
では手続き型の Squeak Smalltalk で。
最低 10ガチャ、最高 156ガチャ、頻度最多は 23ガチャで 45475回出現。
1.8GHz Core i7 で 66秒程度。(CogVM 使用)
| N M histo cards time |
N := 10.
M := 1000000.
histo := Bag new.
cards := 1 to: N.
time := [
M timesRepeat: [
| player |
player := Bag new.
[player add: cards atRandom; includesAllOf: cards] whileFalse.
histo add: player size]
] timeToRun.
^{time. histo min. histo max. histo sortedCounts first} "=> {66128 . 10 . 156 . 45475->23} "
>>778 これで、できてると言ってる訳ではなくて、
数値を関数化してラムダ演算をするのが目的であって
オブジェクトで雰囲気が近いことできても仕方ない
という事を書いたつもりです。
最終的な目標は
>>759の様な(欲を言えばチャーチ数)演算が
できる言語を見つける事です。
>>775 よく知らないので、調べてる最中ですよ。
チャーチ数?
型無しラムダな処理系なら、学生演習レベルのものならいくらでもあるだろ。
チャーチ数が欲しいのか
>>759が出来る何かが欲しいのかどっちだよ
>>785 存在すればどちらでも構いません。
ただし誤解されてるかもしれませんが、
チャーチ数というのは、f x.x を直に表現できて
欲しいと思ってる訳ではなく。0なら f x.xと同じ振る舞いを
して欲しいという話で、今までの話とは大きく違いません。
チャーチ数と今までの話は、2以上の時、1回関数が評価されるのか、
2回評価されるのか程度の違いの意味で書いてます。
間違えました
×2回評価されるのか
○その数だけ評価されるのか
いよいよ何がしたいのか良く分からないが、
再起でよいんじゃないの?
>787
型なしラムダ計算でやりたいことがかける?
もしそうならLazy Kやunlambdaを使えばできるな。
lispならevalいじりゃ何とか出来そうな気がするが
関数名が数値型だったら特別扱いすりゃいいだけだろ
>>790 変数名が値だったらって何か変だぞ
変数は単に置き換えるのが目的であって
置き換えた後にどのような演算が出来るかというと、確かに何でも出来ると思う
しかしLispは要らない
関数名って書(ry
定数0を(\ f x -> x)に置き換えることはできないかもしれない
変数zを(\ f x -> x)に置き換えることはできる
なら定数を使わない言語を考えるのが普通で
定数の定義を書きかえるのは変だ
定数というか、リテラルかな。
いずれにしろ、リテラルの意味を再定義できる言語、というのは珍しいが、無いわけじゃない。
Forthなんかモード切り替えで、"100" というワードが 10 進にも 16 進にも解釈される、
っていう仕様だったと思ったし。
>むちゃくちゃになっていたので直します。何度もすいません。
>( 0 (lambda () "true" ) ) 0関数はlambdaを評価せず、nilを返す
>( 1 (lambda () "true" ) ) 1関数はlambdaを評価し"true"を返す
>( 2 (lambda () "true" ) ) 2関数はlambdaを評価し"true"を返す
>( (- 1 1 ) (lambda () "true" ) ) 0関数を評価する事になるのでlambdaを評価しない
>( (+ 1 1 ) (lambda () "true" ) ) 2関数を評価する事になるのでlambdaを評価する
こう言ってるから、処理系の持ってる整数型はそのまま使いたいんだろうと思う。
その上で、整数値を関数としても定義したいと。
良く分からないのは、整数値を関数で定義せず、
引数で渡せばよさそうなものなのに、なぜそうしないかだな。
796 :
795:2012/05/15(火) 16:41:00.21
あー、だから、整数の無い処理系もNGだろうし、
単純に整数をfunctorにしたいんだろう。
分からないのは、普通ならパラメータで渡せば直ぐ済むのに、
なぜそうしないかだとおもう。
その辺の説明が何も無いから、誰も答えられないんだと思う。
ついでに
>>780 1.6GHz Core i5 で 3.5秒 (GHC 7.0.4)
最小10, 最大162, 最多頻度23(45003回)
import Control.Applicative
import Data.Ord
import Data.List
import Data.HashTable as H
import System.Random.Mersenne
cardNum = 10
iterateNum = 1000000
count n = (+ n) . sum . map (length . f) . zip [1..n-1]
where f (x,p) = let q = fromIntegral x / fromIntegral n
in takeWhile (< p) $ iterate (\x -> x + (1-x) * q) q
799 :
798:2012/05/15(火) 18:50:05.32
続き
main = do
ht <- new (==) hashInt :: IO (HashTable Int Int)
gen <- newMTGen Nothing
mapM_ (trial ht gen) [1..iterateNum]
xs <- sort <$> H.toList ht
print $ (fst $ head xs, fst $ last xs, maximumBy (comparing snd) xs)
where
trial ht gen _ = do n <- count cardNum <$> (randoms gen :: IO [Double])
incr ht n =<< H.lookup ht n
incr ht k Nothing = H.insert ht k 1
incr ht k (Just v) = H.update ht k (v + 1) >> return ()
>>780 R
N = 10
M = 100000 (!= 1000000)
Intel(R) Atom(TM) CPU N455 @ 1.66GHzで、
user system elapsed
180.467 0.084 180.719
最小 10、最大 130、最頻値は4548回の23。
gacha <- function(N, M) {
print(system.time(t <- table(sapply(1:M, function(x) {
count <- 0
card <- logical(length=N)
while(!all(card)) {
count <- count + 1
card[sample(N, size=1)] <- T
}
count
}))))
print(t[1])
print(t[length(t)])
print(t[which.max(t)])
}
>>780 JavaScriptで多分ベタなOOP
Core2Duo(3.16GHz) Node.js(Windows)で
試行回数=1000000 所要時間=1398msec 最小=10 最大=144 平均=29 最頻=23(44951回)
ソース(※こっちは10000回)
http://ideone.com/DkeKE
>>801 コードそのものよりもNode.jsがspidermonkeyより
44倍も速いのが興味深い
Node.jsの中身のV8はJIT持ってるので
1000000回も試行してるのに各人の最大値がおおきくばらついてるのが気になる。
各処理系の乱数の質の差が反映されているのか。
書き捨てなのは分かるけど、
せめて void gacha(int n, int m, RESULT *r); くらいにロジック分離しようぜ。
>>803 しかもx86,x64,ARMに特化されたかなり先進的なJITだしね。
ところで、数値を関数にしたいと言ってた彼は
結局Scalaで望みのことが出来たの?
それとも、実はSmalltalk辺りのOOPLで
やりたいことは既に出来てて、あとは
「関数型言語で出来ないことがOOPLで出来る!OOPサイコー!!」
って言い出すタイミングをはかってるの?
Smalltalkは実社会で何の価値もないので
せめてこういうスレのトイプログラムの御題でくらいは
存在感を出さないとね。
既に引退の身ですが、現役の時はすごかったんですよ(棒読み
Intは関数ではないけど forall a. ((Int -> a) -> a) は関数だよ
Intに限らず任意の型で同じことが言えるのでチャーチ数は関係ない
関数を数リテラルとして表現できて
加算や減算ができるなら
チャーチ数で無くても文句無いんだろう、多分
ただし
>>797のプログラムはチャーチ数でないと
加算減算が出来ないから成立しない
静的言語 VS 動的言語スレとかないの?
まずJavaかHaskellのどちらかを潰さないと
静的言語は一貫していない
関数型言語も一貫してないから
それぞれで代表一つ以外は全て潰し
最後に決定戦とすべき
クラスベースOOとプロトタイプOOの潰し合いとか
スレが幾つ在っても足りんだろ
プロトタイプとか無視していいぞ
評判の良いやつだけで潰しあえ
Javascript「えっ」
動的言語の代表はLLバトルロワイヤルスレの勝者ですか?
Scalaスレ見てたんだけど、リストがソート済みかどうか
判定する関数を書くのに苦労してた。
短く書けるとウワサのScalaですらそのレベルなんて、
静的型付け言語はダメダメだなぁ。
scalaで書くとこんな感じかな。
def sorted[T:Ordering](xs:List[T]) : Boolean =
xs match { case x::y::zs => implicitly[Ordering[T]].lt(x, y) && sorted(y::zs); case _ => true }
型指定は面倒だね。
暗黙の型変換を定義すればもう少し簡潔になるかも。
おお、想像以上に型注釈がうざいw
関数プログラミング的に、比較演算子を引数で受け取るようにすると少しましかも。
def sorted[T](xs:List[T], f:(T,T)=>Int) : Boolean =
xs match { case x::y::zs => f(x, y) >= 0 && sorted(y::zs); case _ => true }
ソート済か?なんて調べる発想が変だろ
そんなこと無いだろ
二分探索を使う前とかに調べるじゃん
ていうかscalaって型推論って
引数と返り値の型は推論してくれないんだっけ?
つ amortized sortでcheck inする必要がある時にtestしながらinsert sort
>>825 ソートしとけよ
してないなら、まずソートしろ
実際にソートするのとソート済みか確認するのが
同じ計算量だと思ってる男の人って...
動的言語は静的言語より3〜5倍くらい短く書けないと
静的型チェックのメリットと釣り合わない
でもあまりに短いと、それはそれで暗号になっちゃうんだよ。
チェックは保険だろ
釣り合う物を取り返そうとしたら保険の意味がなくなる
>>830 ソートされてるかどうかわからない
なんてことになる設計がダメだしされてるんだろ
はいはい
オブジェクト指向で静的型のJavaですよー
public static<T extends Comparable<? super T>> boolean sorted(List<T> xs) {
for (int i = 1; i < xs.size(); i++) {
if (xs.get(i-1).compareTo(xs.get(i)) > 0) return false;
}
return true;
}
isSorted xs = and $ zipWith (<=) xs $ drop 1 xs
"Squeak Smalltalk"
SequenceableCollection >> isSorted
self overlappingPairsDo: [:a :b | a <= b ifFalse: [^false]]. ^true
大小関係を満たさないのが途中で分かってもソコで計算終了せず
全ての隣り合う組を比較するようなダメコードを書くダメプログラマは
まさかこのスレには居ないよね?
>>831 コードの長さはあまり関係なくないか?
考えた処理をサクサクとコード化できるか、だと思う
重要なのは品質,保守性,開発効率だな
>>833 保険というか、コンパイラに一部の整合性のチェックを任せられるので
作業量増加と引き換えに、開発者が気を使う要素が減る
トレードオフで負担を変化させる
[作業量が減る][気を使う要素が減る]どちらの開発効率が良いかは
ケースバイケースだと思うが
単位が一貫していない量を比較するのは難しいね
>>838 もしかしてHaskellについて言ってるなら、遅延評価だから途中で止まる
無限リストで試せば分かる
Prelude> isSorted [1,0..]
False
>>838 もしかしてSmalltalkについて言ってるなら、どうせ遅過ぎてウンコだから
そんなところ気にしても仕方ない
メッセージング(笑)
^falseってあるとおり、Smalltalkのもふつうに止まる。
Smalltalkerかアラン・ケイになんか嫌なことでもされたか?
遅延評価ってこんなにすごいのに
なんで使うことってあまりないんだろうね。
Haskell使ってれば基本は全部遅延評価だけど?
関数型言語でも、効率とか速度とか(必要なら汚らしさとか)を度外視すれば、mainで
「N種類のカードをアトランダムにコンプするまで引く作業をM回繰り返して集計」
ってただそれだけのことをSmalltalkみたいにそのまんまに書き下すことも可能なのかな。
HaskellにもMultiSet(SmalltalkでいうところのBag)とかあるよね?
>>846 内部で勝手に遅延評価してるってだけだから
そんな言語の話をしたってしょうがない。
遅延評価をしたい場面が無いって話をしてる。
>>809 あ?政府から海運業、通信、保険、金融、音響。
お前がしらんだけで実際いろんな所で使われとるわ。
英語が読めん奴が覆いから日本人の開発者が少ないだけ。
値を参照しようとするとその値の計算が始まる、
こういうイデオムはgetterのあるオブジェクト指向プログラミングだとよくある。
getterがないと値参照から関数呼び出しを引き起こせないので、
単に関数呼び出しをすることになってしまう。
ただしそのような場合でも遅延評価イデオムと呼ぶ場合もある。
例えば上に出たamotized sortは挿入時にやるべき並び替えを最後までやらずに、
細かい部分はサボって後回しにして、後でまとめてやっている。
こういうのは遅延実行の一種。
Smalltalkが現実で使われてないと言ってるヤツは、
Smalltalkという実行環境が現存してると思ってんだろ
うんで「Smalltalkでググっても見つからないよー」とw
Linuxと同じように純粋なSmalltalkは存在しないのにな。
>>851 よしわかった。
具体t系な実行環境を言ってくれ。
それに対して、使われているかいないか
判断することにしよう。
>>852 Visual Works.
VA Smalltalk.
Squeak.
Pharo.
GNU Smalltalk.
VA Smalltalkの前身であり、Eclipseの前身でもある
VisualAgeは、各種言語の統合開発環境でもあり
Smalltalkの実行環境なんだよな。
emacsのlispをSmalltalkに置きかえたと考えればわかりやすい。
>>853-854 よし、じゃあ次にどれくらい使われてるか
公平に判断するために、どこかが発表した
ラインキングを見てみるとしよう。
何か希望はあるかね?
ないならこちらで適当なランキングを
もってくるが、それだと不満だろう?
>>855 なんで回答者に左右されるランキングが必要なんだ?
製品のダウンロード件数でも調べてくりゃいいじゃねぇか。
あと販売数も。
MUMPSとかランキングにまず上がらんけど
物流や医療じゃ高確率で見かけるからな
その癖ググっても資料がでてこないから苦労する
あとCOBOLもまずランキングにのる事はないが
未だに金融じゃ必ずと言っていいほど見かける
ネットで見かける需要が現実の需要と
一致してるとは限らんよ(COBOLはみんな
嫌々使ってんだろうけど)
>>856 > なんで回答者に左右されるランキングが必要なんだ?
個人の意見じゃ、回答者(個人)に
左右されるからじゃないかw
同じ回答者でも、たくさんの意見を聞いたほうが良い。
回答者(多数)の方が信頼性が高いって言ってるんだよ。
>>859 個人じゃなく販売数とか、ダウンロード数とか
確実な値で調べろと言ってるんだが
マスコミがキムチピザをランキングの1位にしてたからって信じるのか?
まともな思考なら販売店の商品別売上実績を調べるだろ。
>>859 >回答者(多数)の方が信頼性が高い
理論的にはね。現実にはそううまくは実情は反映されない。
だからTIOBEを人気ランキングと勘違いする情弱が量産されてるんだと気づけよ。
Haskellのダウンロード数とSqueakのダウンロード数を比べえみたら良いんじゃない?
関数型言語のドマイナーさ加減が情弱にも理解できて少しはおとなしくなるだろう。
Haskell, Lisp, Smalltalk押しの俺はどうしたらいいんだ
linuxユーザーだから忘れてたわ
すまんすまん
でも、C言語なんかと比べたら全然なんでしょ?
その時点でどうでも良くない?
豆粒みたいな普及率をどうのこうの言ったって仕方ないし、
どうせ、数字の見方の問題に話がそれるだけでしょう。
それより、関数型言語のスレらしく、、
関数型言語の優れている点でも語り合ったら?
手続き型言語には副作用を簡単に表現できる利点があるから、
それを上回るメリットが関数型言語に無いことにはねぇ。
手続き型言語でも、副作用を禁止して書いていくことは出来るし、
その場合は副作用が無いからとても安全に記述できるわけだけど、
それと比べて関数型言語に一体どれだけのメリットがあるのか。
特に最近は遅延評価をサポートしている手続き型言語もあるし。
>>866 普及率自体はどうでも良くて社会基盤の一部として実働してることが重要。
そもそも玩具だの言い出したから始まった話だし。
F-22や米国兵器ぐらいにしか使われておらず
普及しているとは全然言えないからAdaは
おもちゃだと言ってるのに似てるね
>>860 > 個人じゃなく販売数とか、ダウンロード数とか
> 確実な値で調べろと言ってるんだが
公表されてないから調べようがない。
ランキング厨って、「世の中の仕事の99%は事務処理だから、プログラミング含め、創造的と言われてる仕事は重要でない」と宣う奴みたいだな。
そんなのが何でブログラムスレに居るのかは謎だが。
重要かどうかはどうでもいいよ。
実際、使われてないんだろ?
利用者数なんて使いやすさ/間口の広さの指標ぐらいにしかならないでしょ
価値と直結してるとか考えてる人はちょっとやばい
え、言語においては、たくさんの人が使っているものは、
それだけ価値があるんじゃないの?
>>876 違う。
違うっていうことはどういうことか分かるか?
反対ってことだ。
つまりあまり使われてない言語のほうが価値がある。
やっぱ池沼か。うざいからどっか行ってくんないかな。
日本語プログラミング言語のひまわりとか?
おいおい。使われないクソ言語はいくらでもあるだろう。
そこは、言語の価値はシェアや人気とは無関係って方向にもってけよ。w
柳刃包丁の包丁市場に占めるシェアみたいなものか
自分で書いてて例えが微妙な気がした
Smalltalkみたいなマイナー言語を長年使ってると
こんな
>>877書き込みするようになっちゃうの?
ガチなら狂ってるとしか思えないんだけど
>>880 > そこは、言語の価値はシェアや人気とは無関係って方向にもってけよ。w
無関係ではない。
統計とはそういうもの。
データを集めれば、
概ね正しい結果が出てくる。
ほら下らない展開。
だから、
>>866で止めようって書いたのに。
人海戦術は統計学に入りますか?
入りません
正しい統計結果を出すための前提が
>>883の中で欠落してる件について。
>>873 導入事例が存在するんだから使われてるに決まってんだろ
>>883 じゃADAは国家レベルの事業でしか使われてないから価値がないのか
あれだよな、スパコンじゃ9割7分Fortranが使われてて
科学技術の基礎や応用を作り上げてるが
ランキングに乗っていない以上無価値なんだよな
電話かけて聞けよ
電話かけて聞けよ
電話かけて聞けよ
>>868 > そもそも玩具だの言い出したから始まった話だし。
そんなレス在ったっけ?って検索しても無いから
遡って探したら前スレで見つけた。
> 382 : 営利利用に関するLR審議中@詳細は自治スレへ : 2012/03/31(土) 14:28:58.16
> かつてのSmalltalkファンが
> 今ではRubyやPythonを使ってるってのは良く在る話
>
> Smalltalkは構文がダサくて読み難いし
> Squeak/Pharoは玩具過ぎるし
> Visual Worksはまるで古いVBみたいだし
こんな前の話をまだ根に持ってたのかよw
執念深過ぎwww
そんな前のレス引っ張り出してきてドヤ顔のお前もそーとーあれだぞ。
>>809 の事だろ
>トイプログラムの御題でくらいは存在感を出さないとね。
なんだよ
>>895のマッチポンプかよ。いよいよヤバイ奴っぽいな。
マイナー言語使いって少し煽るだけで
顔真っ赤にして反論するからスレが荒れてうっとうしい
HaskellしかりSmalltalkしかり
少しはスルーしろよ、どんだけ余裕が無いんだよ
つーか日曜日の昼から2chかよ家族はどうした
志村っ! 日食! 日食!
>>847 1.6GHz Core i5 で12秒
{-# LANGUAGE BangPatterns #-}
import Control.Applicative
import Control.Monad
import Data.Maybe
import Data.Ord
import Data.List
import Data.MultiSet as S
import System.Random.Mersenne
cardNum = 10
iterateNum = 1000000
completeSet = fromList [0..cardNum-1]
main = do
s <- replicate iterateNum <$> newMTGen Nothing >>=
foldM (\(!s) g -> flip S.insert s <$>
S.size . fromJust . find (completeSet `isSubsetOf`) .
scanl (\x n -> S.insert (n `mod` cardNum) x) S.empty <$>
(randoms g :: IO [Int])) S.empty
print $ (findMin s, findMax s, maximumBy (comparing snd) $ toAscOccurList s)
いろいろスゴイ!
そもそも847はなぜ関数型で書けないと思ったのか
Smalltalkのコードだってブロック(クロージャ)多用してるのに
副作用を前提としたクロージャと、Haskell のそれはだいぶ違うと思うけど。
オブジェクト指向も最初はそんな感じだったじゃないか
C言語で同じことができると思う奴と
だいぶ違うと思う奴に分かれていた
いいかげん関数型言語 = Haskellの図式で語るのをやめなさい
OCamlとF#とSMLが怒りますよ
C言語は実際凄いだろ。副作用がかけるし。
Haskellでも副作用は書けるけどね
副作用の有無が型でキッチリ区別されて
静的型チェックの対象になるだけで
909 :
sage:2012/05/25(金) 08:12:50.15
今時OOPが本当に優れていると考えているヤツなんているのかよ。
OOPなんて、回路基盤 -> アセンブリ -> C言語の延長線上にある、非常にアドホックな
考え方だと思うのだが。
多くの静的型付け関数型言語は次の利点があるのは有名だろ。
* 自動テストが容易
* 拡張に対する変更箇所が少ない
* 型で「ありえない状態」の存在を除去
* nullがない
関数型と比べて、OOPのいいことってなんだ?存在しないんじゃない?
今どき、静的型のメリットと関数型のメリットを混同している奴がいるとはな。
あといい加減、OOP(あるいはもっと一般化した抽象データ型)と関数型は
型による抽象化か関数による抽象化かという抽象化手法の違いに過ぎず、
つまりそれぞれ得手不得手があるし互いにある程度補い合う事が可能な
考え方だってことに気づけよ。
つまりOCaml(関数型+抽象データ型)とScala(抽象データ型+関数型)が最強というわけでつね。
912 :
sage:2012/05/25(金) 09:13:10.98
>>910 OOPの得意な抽象化手法ってなんぞや。
カプセル化、多態性、継承はHaskellの方が優れていると思うのだが。
関数型言語の方が優れていますが
同時に優れたプログラマを必要とするので流行りません
どうりでRubyが流行るわけだ
黒板言語とその仲間たちと、実用は別だからな。
存在する処理系を認識できないような脳をしている
>>915 のような人間もいるしな。
>>912 カプセル化・継承・多態性というお題目は、OOPにおいてクラスを用いて
抽象データ型が実現されている(その恩恵〜かつてはそう信じられていた〜として
継承による差分プログラミングや、付随して多態性もある)ということを言い表わしてるだけなので
OOPで可能な抽象化手法を列挙したものではないってのはOK?
加えて、OOPにおいてクラスが単なる(SIMULAからの)借り物なのに対して、
抽象データ型を最初から視野においてよく練られたHaskellの型クラスが優秀なのは
あたりまえといえば当たり前。
Haskellはよく純粋な関数型と言われるけれど、OOPのように抽象データ型にクラスを使っていない
というだけで、言語としては関数型と抽象データ型のハイブリッド。
しいて言えば、クラスのように関数(メソッド)を型に内包する機構を使って
実現された抽象データ型の場合、関数型で好まれる関数を型の外に置く
抽象データ型(狭義の抽象データ型。CLUやAdaなんかもこの類)に比べて
型を追加する拡張が得意だし、その逆で後者は関数(その結果としてインターフェイス)を
増やす拡張が容易という程度の得手不得手はある。
http://www.cs.utexas.edu/~wcook/papers/OOPvsADT/CookOOPvsADT90.pdf
>>912 Haskell のカプセル化って何?
カプセル化って副作用のための仕組みじゃないの?
カプセル化→隠蔽工作
>>917 出典がちょっと古いな。
今はハイブリッドもある。
>>918 カプセル化っていうのは有り体に言えば抽象データ型、簡単にはユーザー定義型のこと。
あるいはその作業・手法のこと。OOPでは抽象データ型にクラスを使うから副作用の封じ込め的な
イメージがあるけれど、広い意味での抽象データ型においてはそれだけを意図したものではないよ。
カプセル化というのはアクセス制御をちゃんとやることです
もっといえば必要なもの以外はpublicにすんな、ということです
>>920 切り分ければそうだというだけで、別にクラスを使った関数(メソッド)を
内包させるタイプの抽象データ型と、内包しない狭義の抽象データ型の共存が
できないということを意味するものではないよ。
PythonとかScalaとかC#とか普通に(後者は特に巧妙に)やっているでしょう。
>>922 坊や。危ないからこんなところに来ちゃだめだよ。ほらほらOOP村にお戻りなさい。
>>921 だとしても「継承、多態、カプセル化」と並べられた場合
カプセル化が意味するところは封じ込めのほうで良いのでは?
>>921 haskellでのカプセル化はモジュール化して公開するシンボルを制限することだと思うが
>簡単にはユーザー定義型
カプセル化とオブジェクト化を混同してないか
ADTは、カプセル化の型システムからの射影。
OOPの文脈で
データの抽象化:データと振る舞いを一つにまとめること(クラスベースやプロトタイプベースで実現)
カプセル化:整合性を保つため内部への直接の操作を制限すること(アクセス指定子やクロージャで実現)
抽象化:派生クラスが何個あるのか気にしない
カプセル化:メンバ変数が何個あるのか気にしない
「obj.fooとobj.barは絶対にアクセスするなよ」と言われると逆に気になってしまう
OOPのカプセル化も公開するシンボルの制限にすぎんだろ
副作用を制限するって言ってるけど、OOPでカプセル化すれば
同じメソッド呼び出しが常に同じ結果を返すようになるんか?
ならないなら副作用の何を制限してるんだ?
>>901をSmalltalkに逆翻訳してみた。もちろん厳密にはいろいろと違うけどまあ勘弁して。
>>782や
>>799と見比べて、関数型でMultiSet(Bag)が使えてもぜんぜん嬉しくないのはよく分かった。
| M N cards bag replicate randoms |
M := 1000.
N := 10.
cards := 1 to: N.
replicate := [:n :x | Array new: n withAll: x].
randoms := [:g | (g next: N*10) * 2147483647 truncated].
bag := (replicate value: M value: Random new) inject: Bag new into: [:b :g |
b add: (((randoms value: g) inject: {Bag new} into: [:xs :n |
xs, {xs last copy add: n \\ N + 1; yourself}])
detect: [:xs | xs includesAllOf: cards]) size; yourself].
^{bag min. bag max. bag sortedCounts first} "=> {12 . 85 . 56->23} "
>>932 HaskellのMultiSetはimmutableだから、SmalltalkのBagとはその点で違うよ
immutableなコレクションに値を次々突っ込んでいく場合、
foldl等使って次々に新しいコレクションを生成する必要があるけど、
mutableなデータ構造で同じことやっても無意味に遅いだけだし
だからSmalltalkで真似したときに意味を見出せないのは当然だと思う
immutableなデータ構造や副作用の隔離による
ミス防止の恩恵は、うっかりなプログラマには嬉しいものだが
全く必要としないプログラマも居るんだよな
SmalltalkerにはHaskellのメリットなんて拘束具にしか見えんのかもしれんね
>>931 副作用をもたらす経路を制限出来る、というのは副作用を許す言語にとってかなり大きいことだよ
>>934 つまり、マルチセットをイミュータブルにして、その状態は
リストや再帰コンテキストに封じ込めて破壊的操作の代替にするのは
ミス防止のためっていう理解であってます?
具体的にはどんなミスが想定されて、イミュータブルにすることで
どうしてそれが防げるのか教えてもらえますか?
>>936 同じ値が複数箇所から参照されてるケースを考えれば分かるよ。
そういや
>>932ってどのくらいの実行速度だったの?
次世代高速CogVM(笑)だから速いんだよね?
暫定ダイナブック環境ww
老害しか使わないOSもどきの玩具www
レッテル貼りしかできない馬鹿wwwwwwww
オブジェクト指向言語って今でもあるのか。
>>941 お前が何の言語を知っているのか
すごく不安になるwwww
自分で作った訳でもない言語をドネーションも無しで手に入れて、他の言語ファンを叩くのに使うのが楽しい人って何時の世でも居るんだな。
訂正:本当に使ってるかは判らんか。
ドネーションの意味がわからない。
どないしよん。
>>943 笑うところだよ。
HaskellやSmalltalk使ってる人達は
JavaやC#使ってる人達をドカタ呼ばわりして
見下してるから好感が持てる
947 :
944:2012/05/27(日) 18:26:08.71
・・・
948 :
941:2012/05/27(日) 19:55:08.90
>>942 Smalltalkっていう言語があったのは知ってるけど。あの言語の
ような徹してオブジェクト指向という言語はあるのかい?
値打ちのわからない者には何の役にもたたないということ。
>>948 > ような徹してオブジェクト指向という言語はあるのかい?
中置演算子っぽく見せかけて実は他のメッセージと同じ扱いなので
2 + 3 * 4 => 20 になるような言語ってこと?
Rubyをdisろうとして失敗してる?
お題:
整数型を引数に取る、次の性質を満たす関数fを定義せよ。
f(f(x)) = -x
OOPLで解く場合は x.f.f = -x でも良い。
def f(x):
return complex(0, x)
>>953 二回目の関数適用でfの引数が複素数になるぞ。
場合わけはOK?
f(x) = -x (x >= 0)
f(x) = +x (x <= 0)
operator=だかoperator==だかを置き換えればいいのだな!
>>955 ごめん。これ x < 0 のときf(f(x)) = x だった。
降参だ。
>>958 御題の条件が自然数なら問題ないけど、整数だからね
f(f(x)) = -x
なので
f(f( f(f(x)) )) = x
引数が整数型なので戻り値も整数型
オブジェクトもタプルも複素数も使えない
分かんね
こんな感じかな。
f 0 = 0
f k | k > 0 = if odd k then k+1 else 1-k
f k = - f (-k)
>>952 たぶんこういうのを求めてはいないのだろうけど、Squeak Smalltalk で。
Integer >> f
| selectors |
selectors := #(negated yourself).
thisContext method literals first swap: 1 with: 2.
^self perform: selectors first
1 f f "=> -1 "
2 f f "=> -2 "
3 f f "=> -3 "
あ、いかん。負数の実行例を忘れた。
-1 f f "=> 1 "
-2 f f "=> 2 "
-3 f f "=> 3 "
>961が正攻法なんだろうけど、>962も面白いな。
>>961と基本的に一緒だけど
f x = (-1) ^ abs x * x - signum x
> map (f . f) [-5..5]
[5,4,3,2,1,0,-1,-2,-3,-4,-5]
このスレもそろそろ終わりか
関数型言語を覚えられない頭の可哀想なPGだけが
オブジェクト指向言語を使う、でFA
お前ん中ではなwwwww
関数型の駄目なところやその使い手のコミュ障っぷりはよく分かったけど
メリットはいまいち見えてこなかったなぁ…
自分の脳に障害があると疑ったほうがいいぞwwwww
でも手続き型のほうが副作用を簡単に書けて便利じゃないですか。
手続き型言語は確かに沢山あるけど、オブジェクト指向言語なんて
呼べるものはほとんどないのではないかな。