【激突】関数型言語 VS オブジェクト指向言語2

このエントリーをはてなブックマークに追加
一般的には、オブジェクト指向型言語が優勢でが
一部には関数型言語を崇拝している人もいます

どちらが上なのか、この際はっきりさせましょう

前スレ http://toro.2ch.net/test/read.cgi/tech/1331328955/
オブジェクト指向 ∋ (関数型言語 VS 手続き型言語)
http://toro.2ch.net/test/read.cgi/tech/1333801632/
前スレ>>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 -- 改行コードを変えて入出力先も変更
>>25
おー、なかなか。パチパチ
なんかお株奪われた?
>容易に変更できる設計にしておくこと

ソースにパッチを当てて変更するのは容易ではないの?
パッチが容易ではないというのは、もしかして
「CUIは容易ではない」「GUIは容易」みたいな思想と関係あるのか
> ソースにパッチを当てて変更するのは容易ではないの?
ソースにパッチ当てるといってもいろんな意味がある。

インターフェースを変更するようなソースの修正は容易ではない。
影響があちこちに波及するからだ。
OOが使えそうなところにはOOの機能を使うし、
関数型が使えそうなところには関数型の機能を使う。
両方使えそうにないところは普通の手続き型の格好に。たったそれだけのことだろ?
「関数型 vs オブジェクト指向」 からは、「if文 vs for文」並みのナンセンスさを感じるね。
OOも関数型も単なる一機能なんだから、状況に合わせて 使う/使わない すればよいじゃない。
なにも言ってないレスされても
>>30
「関数型 vs オブジェクト指向」ならその通りなんだけど、
ここは「関数型言語 vs オブジェクト指向言語」なんだわ
そういや関数型指向ってないよねw
>>29
パッチの意味は追加と削除の二種類しかない。
マクロな視点でいうと、最新版を出す影響と古い安定版を切り捨てる影響の二つ。
現に大きな影響が出ているが、
関数型とオブジェクト指向の人間はこの問題についてなにも言ってない。
なぜなら、古い仕様が優遇されてしまうと手続き型が圧倒的に有利だから。
>>34
具体的に言って下さい。
>>33
functional (programming)
一口にパッチと言っても

・ソースコード自体を書き換える方法
・ソースコードはそのままに静的に書き換える方法(マクロ、テンプレート)
・ソースコードはそのままに実行時に書き換える方法(モンキーパッチ)

などがあるのですが
>>37
文字列自体を操作する方法と、文字列に代わるものを操作する方法があるよね
>>33
個人的に、関数型言語は「型指向」だと思う
どう言う型受け取って、どう言う型を変えしたいのか考えると、自然と答えが出て来る
>>37
それらの区別はたいして何も変わらんw
個人的には、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
>>40
全然違うだろアホか
>>39
節子、動的・動的…
>>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だから。
結局無記名で議論すると個人の感想の叫びあいなんだよね
関数型における分析と設計が出ない時点で
実装のみの技術ってことだろうね。
>>47
何を?
関数と述語による形式的仕様記述やZ言語は?
OOP より FPのほうが響きがいい よってFPの勝ち。
>>56
流れ的に>>41
>>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
犬とか猫を
どうやって関数型言語で表現するの?
>>83
これを本気でいうからなぁ
>>84
犬とか猫を
どうやってオブジェクト指向言語で表現するの?

まさか class Dog のインスタンスが犬なの?www
>>83
言いたい事は分かったが、なんでUMLで分析しないの?
金銭の概念をオブジェクト指向分析すればいいのに、なぜ犬と猫なんだ?
>>86
型と値の区別ついてるかな?
>>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で書く必要ない。
「状態」をオブジェクト分割する必要性がほぼ無いから
ちなみに>>104が言ってるのはこれね
http://www.cs.nott.ac.uk/~gmh/life.lhs
しかも「無理があると思える対話型プログラムを自然に書く」
というお題の章に乗ってるんだけどな。
つまり書けますよといっているだけでよりメリットがあるとは言っていない。
「無理がある」がかかってるのは「対話的プログラミング」の
部分であってライフゲームじゃない

そして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
違うのですか?
違うなら説明してもらわないと分かりませんよ
>>121
すでにループだと思うんだけど>>105
あ、それと f x y z で x と y と z の型でスイッチするときに
OOPで良くある x.f y z という表記は分かり難くないですか?
なんで x だけ f の前に来てるんですか?
>>122
だからオブジェクトを起点にしてるとだけ言われても分かりませんよ
なんとなくの気分の問題なんですか?
>>124
正直それで分からないときついと思うんだけど。
オブジェクト指向分析とかイメージできる?
オブジェクトを起点にしたか否かなんて
設計者の心の中にしか無いのではないですか?
設計/分析されたものだけを見てオブジェクト指向か否か判定できるのですか?
いや、>>92を見ると判定はできるようですね
その基準を教えてください
>>126
それは正しいとも言えるし正しく無いとも言える。
設計者本人がどう設計したかを100%証明することはできないという意味では正しいが
OOPLで書かれたコードをみてどう設計したかったを推測することは可能。

正直君のレスは哲学レベルの話でソフトウェア工学の話じゃない。
>>128
ソフトウェア工学の話じゃないのは>>115の説明ですよ
>>116の話は分かりますよ?ソフトウェアの機能について言及してますからね
>>129
じゃあどこが理解できないか説明してもらえるかな
あまりに共通言語なさそうだから説明は無理かもしれないけど。
>正直君のレスは哲学レベルの話でソフトウェア工学の話じゃない。

お前のことだろw 自分で >>105 読み直してみろよw
>>131
どこがか指摘してね
>>130
「起点にする」を正しく定義してください
それはソフトウェアの機能として定義できますか?
プログラマの心理状態として定義するのですか?
それとも哲学的な何かとして定義するのですか?
>>133
えーと正直あほらしいです。
Wikipediaで気分に近い文章を引用してみます。

>ソフトウェア工学において、ソフトウェア (システム) を相互作用するオブジェクトの集まりとしてモデル化 (オブジェクト指向モデリング) する、オブジェクト指向に基づくソフトウェア開発の方法である。
http://ja.wikipedia.org/wiki/%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E6%8C%87%E5%90%91%E5%88%86%E6%9E%90%E8%A8%AD%E8%A8%88
>>134
その定義は大分>>105>>115と違いませんか?

それはともかく、それでは関数がオブジェクトの関数型言語では
関数が相互作用してるのでオブジェクト指向ですね
こう言っては何ですが、議論に負けないために
より一般的な、より抽象度の高い何かとして
オブジェクト指向を定義しようとするあまり
ナンセンスの域に到達してると思いますよ
主語も述語も不明なレス
>>137
自己言及文ですか?
結局のところオブジェクト指向で
システム開発は行われるんだよ。
たとえ関数型言語を使ったとしてもね。

だって考えるでしょ?
関数型言語で多態を実装するにはどうしようか?とか。
ルールを厳密に適用すれば何でも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
OO感→OO観
基本的な流れとして手続き型も、関数型も
オブジェクト指向を取り入れる方向で進化してるよね。
>>159
parottはなかろう…
オブジェクト指向言語は
関数型言語の利点を取り入れ、

関数型言語はそれだけではアプリを作りにくと
現実的な選択肢としてオブジェクト指向を取り入れる。
>>159
最近楽しいなと思うのは10年くらい前に産声を上げたオデスキーのScalaがここ近年
実用に使われるようになってきたこととか、Clojureというもう一つの選択肢がでてきたこととかetc
>>162
あ、いや成功したのはparottでは(まだ)なく、parottの実装でhaskellが注目されたこと
絶賛というか、今のOOPは単なる常識でしかない
関数型もまた、珍しい技術から単なる常識になりつつある
ただそれだけのことだろ
メソッドをメッセージと捉えるのは、その多くの場合の使われ型から無理を感じる
なれればどうってこと無い
OOも関数型も単なる一機能なんだから、
それをもって〜言語って言い張るのは無理があるんだよ。
>>169
でも、マルチスレッドや分散処理の論文は関数型や論理型の推奨する永続データモデルばかりだよ?
シングルスレッドならともかく、マルチスレッド意識したら純粋関数型や論理型じゃないと厳しい時代になってくると思うんだけど
>>170
今は普通にマルチスレッドの機能は
オブジェクト指向言語に搭載されてる。
ストラウストラップのOOのキモは「抽象データ型にクラスを使うアイデア」。
ref. http://www2.research.att.com/~bs/whatis.pdf

ケイのOOのキモは「処理系のみならず、その受け皿であるナンチャッテOS、工程まで
ひっくるめたあらゆることで徹底した動的性」。
ref. http://metatoys.org/oxymoron/oxymoron.html

関数型のキモは「非破壊操作とそれがもたらす参照透明性」。

型推論とかメッセージとかパターンマッチとかはオマケです。偉い人には(ry
>>170
分散したいならデータも共有しないのが基本なので
永続データの共有を推奨するのはおかしいと思う
>>170
あんま最近は追いかけてないから知らないけど、
汎用手続き型+トランザクショナルメモリの研究はもう止めちゃったのかね。
デッドロックのみならず、例外処理もしやすくなるから期待していたんだけど。
トランザクションで思い出したけど、SQLは宣言的言語と言われてたはずだったんだけど、
今どきはストアドプロシージャとかも使うらしいね。
結局欲しいのは副作用の管理
>>161>>163
オブジェクト指向の何を取り入れたの?
Haskellのどの機能がオブジェクト指向由来なのか教えてくれ
OOで見るべきところがあるのはメッセージング(徹底的な動的性)とtraitsのみ
他はゴミ
OCaml のことを言ってるんじゃないのか?

あとジェネリックプログラミングとかは、中途半端に型があるオブジェクト指向系の
言語でやるより、がっちり型のある関数型言語でやったほうがいいし、ST モナド
使えば、本物の「状態のカプセル化」ができる。
関数型ではオブジェクト指向なんてできない、というのは初心者が陥りがちなデマ。
そういや、関数型でOOPLでいう継承ってどんな形になるの?
>>179
継承っぽいやつ>>93
プロトタイプOOっぽいやつ>>25

OCamlは普通にクラスも継承もあるので省略
>>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
>>189
彼には言っても無駄な稀ガス…
>クラスの生成時に呼び出すメソッドと演算子に直感的な違いも何も無いと思いますが・・・

右辺で使う演算子を左辺に書いてみれば違いが分かるよ
reverse (xs++[x]) = x : reverse xs
実際には xs++[x] というパターンマッチはできない
192デフォルトの名無しさん:2012/04/11(水) 21:29:08.42
ユーザ定義のデータコンストラクタは頭大文字で始まるから
そんな混乱せんだろ
むしろコンストラクタを関数としても使えるのは便利だ
まあリストやタプルのコンストラクタは記号だが、それくらい覚えとけ
193デフォルトの名無しさん:2012/04/11(水) 23:24:51.38
関数型言語ってようするに、
関数がクラスになる。

言ってみればJavaScriptからprototypeがなくなったようなもの。
prototypeがなくなっても効率が悪くなるだけで
オブジェクト指向できるでしょ?

それが関数型言語。
194デフォルトの名無しさん:2012/04/12(木) 00:08:31.03
オブジェクト指向言語ってようするに、
オブジェクトがクロージャになる。

言ってみれば関数型言語から代数データ型やパターンマッチやカリー化が無くなったようなもの。
代数データ型やパターンマッチやカリー化が無いと効率悪いけど
関数型スタイルでプログラミングできるでしょ?

それがオブジェクト指向言語。
195デフォルトの名無しさん:2012/04/12(木) 00:14:31.10
> 代数データ型やパターンマッチやカリー化が無いと効率悪いけど
それはないな。
196デフォルトの名無しさん:2012/04/12(木) 00:22:10.76
>>194
それはチョット違うだろ。
クロージャーはlexical scope内にある変数をバインドして保持している関数オブジェクトで、あくまで関数オブジェクト。
オブジェクト指向のオブジェクトは、主に構造を持ったデータオブジェクト(単純スカラーでも可)またはクラスscopeにメソッドやインスタンス変数を
従属させモジュラレティーを確保する事に加え、インヘリタンス/mixin/treitなどで共有または階層関係を持たせ、データドリブンなインターフェースを提供する。
似たところもあるけれど、分けて考えるべきかと。
197デフォルトの名無しさん:2012/04/12(木) 00:29:40.32
>>196
いや、マジレスされると困るわw

つーか、そこ突っ込むなら>>193の方が違いすぎるだろ
> 関数がクラスになる
198デフォルトの名無しさん:2012/04/12(木) 00:39:23.32
>>197
じゃあ、関数の戻り値がオブジェクト(インスタンス)になる。でいいか?

オブジェクトを作り出すもの = クラス
戻り値を作り出すもの = 関数

言ってることは同じだけどなw
199デフォルトの名無しさん:2012/04/12(木) 00:48:53.41
>>198
カリー化されてんだから関数の戻り値も関数だろ
クラスとインスタンスのような関係はねーよ

それともあれか?関数もオブジェクトだから
関数型言語はオブジェクト指向ってやつか?くだらねえ
200デフォルトの名無しさん:2012/04/12(木) 00:56:44.16
気持ち悪いアナロジーで無理矢理OOに対応付けて
理解しようとしなくても
ドカタの人生で関数型言語を使う機会なんて来ないから
安心しろよ
お前にとって運悪く関数型言語が普及してしまったとしても
その頃にはお前の仕事は無くなってるよ
201デフォルトの名無しさん:2012/04/12(木) 00:57:45.87
>>197
>>193も突っ込もうと思ってたw
JSがらprototype削ったらinfix notationなlispみたいなのになっちゃうから。
202デフォルトの名無しさん:2012/04/12(木) 01:01:03.49
ドカタ以下のトイプログラマー
203デフォルトの名無しさん:2012/04/12(木) 01:05:35.12
オレ>>169>>201だけれど、

関数をOOのオブジェクトとみなすところにはそれ程違和感無かった。
言語によっては、関数オブジェクトにもメタ情報設定してOOのオブジェクトみたいにmethodを従属させたり、他のmethodをmixinさせることもできるものがあるから。
ただしhaskellではないが。
204デフォルトの名無しさん:2012/04/12(木) 01:12:21.32
関数型が自己満足以上のメリットがあると感じたこと無い
205デフォルトの名無しさん:2012/04/12(木) 01:15:35.37
>>203
うそつけ。>>169はオレの書き込みだ。
206デフォルトの名無しさん:2012/04/12(木) 01:17:46.33
>>203
あ、でもやっぱ違うか、勘違い。
クラスは静的な物(ともかぎらないclassすらもオブジェクトという概念の言語もあるけれどちょっとおいて置いて)
オブジェクトの生成はコンストラクタってのが昨今普及している概念だから。
207デフォルトの名無しさん:2012/04/12(木) 01:18:40.06
>>205
こめ、あんか間違えた。えーとどれがオレのレスだったっけw
208デフォルトの名無しさん:2012/04/12(木) 01:19:35.18
ぶっちゃけいうと

関数型は今仕事がない。
将来はあると信じてる。

オブジェクト指向は今仕事がある
将来はなくなって欲しいと、関数型厨は思ってる。
>>200とかそうだなw
209デフォルトの名無しさん:2012/04/12(木) 01:49:53.91
スパコン向けのプログラム書いてる人とかなら関数型を使う機会があるかもだが、
求められるのはプログラミング技術じゃなくて、対象問題の専門知識だわな。
あとは、大学教授が自分の論文に必要な計算をキャンパスのコンピュータを使って並列計算しました的な。

関数型は並列化が容易だから、実行速度が求められる分野に適していそうだが、
手続き型で並列化したほうがもっと速くなるから、結局なんだかなーな。

クラスタを電卓代わりに使う人用かと。
210デフォルトの名無しさん:2012/04/12(木) 02:03:13.63
>>209
本気で並列化に取り組むとその考えかたは変わるよ。
関数型の並列化はタスク?データ?どっちのparallelだと思う。
スパコンは徹底的に性能重視だし。
まいいや2chでマジレスカコワルイオレw
211デフォルトの名無しさん:2012/04/12(木) 02:20:44.68
>>210
関数型で出来ることが手続き型で出来ないってことはないんで。
FPGAとかは別としても、主流のノイマン型は手続き型がネイティブなんで。
212デフォルトの名無しさん:2012/04/12(木) 02:45:31.08
>>211
できるできないまで話を広げればパラダイムなぞ何でもいいんだよ。
性能を徹底的に追及するにはCPUの命令レベル並列化SIMD並列化core間メモリ共有離散並列化ネットワーク分散並列化
徹底的に実効効率(≒GFLOPS)と性能を追求する。
一方の関数型で一部取りざたされる並列化は、並列化のしやすさ=参照透過による並列依存解析の簡便さなどで
まだ止まっている段階であり性能の追求に関してはマッタク解になっていないンジャマイカ?
だからデータパラレルorタスクパラレルか上で訊いてみた。その答えでどのくらい深く考えている椰子かわかるから。
簡便さは無視できず大切なことかもしれないが、それで数値解析がいままでより早くなっていないのであればつかわれなくてもしょうがない。。
安易に並列化に研究成果を求めて逃げるのは愚。

で、FPGAって何の話だ?と小一時間w
もしかしてハード・ソフト両面でずぶの素人さんをオレは相手にしてしまった?
上のクロージャーもしかりだけれど2chでマジレスあまりしたくない。
213デフォルトの名無しさん:2012/04/12(木) 03:06:38.71
あーわかったわかった。
関数型が並列化に向いてるって書き込みに噛み付いてたのか。そりゃ食い違うわ。
でも、参照透過性って並列化以外に上手い生かし方が無いと思うんだが。
遅延評価も言語レベルでサポートが欲しいかと言われると、別にねぇ。
214デフォルトの名無しさん:2012/04/12(木) 03:13:37.82
>>213
参照透過性はプログラムコードの理解しやすさ、バグの入りにくさなどに少なからず貢献あるんじゃマイカ
215デフォルトの名無しさん:2012/04/12(木) 03:20:08.01
でも、副作用のないプログラムが読みやすいのは、手続き型でも同じことだしなぁ。
言語レベルでサポートしていることの意味は、自動化、
つまりは自動遅延評価や自動並列化になるとおもうんよ。
216デフォルトの名無しさん:2012/04/12(木) 03:27:10.53
>>215
副作用を禁止しちゃっても十分ソフトウェアは記述できるという数学的な原理に基づき
そのための仕組みを言語レベルの機能でちゃんとサポートし副作用を低減しようとする意義はあるのでは?
217デフォルトの名無しさん:2012/04/12(木) 03:42:11.67
そんな蓮舫さんみたいなこと言われても。
218デフォルトの名無しさん:2012/04/12(木) 06:22:33.36
副作用のある部分をコードの一部に隔離したとき、
それが他に漏れてないことを静的型検査できるのがメリット

静的型検査なんて要らないし、副作用の有無なんて
コメントにでも書いとけば分かるだろ
というプログラマにはメリット無い(批判する意図はないので注意)
219デフォルトの名無しさん:2012/04/12(木) 06:34:07.76
ただし、>>218は特定の言語(HaskellとかD)のメリットであって
関数型言語のメリットでは無い
220デフォルトの名無しさん:2012/04/12(木) 06:44:16.58
普及してるかどうかで使う言語を決めてる人って
TIOBEとか見て一喜一憂してるの?

http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html

JavaプログラマならJavaの人気が長期的に下がり続けてる
(ついに今月は2位に陥落)の見てショック受けてるの?

幾らでも他と交換可能な木っ端プログラマは大変だね
221デフォルトの名無しさん:2012/04/12(木) 09:49:24.36
中身無いなぁ。
普及率は人気の度合い。なぜ人気があるのか考える必要がある。
誰かさんの思い込みより価値ある。
222デフォルトの名無しさん:2012/04/12(木) 09:50:24.09
>>216
仮にIOを禁止しても、IOと殆ど同じモナドを簡単に作れる
だから禁止していいんだという解釈もあるが、禁止しても無意味だという解釈もある
Haskellが、いずれかの解釈を一方的にサポートすることはない
あくまで中立
223デフォルトの名無しさん:2012/04/12(木) 09:55:43.85
モナドって副作用の定義を限定的にして副作用なくしたと主張してるだけで
ソフトウェア工学上で問題になる事項をすべて解消しているわけではいないと思うんだけど
どう思う?
224デフォルトの名無しさん:2012/04/12(木) 11:16:27.37
問題を定義した本人には、自己解決しましたと主張する権利があると思う
225デフォルトの名無しさん:2012/04/12(木) 16:43:59.37
>>221
全くもってその通り!!
中国語だって世界中で大人気だからな!!
226デフォルトの名無しさん:2012/04/12(木) 16:51:24.45
>>223
現実のコンピュータが副作用必須の設計で、モナドは副作用解決に使えるというだけ。
モナドが副作用解決のために作られた訳じゃない。
227デフォルトの名無しさん:2012/04/12(木) 17:45:50.95
モナドは何のために作られたの?
228デフォルトの名無しさん:2012/04/12(木) 18:33:25.41
人工知能だけに限らず人間の知能にも起こり得るフレーム問題は、ジョン・マッカーシー
らの提案したフレーム問題と区別して一般化フレーム問題と呼ばれている。
ソースはwikipedia

>>223
限定的なフレームを選択しないと、フレーム問題に対処できない
229デフォルトの名無しさん:2012/04/12(木) 19:54:30.42
関数型は問題資源を乱獲してあっという間に死滅させる蛮族の手法

対して従来のやり方は問題を死滅させず適宜再生産もする
農耕・牧畜をおぼえた文明人の手法
230デフォルトの名無しさん:2012/04/12(木) 20:03:40.16
は?

単に生産性が低いものを賞賛してるだけのバカですねw
231デフォルトの名無しさん:2012/04/12(木) 20:11:16.33
OOを使ったプロジェクトは次の二つに分類される

・プロジェクトが成功した場合 => 成功したのはOOのおかげ
・プロジェクトが失敗した場合 => 設計者やプログラマがOOに未熟だった

以上の詭弁により、OOはソフトウェア工学の全ての問題を解決した
232デフォルトの名無しさん:2012/04/12(木) 20:12:09.57
え、関数型って生産性あったんですか。
233デフォルトの名無しさん:2012/04/12(木) 20:15:51.90
どんな被害妄想だよ。成功も失敗も設計者の腕次第だろ。
234デフォルトの名無しさん:2012/04/12(木) 20:41:17.18
解決はするけど生産はしない
235デフォルトの名無しさん:2012/04/12(木) 22:36:25.45
>>232
生産性については職業プログラマの人に比較して貰うとして、少なくとも、rubyで入門書のサンプル以上のものが作れなかった自分が、haskellでは>>41,>>74のコードを書ける様になった

初心者には、rubyよりhaskellの方が自力でコード書ける様になり易いんじゃ無いかと思う

236デフォルトの名無しさん:2012/04/12(木) 23:36:58.60
せめて一ファイル千行ぐらいのものを
数十ファイルからなるアプリを作ってから
書けるようになったといって下さい。

短い関数一つと程度、
あんなの誤差でしかない。
237デフォルトの名無しさん:2012/04/12(木) 23:59:11.36
プログラムが書けるようになったといえる最低ラインは数万行のアプリを作れてから・・か。
238デフォルトの名無しさん:2012/04/13(金) 00:07:17.03
http://gihyo.jp/design/serial/01/ec_cube2011/0002
EC-CUBE 4万行らしいよ。
239デフォルトの名無しさん:2012/04/13(金) 00:08:42.48
240デフォルトの名無しさん:2012/04/13(金) 00:12:30.38
http://picomu-tech.blogspot.jp/2010/01/openpne2.html
OpenPNE2 13万行

Linuxは1500万行らしい

http://www.infoq.com/jp/news/2012/03/Defects-Open-Source-Commercial
解析対象のオープンソースプロジェクトは、コード行数が10万〜50万のものが
ほとんど(700万行を超えるプロジェクトが2つ)で、
の合計コード行数は3,744万6,469行、平均コード行数は83万2,000行になった。
241デフォルトの名無しさん:2012/04/13(金) 00:21:31.21
OpenDylanは処理系が80万でIDEが100万stepだったっけ、失念
gccが少し前は30~40万行あった、いまの4.6,47はもっとだろうな
242デフォルトの名無しさん:2012/04/13(金) 00:23:31.62
>>236
書きたいものを書ける様になったら行数関係無い気がするけど・・・
そもそも、私の場合、Rubyではどう書けばいいかすら思い浮かばない
(学習が足りないと言われればそうだけど、どっちも入門書読みかけ状態での知識でしかない)

Haskellは入門書読みかけの状態でも結構色々書けるから、入門者のモチベーション維持にも良いんじゃないかな
(少なくとも、自分のモチベーション維持には良い効果がある)
243デフォルトの名無しさん:2012/04/13(金) 00:27:01.11
書きたいものを書けるのは
プロである以上最低限のことです。
244デフォルトの名無しさん:2012/04/13(金) 00:27:48.64
>>241
間違えた、The compiler includes an IDE (Win32 only, sorry), CORBA, OLE, all in all 850000 lines of code. This is (nearly) all Dylan code.
245デフォルトの名無しさん:2012/04/13(金) 00:33:06.76
>>243
書きたくない物でも金を受けとる以上書き上げるのが…(ry
246デフォルトの名無しさん:2012/04/13(金) 00:36:02.31
>>245
あんたプロや。プログラマー(ry)や。
247デフォルトの名無しさん:2012/04/13(金) 00:38:56.24
>>243
プロじゃないと言うか、プロの卵として就職して半年で諦めたんですが・・・
そんな奴が、Haskellでなら、ちょっとは書ける様になったですよ

それで気付いたのは、やってる事はどの言語も同じなのかもなぁー・・・と
で、関数型言語はそのやってる事は同じ。の部分を気付きやすい言語だな・・・・と

他の言語で何やってるのか分かんなくて挫折した人は、一度、関数型言語に挑戦してみてほしいかも
248デフォルトの名無しさん:2012/04/13(金) 00:46:28.21
>>247
うん。やる気マンマンです。
249デフォルトの名無しさん:2012/04/13(金) 01:27:06.58
>>248
一緒に頑張りまっしい

多分、私はそもそものググルための用語を知らないのが、そもそもの才能の無さな気がする
なので、そもそもググらず自分で作っちゃえ!派な自分には関数型言語の方が性に合うっぽい
(不器用なのは自覚してる)
250デフォルトの名無しさん:2012/04/13(金) 01:30:15.85
そういうセリフは関数型言語を作ってから言って下さい。

作らずに言語を使ってるだけのくせに
251デフォルトの名無しさん:2012/04/13(金) 01:41:31.45
>>249
> なので、そもそもググらず自分で作っちゃえ!派な自分には関数型言語の方が性に合うっぽい

初心者なら当然のことだよ。

俺なんかだと、見ただけで簡単な処理と分かるようなもの、
自分で作れると分かっているものは、作っても時間
を浪費するだけで何の経験値にならないし、自慢にもならない。

でも初心者にとっては、そんなものでも
挑戦する価値がある課題なのだから。
自分で作ったんだって自慢げになるでしょ?
252デフォルトの名無しさん:2012/04/13(金) 06:51:30.77
何万行とかで脅されても気にする事無いよ
ドカタ仕事で書くコードなんてAPI呼び出すだけ、コピペコード満載の
頭悪いコードなんだから

疑うなら適当なコード書く御題出してみ?Javaのコードとか出てこないから
253252:2012/04/13(金) 06:57:36.95
多分、「そんなの意味ない」「もっと規模が大きくないと本当の事は分からない」
とかその手の言い訳を、御題のコードの10倍くらいの長さの文章で
必死に語ってくれるよ
本当は2chのレスに収まる規模のコードも書けないんだけどね
254デフォルトの名無しさん:2012/04/13(金) 07:16:26.24
>>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" など)で。
255デフォルトの名無しさん:2012/04/13(金) 07:48:45.37
>>252
ありがとうです
では、仕事があるので明日私は書くと思いますが(飲んで帰るので、今日は無理)

ファイルと検索したい文字列をコマンドから入れて、見つかった行と列のリストを表示すると言うのはどうでしょう?
256デフォルトの名無しさん:2012/04/13(金) 08:18:23.98
全くなんの工夫もないが

$ cat fizzbuzz.hs
import Control.Monad (mapM_)

main = mapM_ (runFizzBuzz . gizz . buzz . fizz) [1, 3, 5, 7, 15, 21, 35, 105]

runFizzBuzz (n, s)
 | s == "" = putStrLn $ show n
 | otherwise = putStrLn $ show s

fizz n
 | n `mod` 3 == 0 = (n, "Fizz")
 | otherwise = (n, "")

buzz (n, s)
 | n `mod` 5 == 0 = (n, showString s "Buzz")
 | otherwise = (n, s)

gizz (n, s)
 | n `mod` 7 == 0 = (n, showString s "Gizz")
 | otherwise = (n, s)

$ runghc fizzbuzz.hs
1
"Fizz"
"Buzz"
"Gizz"
"FizzBuzz"
"FizzGizz"
"BuzzGizz"
"FizzBuzzGizz"
257デフォルトの名無しさん:2012/04/13(金) 08:45:35.77
この場合の顧客がのぞむもの。

map (gizz . buzz . fizz) [1, 3, 5, 7, 15, 21, 35, 105]
-- [1, "FIzz", "Buzz", "Gizz", "FizzBuzz", "FizzGizz", "BuzzGizz", "FizzBuzzGizz"]

map (buzz . gizz . fizz) [1, 3, 5, 7, 15, 21, 35, 105]
-- [1, "FIzz", "Buzz", "Gizz", "FizzBuzz", "FizzGizz", "GizzBuzz", "FizzGizzBuzz"]
258デフォルトの名無しさん:2012/04/13(金) 08:54:17.09
整数と文字列が同じリストにフラットに入らなきゃ嫌だという主張?
259デフォルトの名無しさん:2012/04/13(金) 09:05:31.58
struct filter_t{ int e; const char *t; };
struct fizzbuzz_t
{
  int in;  std::string out;
  fizzbuzz_t &operator >>( filter_t &f )
  { if( 0==in%f.e ){ out.append( f.t ); } return *this; }
operator const char *()
{ if( out.length() ) return out.c_str(); static char tmp[50]; itoa( in, tmp, 10 ); return tmp; }
};
fizzbuzz_t operator >>( int i, filter_t &f ){ fizzbuzz_t fb; fb.in = i; fb>>f; return fb; }
filter_t fizz = { 3, "Fizz", };
filter_t buzz = { 5, "Buzz", };
filter_t gizz = { 7, "Gizz", };

int main(){ 105>>fizz>buzz>>gizz>>endfb; return 0; }
260デフォルトの名無しさん:2012/04/13(金) 09:05:55.65
fizz buzz gizz (とその合成)で完結する。
合成順が結果に反映される。
結果は標準出力ではなく関数の戻り値として欲しい。
というのが要件だろう。
関数縛りがなければマクロですぐなんだが。
261デフォルトの名無しさん:2012/04/13(金) 09:09:14.47
ごめんごめん途中で送信してしまった。
読まなくても良いくらいC++でのスタンダードな回答。

struct filter_t{ int e; const char *t; };
struct fizzbuzz_t
{
  int in;  std::string out;
  fizzbuzz_t &operator >>( filter_t &f )
    { if( 0==in%f.e ){ out.append( f.t ); } return *this; }
  operator const char *()
    {  if( out.length() ) return out.c_str();
      static char tmp[50]; itoa( in, tmp, 10 ); return tmp; }
};
fizzbuzz_t operator >>( int i, filter_t &f ){ fizzbuzz_t fb; fb.in = i; fb>>f; return fb; }
filter_t fizz = { 3, "Fizz", };
filter_t buzz = { 5, "Buzz", };
filter_t gizz = { 7, "Gizz", };

int main(){ 105>>fizz>buzz>>gizz; return 0; }
262デフォルトの名無しさん:2012/04/13(金) 09:19:13.99
スタンダードっていうより姑息だな。(←褒め言葉)
とはいえ、関係ない演算子をしれっとまぎれこませちゃったら失格じゃまいか?
263デフォルトの名無しさん:2012/04/13(金) 09:30:20.96
>>260
マクロを使わなくても、型クラスと多値とモナドが賢い言語なら関数でも書けるんじゃね?
264デフォルトの名無しさん:2012/04/13(金) 09:49:06.63
>>257 map でそれをやれ、というのは無理。

それに hoge を追加することを想定して、
map (hoge . gizz . buzz . fizz) [1, 3, 5, 7, 15, 21, 35, 105] について考える。

関数合成と map の性質より、
map (f . g) [...] = map f (map g [...]) であるから

map (hoge . gizz . buzz . fizz) [1, 3, 5, 7, 15, 21, 35, 105]
 = map hoge (map (gizz . buzz . fizz) [1, 3, 5, 7, 15, 21, 35, 105])
= map hoge [1, "FIzz", "Buzz", "Gizz", "FizzBuzz", "FizzGizz", "BuzzGizz", "FizzBuzzGizz"]

よって hoge が書けない。===== 終 ===== 了 =====

-- という風に論破されちゃうのが嫌な自称上流には嫌われるだろうなぁ、
-- Haskell や形式手法はw
265デフォルトの名無しさん:2012/04/13(金) 10:04:19.47
メソッドの追加は副作用よりも難しい
代入しても型は不変だがメソッドを追加したら型が変わる
266デフォルトの名無しさん:2012/04/13(金) 10:10:13.95
マクロも型クラスも多値もモナドも無いけどSqueak Smalltalkで。

Trait named: #FizzBuzz uses: #() category: 'FizzBuzz-Trait'

FizzBuzz >> fizzBuzzPrep
   self value isString ifFalse: [thisContext sender receiver: self -> ''].

FizzBuzz >> fizzBuzzReturn
   | method nextByte type |
   method := thisContext sender sender method.
   nextByte := thisContext sender sender method at: thisContext sender sender pc.
   type := nextByte // 16.
   ^(type = 13 and: [FizzBuzz selectors includes: (method literalAt: nextByte \\ 16 + 1)])
      ifTrue: [self] ifFalse: [self value ifEmpty: [self key]]

FizzBuzz >> fizz
   self fizzBuzzPrep.
   (self key isDivisibleBy: 3) ifTrue: [self value: self value, 'Fizz'].
   ^self fizzBuzzReturn
FizzBuzz >> buzz
   self fizzBuzzPrep.
   (self key isDivisibleBy: 5) ifTrue: [self value: self value, 'Buzz'].
   ^self fizzBuzzReturn
FizzBuzz >> gizz
   self fizzBuzzPrep.
   (self key isDivisibleBy: 7) ifTrue: [self value: self value, 'Gizz'].
   ^self fizzBuzzReturn

Integer uses: FizzBuzz. Association uses: FizzBuzz.
105 fizz gizz buzz. "=> 'FizzGizzBuzz' "
267デフォルトの名無しさん:2012/04/13(金) 10:18:03.23
>>256 は runFizzBuzz に渡す前までは文字列の蓄積で通してるから、
putStrLn を削るだけでリストになるんじゃね?
268デフォルトの名無しさん:2012/04/13(金) 10:45:33.86
継続使える言語なら書けるんじゃね?
269デフォルトの名無しさん:2012/04/13(金) 11:19:14.13
Scheme使いの登場を待ってるわけ?
てか継続をどう使うことを想定してるの?
270デフォルトの名無しさん:2012/04/13(金) 12:38:39.46
join fs n = case concatMap (\f -> f n) fs of
                        "" -> Left n
                        s -> Right s

fizzT f s n | f n == 0 = s
fizzT _ _ _ | otherwise = ""

fizz = fizzT (`mod` 3) "Fizz"
buzz = fizzT (`mod` 5) "Buzz"
gizz = fizzT (`mod` 7) "Gizz"

main = print $ join [fizz, buzz, gizz] 105
271デフォルトの名無しさん:2012/04/13(金) 12:50:09.96
こっちのほうが join を入れ子に出来て良いかも


import Data.Either

join fs n = case concat $ rights $ map (\f -> f n) fs of
                 "" -> Left n
                 s -> Right s

fizzT f s n | f n == 0 = Right s
fizzT _ _ _ | otherwise = Right ""

fizz = fizzT (`mod` 3) "Fizz"
buzz = fizzT (`mod` 5) "Buzz"
gizz = fizzT (`mod` 7) "Gizz"

main = print $ join [join [fizz, buzz], gizz] 105
272デフォルトの名無しさん:2012/04/13(金) 13:14:50.14
join とか無しで gizz buzz fizz 105 で "FizzBuzzGizz" をさくっと返す方法はないの?
273デフォルトの名無しさん:2012/04/13(金) 13:43:15.17
ここまでruby/python無し
LLに有利っぽいのに
274デフォルトの名無しさん:2012/04/13(金) 13:43:49.58
gizz buzz fizz 105 という式が、ちゃんと型を持っているとする。
また、fizz 105、buzz fizz 105 という式も、同様になんらかの型を持つとする。

すると、

fizz の型は
Int -> a

buzz の型は
(Int -> a) -> Int -> b

gizz の型は
((Int -> a) -> Int -> b) -> (Int -> a) -> Int -> c

というような型でなければならない。無理。というか、どう頑張っても、
先頭に do か何かが要る。
275デフォルトの名無しさん:2012/04/13(金) 13:56:46.55
型システムに制約を受けないパワフルな関数型言語ってのはないもんかね。
276デフォルトの名無しさん:2012/04/13(金) 14:00:17.79
Perlしか読めないから誰かPerlで書いて
277デフォルトの名無しさん:2012/04/13(金) 14:04:41.69
>>275 Erlang ?
278デフォルトの名無しさん:2012/04/13(金) 14:24:54.40
>>273 つーか元出題者が Ruby だとオープンクラスやらなんやら使ってできるぜ、
って言いたいだけで作った問題なのがかなり見え見えなんだが。
279デフォルトの名無しさん:2012/04/13(金) 15:57:16.91
書き込み行数がオーバーするんで適当に圧縮した

module FizzBuzz
SYM_HASH = {} ; def self.add_fizz sym, n ; SYM_HASH[sym] = n ; end
def self.do_it sym, n, prefix ; if m = SYM_HASH[sym]
if n % m == 0
s = sym.to_s ; s.capitalize!
if prefix.kind_of? String then s[0, 0] = prefix end
s.fizzbuzzval = n ; s
else prefix end else nil end
end
end

class Integer ; def method_missing sym
if it = FizzBuzz.do_it(sym, self, self) then it else super end
end end
class String ; attr_writer :fizzbuzzval ; def method_missing sym
if it = FizzBuzz.do_it(sym, @fizzbuzzval, self) then it else super end
end end

FizzBuzz.add_fizz :fizz, 3
FizzBuzz.add_fizz :buzz, 5
FizzBuzz.add_fizz :gizz, 7

p [1, 3, 5, 7, 15, 21, 35, 105].map{|n|n.fizz.buzz.gizz}
280デフォルトの名無しさん:2012/04/13(金) 16:17:23.17
>>276 突貫工事だけれど…

package FizzBuzzGizz;
sub new {
  my ($c, $n) = @_;
  bless {n => $n, s => ''}, $c
}
sub fizz {my $t = shift; $t->{s} .= 'Fizz' if 0 == $t->{n} % 3; $t}
sub buzz {my $t = shift; $t->{s} .= 'Buzz' if 0 == $t->{n} % 5; $t}
sub gizz {my $t = shift; $t->{s} .= 'Gizz' if 0 == $t->{n} % 7; $t}
sub result {my $t = shift; $t->{s} ? $t->{s} : $t->{n}}
1;

package main;

do {
  my $fbg = new FizzBuzzGizz($_);
  print "$_:" . FizzBuzzGizz::result($fbg->fizz->buzz->gizz) . "\n"
  # あるいは print "$_:" . $fbg->fizz->buzz->gizz->result . "\n"
  } for qw{1 3 5 7 15 21 35 105};

$ perl p_fizzBuzzGizz.pl
1:1
3:Fizz
5:Buzz
7:Gizz
15:FizzBuzz
21:FizzGizz
35:BuzzGizz
105:FizzBuzzGizz
281デフォルトの名無しさん:2012/04/13(金) 16:22:11.22
>>280
objectのmethodが返す値はまたobjectだけれど、
printで評価すると判定結果文字列を返すには、
こんな書き方くらいしかないのかな…?
多値のリスト返しでやってみようと思ったけれどうまい方法が思いつかなかったぜよ
282デフォルトの名無しさん:2012/04/13(金) 17:12:42.66
>>281
package FizzBuzzGizz;
sub new {
  my ($c, $n) = @_;
  bless \"$n."
}
sub fizz {my $t=shift; $_=$$t; bless do { /(^\d+)/; 0 == $1 % 3 ? \"${_}Fizz": $t }}
sub buzz {my $t=shift; $_=$$t; bless do { /(^\d+)/; 0 == $1 % 5 ? \"${_}Buzz": $t }}
sub gizz {my $t=shift; $_=$$t; bless do { /(^\d+)/; 0 == $1 % 7 ? \"${_}Gizz": $t }}
1;

package main;

do {
  my $fbg = new FizzBuzzGizz($_);
  print ${$fbg->fizz->buzz->gizz} . "\n"
} for qw{1 3 5 7 15 21 35 105};
283デフォルトの名無しさん:2012/04/13(金) 17:29:05.85
>>272
何縛りのゲームなのかわからんけど、関数合成演算子でも駄目かね?


import Data.Either
import Prelude hiding ((.))

(.) f g n = case concat $ rights [f n, g n] of
                 [] -> Left n
                 s -> Right s

fizzT f s n | f n == 0 = Right s
fizzT _ _ _ | otherwise = Right []

fizz = fizzT (`mod` 3) "Fizz"
buzz = fizzT (`mod` 5) "Buzz"
gizz = fizzT (`mod` 7) "Gizz"

main = print $ fizz.buzz.gizz $ 105
284デフォルトの名無しさん:2012/04/13(金) 17:30:10.61
>>282
package FizzBuzzGizz;
sub new {
  my ($c, $n) = @_;
  bless \"$n."
}
sub comm { my ($t, $r, $s) = @_; $$t =~ /(^\d+)/;
                0 == $1 % $r ? \"${_}$s": $t }
sub fizz {bless comm((shift), 3, 'Fizz')}
sub buzz {bless comm((shift), 5, 'Buzz')}
sub gizz {bless comm((shift), 7, 'Gizz')}
1;

package main;
for (qw(1 3 5 7 15 21 35 105)) {
  print ${new FizzBuzzGizz($_)->fizz->buzz->gizz} . "\n"
}
285デフォルトの名無しさん:2012/04/13(金) 17:31:15.65
Ruby のカオスな部分を前面に押し出して書いてみた

class String
  attr_accessor :srcint
private
  def f(n,s); (@srcint % n == 0) ? (self << s) : (self); end
end
class Integer
private
  def f(n,s); (self % n == 0) ? (s.srcint = self; s) : (self); end
end
class Object
  def fizz; f(3,'Fizz'); end
  def buzz; f(5,'Buzz'); end
  def gizz; f(7,'Gizz'); end
end
p [1,3,5,7,15,21,35,105].map{|n| n.fizz.buzz.gizz }
# => [1, "Fizz", "Buzz", "Gizz", "FizzBuzz", "FizzGizz", "BuzzGizz", "FizzBuzzGizz"]
p [1,3,5,7,15,21,35,105].map{|n| n.fizz.gizz.buzz }
# => [1, "Fizz", "Buzz", "Gizz", "FizzBuzz", "FizzGizz", "GizzBuzz", "FizzGizzBuzz"]
286デフォルトの名無しさん:2012/04/13(金) 17:33:52.32
>>284 ${_}$s←バグ
package FizzBuzzGizz;
sub new {
  my ($c, $n) = @_;
  bless \"$n."
}
sub comm { my ($t, $r, $s) = @_;
                0 == $$t % $r ? \"$${t}$s": $t }
sub fizz {bless comm((shift), 3, 'Fizz')}
sub buzz {bless comm((shift), 5, 'Buzz')}
sub gizz {bless comm((shift), 7, 'Gizz')}
1;

package main;
for (qw(1 3 5 7 15 21 35 105)) {
  print ${new FizzBuzzGizz($_)->fizz->buzz->gizz} . "\n"
}
287デフォルトの名無しさん:2012/04/13(金) 17:45:43.30
>>286 オッチャン、どうせ書くならこうやろ
package FizzBuzzGizz;
sub new { my ($c, $n) = @_;
              bless \"$n." }
sub com { my ($t, $m, $s) = @_;
              bless 0 == $$t % $m ? \($$t.$s): $t }
sub fizz {com(shift, 3, 'Fizz')}
sub buzz {com(shift, 5, 'Buzz')}
sub gizz {com(shift, 7, 'Gizz')}
1;

package main;
for (qw(1 3 5 7 15 21 35 105)) {
  print ${new FizzBuzzGizz($_)->fizz->buzz->gizz} . "\n"
}

大差ないか…
288デフォルトの名無しさん:2012/04/13(金) 17:54:12.60
new FizzBuzzGizz($_) している時点でダメだろ。
289デフォルトの名無しさん:2012/04/13(金) 17:58:22.56
>>288
え?なぜ?
290デフォルトの名無しさん:2012/04/13(金) 18:10:15.39
関係ないオブジェクトにもfizz buzz gizzが継承されてしまう気持ち悪さを除けば、
ちゃんと書けているのは今のところRubyだけって感じか。
文字列オブジェクトにインスタンス変数(状態)を持たせられるのが強みだなぁ。
Smalltalkのはやってることが「独立した関数(メソッド)」と呼ぶにはどーよという内容だから失格。
関数型は型システムの制約でこういう仕様の関数モドキは書けないっていうことでFA?
291デフォルトの名無しさん:2012/04/13(金) 18:22:32.06
>>290
でも実際のところ、こんな書き方したくないけどね
実際にやるなら、何らかのコンテナにラップしてからmapして
それが終わったら、文字列や数値として取り出すと思う
原文がいきなり数値に対してメソッド呼んでるから、容赦なく組み込みクラスを弄ったが…
292デフォルトの名無しさん:2012/04/13(金) 18:30:51.94
JSならやれそうじゃね?
293デフォルトの名無しさん:2012/04/13(金) 18:33:45.54
>>291
まあクイズだからね。言語機能をどう使って無茶な要件をクリアするかのパズルみたいなもん。
294デフォルトの名無しさん:2012/04/13(金) 18:35:01.97
>>292
まずコード出せ。話はそれからだ。
295デフォルトの名無しさん:2012/04/13(金) 18:57:18.70
数値がobjectとしてmethodを持たない言語ではどうするかってお題だったのかよ…
296デフォルトの名無しさん:2012/04/13(金) 19:00:25.49
>>290 自分の足を自分で撃ちたいなら、それに向いた言語ある、という話、でFA
297デフォルトの名無しさん:2012/04/13(金) 19:35:12.73
>>290
RubyはメソッドチェインOKなのに
関数型言語はfizz(buzz(gizz))しか認めないんだろ?
そりゃ静的型じゃ無理っつーか制限する意味が分からん
後からgizz等を追加できる拡張性あるコードを
書けないならともかく、そうでもないしな
298デフォルトの名無しさん:2012/04/13(金) 19:40:42.95
>文字列オブジェクトにインスタンス変数(状態)を持たせられるのが強みだなぁ。

-- String "has-a" Integer
data HasA = HasA String Integer
instance Show HasA where show (HasA s n) = if s == "" then show n else show s
fizz (HasA s n) = HasA (s ++ if mod n 3 == 0 then "Fizz" else "") n
buzz (HasA s n) = HasA (s ++ if mod n 5 == 0 then "Buzz" else "") n
gizz (HasA s n) = HasA (s ++ if mod n 7 == 0 then "Gizz" else "") n
main = print $ map (gizz . buzz . fizz . HasA "") [1,3,5,7,15,21,35,105]
299デフォルトの名無しさん:2012/04/13(金) 19:47:44.31
>>298
似たようなコード書いてたら先に張られてた
個人的には hasA = HasA "" を定義しておくのが好み

それはともかく、.演算子使ってるからケチ付けられると思うぜ多分w
300デフォルトの名無しさん:2012/04/13(金) 19:56:22.62
>>294 おまえはどれかのコード書いたの?
301デフォルトの名無しさん:2012/04/13(金) 20:00:44.98
ここまでJava無し
302デフォルトの名無しさん:2012/04/13(金) 20:30:30.61
JavaScriptできた。俺の使ってるブラウザ以外で動くかどうかはわからん。

var def_fizz = function (name, m) {
var fun = function () {
var tp = typeof this.valueOf();
var n = (tp === 'number') ? this : this.fizzbuzzval
if (n % m === 0) {
var s = name.charAt(0).toUpperCase() + name.slice(1);
if (tp === 'string') {
s = this + s;
}
s = new String(s);
s.fizzbuzzval = n;
return s;
} else {
return this;
}
} ;
Number.prototype[name] = fun;
String.prototype[name] = fun;
} ;
def_fizz('fizz', 3);
def_fizz('buzz', 5);
for (var i = 1; i <= 30; ++i) {
document.writeln(i.fizz().buzz());
}
303デフォルトの名無しさん:2012/04/13(金) 20:36:17.98
304デフォルトの名無しさん:2012/04/13(金) 22:09:50.27
305デフォルトの名無しさん:2012/04/13(金) 22:25:54.85
newはダメらしい…>>288
306 ◆QZaw55cn4c :2012/04/13(金) 22:40:22.27
>>305
ΟΓΖ

基本データ型のリテラル単独でクラスのインスタンスになり得ない言語である以上、new しないことにははじまらない‥‥。
307デフォルトの名無しさん:2012/04/13(金) 22:42:51.66
>>306
newを隠蔽すればいいだけ
308デフォルトの名無しさん:2012/04/13(金) 23:24:10.63
いやいや。基本データ型がオブジェクトでなかったり
組み込みクラスにメソッドを追加できない言語では
普通に関数で実装すればいいと思うよ。gizz( buzz( fizz( n ) ) )みたいに。
309デフォルトの名無しさん:2012/04/14(土) 00:02:15.95
>>308
それが一番シンプルだと思う。
速度も早いだろうしね。
310デフォルトの名無しさん:2012/04/14(土) 00:25:40.80
>>309
それがね、gizz() buzz() fizz()の三関数をどれも特別扱いせず、
いずれの戻り値もいずれの引数となり得る柔軟さを備える仕様にし、かつ
print gizz( buzz( fizz( n ) ) )で
1
"Fizz"
"Buzz"
"Gizz"
"FizzBuzz"
"FizzGizz"
"BuzzGizz"
"FizzBuzzGizz"
という出力を得るのは、以外とマンドくさいのよ。
gizz()だけは文字列を返すなどそれぞれの関数のIFを個別に制約すれば子供の使いなみに楽。
つかこういう要求仕様でnewは使うなとか制限もうけること自体が仕様策定の段階でミスなんだろ。
311デフォルトの名無しさん:2012/04/14(土) 00:32:11.23
その意外と面倒くさいところをどう回避するかがこのクイズの味噌なんだが。(´・ω・`)
312デフォルトの名無しさん:2012/04/14(土) 00:51:08.06
>>299
> .演算子使ってるからケチ付けられると思うぜ多分w

志村! HasA! HasA!
313デフォルトの名無しさん:2012/04/14(土) 01:11:55.03
>>311
そしたら、こうだな。

sub com {
  my ($mod, $zz, $num, $str) = @_;
  $str .= $zz
    if 0 == $num % $mod;
  $str ? ($num, $str) : $num
}
sub fizz {com(3, 'Fizz', @_)}
sub buzz {com(5, 'Buzz', @_)}
sub gizz {com(7, 'Gizz', @_)}

print "$_: " . gizz(buzz(fizz($_))) . "\n"
  for qw(1 3 5 7 15 21 35 105);

実効例:
$ perl p_FizzBuzzGizzAret.pl
1: 1
3: Fizz
5: Buzz
7: Gizz
15: FizzBuzz
21: FizzGizz
35: BuzzGizz
105: FizzBuzzGizz

perlのscalar context/list contextを巧みに?利用してるんで、
それを知らない人には分かりにくいかもしれず、申し訳ないんだか…

※もうちょっと考えて出題して欲しいな、言っちゃ悪いがこういった仕様策定ミスをcodeでカバーすることに何の意味が…
314デフォルトの名無しさん:2012/04/14(土) 01:16:27.94
perlのscalar context/list contextの説明。

関数の引数にフラグを一個追加したもの

つまり、
foo(value, false) ・・・ スカラ呼び出し
foo(value, true) ・・・ リスト呼び出し


foo(value, flag)関数の説明

flagがfalseの場合、スカラタイプの値を返します。
flagがturの場合、リストタイプの値を返します。


まあ、こんなもん。
315デフォルトの名無しさん:2012/04/14(土) 01:24:45.45
>>314
志村、ここ、ここ。

  my ($mod, $zz, $num, $str) = @_;
               ↑

  $str ? ($num, $str) : $num

sub xxx {com(3, 'Fizz', @_)}
              ↑

print "$_: " . gizz(buzz(fizz($_))) . "\n"

print "$_: " , gizz(buzz(fizz($_))) , "\n"
の動作の違い

なんか、中途半端に知っている人が出てきたな…
寝るか…。ノシ
316デフォルトの名無しさん:2012/04/14(土) 01:45:08.21
核の部分はこれだけか
sub com {
 my ($mod, $zz, $num, $str) = @_;
 $str .= $zz if 0 == $num % $mod;
 $str ? ($num, $str) : $num
}
sub fizz {com(3, 'Fizz', @_)}
sub buzz {com(5, 'Buzz', @_)}
sub gizz {com(7, 'Gizz', @_)}
317デフォルトの名無しさん:2012/04/14(土) 02:13:05.47
Perlは良く知らないのだが、
print が ($num, $str) の $num を都合よく読み捨ててくれるのは何故?
print fizz(3) の出力は、3Fizz になりそうに思うんだが。よーわからん。
318デフォルトの名無しさん:2012/04/14(土) 02:16:18.43
319デフォルトの名無しさん:2012/04/14(土) 02:40:58.54
>>317
結局 Perl のはこのクイズの要求には到達できてなくて(関数単体では完結できていない)、
出力時の文字列との結合でごまかしているってカラクリ。map とかすればズルが露呈する。
320デフォルトの名無しさん:2012/04/14(土) 02:52:04.92
>>319
ズルはしてないよ。返戻contextの何番目を数値、何番目を文字列とし後続を省略時はundefとなる
利用しているだけでこういうやり方は使うときは使う。
でも、こういうズレたクイズはもういいよ。
関数型言語、オブジェクト指向言語の比較としてこの題材がどういう意味を持っているの?
これ単に>>297とか排除して特定の機能を持った言語を有利に導きたかっただったんじゃない?
321デフォルトの名無しさん:2012/04/14(土) 03:04:43.03
じゃあ、map版です。

use 5.12.0;
sub com {
  my ($mod, $zz, $num, $str) = @_;
  $str .= $zz ;if 0 == $num % $mod;
  $str ? ($num, $str) : $num
}
sub fizz {com(3, 'Fizz', @_)}
sub buzz {com(5, 'Buzz', @_)}
sub gizz {com(7, 'Gizz', @_)}

map{say "$_: " . gizz(buzz(fizz($_)))} qw(1 3 5 7 15 21 35 105);
322デフォルトの名無しさん:2012/04/14(土) 03:07:01.05
>>321
しくったorz、ifの前の;が余計だった。

use 5.12.0;
sub com {
  my ($mod, $zz, $num, $str) = @_;
  $str .= $zz if 0 == $num % $mod;
  $str ? ($num, $str) : $num
}
sub fizz {com(3, 'Fizz', @_)}
sub buzz {com(5, 'Buzz', @_)}
sub gizz {com(7, 'Gizz', @_)}

map {say "$_: " . gizz(buzz(fizz($_)))} qw(1 3 5 7 15 21 35 105);
323デフォルトの名無しさん:2012/04/14(土) 03:07:30.38
そっちじゃなくて、print時の文字列連結による$numの読み飛ばしの件についてでしょ。
print "$_: " , gizz(buzz(fizz($_))) , "\n"
だと 3: 3Fizz とかなる。
324デフォルトの名無しさん:2012/04/14(土) 03:14:00.28
>>323
「gizz,buzz,fizzの三関数をscalar contexで評価すると判定文字列が得られ
 list contextで評価すると数値と判定文字列のリストが得られる関数である
 ただし数値が3,5,7の倍数でない場合は返戻リストの第二要素の判定文字列は
 undef(文字列として評価すると空文字列)」
という仕様の関数として書いている。

のだよ。code嫁よ。
325デフォルトの名無しさん:2012/04/14(土) 03:17:44.46
>>297の主張もじっさい意味不明なんだけど。。。
メソッドチェーンっていうのは関数の入れ子の呼び出し gizz(buzz(fizz(n))) と実質同じだろ?
組み込みの関数合成関数の使用を禁じている訳ではないのだから、要求通り関数で完結できてさえいれば
それらを合成しようがぜんぜん問題ないし、型システムのモデルが足を引っ張っている以外、
なにが不利なのかさっぱり分からん。Perl のズル同様で、関数で完結できてないくせに
合成関数のオーバーロードでつじつまを合わせようとするからなんだかなーとなる。
326デフォルトの名無しさん:2012/04/14(土) 03:19:31.46
>>322
"$_: " . ってのを無しでやっみてくんない?
327デフォルトの名無しさん:2012/04/14(土) 03:21:01.17
>>325
ずれてないよ。
値と評価文字列をlistdで返戻する。
scalarで評価するかlistで評価するかで
返戻を両方参照するか、そのうちの判定文字列だけを印字出力などのために使うか
選択しているだけだよ。
328デフォルトの名無しさん:2012/04/14(土) 03:25:52.86
>>326
sub com {
  my ($mod, $zz, $num, $str) = @_;
  $str .= $zz if 0 == $num % $mod;
  $str ? ($num, $str) : $num
}
sub fizz {com(3, 'Fizz', @_)}
sub buzz {com(5, 'Buzz', @_)}
sub gizz {com(7, 'Gizz', @_)}

map {print gizz(buzz(fizz($_))) . "n"} qw(1 3 5 7 15 21 35 105);
329デフォルトの名無しさん:2012/04/14(土) 03:27:01.29
ニヤニヤ
330デフォルトの名無しさん:2012/04/14(土) 03:27:10.20
Perlは醜いラクダどころか白鳥だったのか
他の言語の立場がないな
331デフォルトの名無しさん:2012/04/14(土) 03:27:54.81
>>328
しくった。

"n" → "\n"
332デフォルトの名無しさん:2012/04/14(土) 03:38:24.58
天然?
333デフォルトの名無しさん:2012/04/14(土) 03:41:23.69
いや、コピペミスw
334デフォルトの名無しさん:2012/04/14(土) 03:43:40.92
多数値の返り値の、主値かそれ以外か、を使う手があるわけか
335デフォルトの名無しさん:2012/04/14(土) 03:43:48.91
>scalarで評価するかlistで評価するか

そんなの認めるんなら、C++だと型キャストのオーバーロードがあるから楽勝じゃねーか。
operator const char*();
operator const int();
こんなんすりゃ良いんだろ?
ちなみに当たり前にオーバーロードがあるから、Fizz(3)とFizz(FizzBuzzObj)との区別もつくし。
C++ですら出来るんなら、この話もう終わりになっちまうじゃねーか。
336デフォルトの名無しさん:2012/04/14(土) 03:45:12.07
しかし、ruby以外はズル、という結論にしたくて必死らしいが、
むしろrubyやJavaScriptがチートだろw

リフレクション使いまくってるしw
337デフォルトの名無しさん:2012/04/14(土) 03:46:02.04
>>335
書け書け。だれもC++をけなしてないぞw
後出しじゃんは、なしね。
338デフォルトの名無しさん:2012/04/14(土) 03:59:30.30
>>337
すでに >>261 に書いた。
339デフォルトの名無しさん:2012/04/14(土) 04:40:06.83
C++の>>261がありなら
Haskellの>>283もありだよな
ていうか、>>325がズルと言ってるの理由がさっぱり分からん
演算子オーバーロードのある言語でそれ使って何が悪いの?

別にmapもできるぜ?
main = print $ map (fizz.buzz.gizz) [1,3,5,7,15,21,35,105]
340339:2012/04/14(土) 05:12:10.70
まあいいや、関数合成のオーバーロードは無しで
>>312の言う通りHasAも隠蔽すれば良いんだな?

data HasA = HasA String Integer deriving Eq

instance Show HasA where
  show (HasA s n) = if s == "" then show n else s

instance Num HasA where
  (+) (HasA r m) (HasA s n) = HasA (r ++ s) (m + n)
  (-) (HasA r m) (HasA s n) = HasA "" (m - n)
  (*) (HasA r m) (HasA s n) = HasA "" (m * n)
  negate (HasA s n) = HasA s (-n)
  abs (HasA s n) = HasA s (abs n)
  fromInteger n = HasA "" n
  signum (HasA s n) = HasA s (signum n)

fizz (HasA s n) = HasA (s ++ if mod n 3 == 0 then "Fizz" else "") n
buzz (HasA s n) = HasA (s ++ if mod n 5 == 0 then "Buzz" else "") n
gizz (HasA s n) = HasA (s ++ if mod n 7 == 0 then "Gizz" else "") n

main = print $ map (gizz . buzz . fizz) [1,3,5,7,15,21,35,105]
341デフォルトの名無しさん:2012/04/14(土) 05:12:11.99
F#で演算子オーバーロードなし。

let threadLocal = new System.Threading.ThreadLocal<_>()

let makeFizzBuzz name condition (x : obj) =
    match x with
    | :? int as number ->
        threadLocal.Value <- number
        if condition number then box name else box number
    | :? string as names ->
        box (if condition threadLocal.Value then names + name else names)
    | _ -> failwith "ロジックエラー"

let fizz = makeFizzBuzz "Fizz" (fun x -> x % 3 = 0)
let buzz = makeFizzBuzz "Buzz" (fun x -> x % 5 = 0)
let gizz = makeFizzBuzz "Gizz" (fun x -> x % 7 = 0)

> [1; 3; 5; 7; 15; 21; 35; 105] |> List.map (fun x -> gizz(buzz(fizz x)));;
val it : obj list =
  [1; "Fizz"; "Buzz"; "Gizz"; "FizzBuzz"; "FizzGizz"; "BuzzGizz"; "FizzBuzzGizz"]
342デフォルトの名無しさん:2012/04/14(土) 05:26:59.93
さーて、また関数型言語が不利になるルールが追加されるよー
343デフォルトの名無しさん:2012/04/14(土) 05:45:13.46
次は関数型言語使いがお題を出したらいいんじゃないか
Rubyじゃこんなの書けないだろ的なのを
スレタイの趣旨にも沿ってる
344デフォルトの名無しさん:2012/04/14(土) 05:58:16.50
それ以前に「使える言語機能を恣意的に制限する」アホを
排除しておかないと比較にも議論にもなんねーんだよ
345デフォルトの名無しさん:2012/04/14(土) 05:59:25.03
じゃあ、型的に間違ってるプログラムをコンパイルエラーにしてください、という問題はどうだろうか。

fizzbuzzのscheme多値版ね。マクロ使っちゃっちゃったけど。

(define-syntax fizz (syntax-rules () ((_ arg) (receive it arg (fuzzbuzz it "Fizz" 3)))))
(define-syntax buzz (syntax-rules () ((_ arg) (receive it arg (fuzzbuzz it "Buzz" 5)))))
(define fuzzbuzz
(lambda (arg name m)
(let* ((is-num (null? (cdr arg))) (s (if is-num "" (car arg))) (a (if is-num (car arg) (cadr arg))))
(if (= 0 (mod a m)) (values (string-append s name) a) (if is-num a (values s a))))))
(define main (lambda (_) (letrec ((loop (lambda (n) (if (<= n 30)
(begin (print (buzz (fizz n))) (loop (+ n 1))))))) (loop 1))))
346デフォルトの名無しさん:2012/04/14(土) 06:40:24.02
ループ禁止で再帰だけで書いてください、とかでも良いな
末尾再帰最適化の無い実装じゃスタックオーバーフロー
347デフォルトの名無しさん:2012/04/14(土) 06:51:51.42
>>325
組み込みクラスを弄るのはOK
組み込み演算子を弄るのはNG

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

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

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

という現実を反映しているだけ。
349デフォルトの名無しさん:2012/04/14(土) 10:10:56.56
そしてモマエは
3向上心のカタマリのオレ様にケンカうってんのかーーー
カワネーゾ
350デフォルトの名無しさん:2012/04/14(土) 10:28:07.46
>>343
いまは人工的に作ったお題の信用がなくなってるんだよ
そこでまた中立でない人間がお題を出しても、紙屑のように無視されるんじゃないの
351デフォルトの名無しさん:2012/04/14(土) 10:47:19.60
>>306
QZってこんなスレまで見てるんだな
352デフォルトの名無しさん:2012/04/14(土) 11:03:19.87
>>350
>>290>>325のような上から目線で変なルール押し付けてくるウザいヤツが
居なければ、言語ごとのアプローチの違いが見れて
遊びとしては面白いんだがなぁ
しかもウザいのに限って口だけでプログラム書けないんだ

あ、もしかして>>290>>325がこのスレに書いたコード在る?だったら謝るけど
353デフォルトの名無しさん:2012/04/14(土) 11:31:51.96
すまんけどちょっと確認させてください。これまで出てきた関数型言語の回答で、
関数合成演算子(あるいは関数)を定義が必須な場合でも、関数 fizz だけ用いた
fizz 1 や fizz 3 はちゃんと組み込み型の数値や文字列である 1 や "Fizz" を返せるのでしょうか?
これって一応要件だと思うんですよね。C++ の回答についても同様です。
Ruby や JS 、Smalltalk の回答はすべてこれが出来ているみたいなんだけど。
354デフォルトの名無しさん:2012/04/14(土) 11:49:35.83
C++は型キャストをカスタマイズできるからそれで対応したら良いと思う。
FizzBuzzオブジェクトから文字列型と数値型へのキャストをそれぞれ用意すればよし。
355デフォルトの名無しさん:2012/04/14(土) 12:28:02.63
>>352
今でも十分おもしろいと思うよ。せっそうのない動的言語(OOといえばOOだけど、
ストラウストラップの抽象データ型OOでなくて、ケイの動的OO寄りの考え方)では
可能だけど、理論的にきっちりした関数型言語では実現不可な境界がはっきりしてきてて。
出来ないと分かっていることを出来ないときちんと理由付きで示せる勇気も見れるし。
他方で、動的言語でもすんなりできるとは限らないから各言語での工夫の仕方も興味深い。
356デフォルトの名無しさん:2012/04/14(土) 12:29:01.02
>>353
>>341だけど、関数fizz, buzz, gizzをそれぞれ単独で使用した場合をテスト。
> [fizz; buzz; gizz] |> List.map(fun f -> [1; 3; 5; 7] |> List.map f);;
val it : obj list list =
[[1; "Fizz"; 5; 7]; [1; 3; "Buzz"; 7]; [1; 3; 5; "Gizz"]]
357デフォルトの名無しさん:2012/04/14(土) 13:02:32.74
あ、すいません。F#さんを見落としていました。
F#以外の関数型言語の回答で、ですね!
わざわざの検証、いたみいります。
358デフォルトの名無しさん:2012/04/14(土) 14:04:34.17
スレッドローカルに状態を保持するのはいいアイデアですね。
359デフォルトの名無しさん:2012/04/14(土) 14:10:22.10
いいアイデアですねw
360デフォルトの名無しさん:2012/04/14(土) 14:42:43.34
>>353
>>340だけどテストしてみた

*Main> [map f [1,3,5,7] | f <- [fizz, buzz, gizz]]
[[1,Fizz,5,7],[1,3,Buzz,7],[1,3,5,Gizz]]
361デフォルトの名無しさん:2012/04/14(土) 14:50:32.97
>>353
ついでに>>283もテスト
正しく動かなかったので修正

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

これで >>360と同じコードが動いた
362361:2012/04/14(土) 15:07:31.88
面白かったのは>>283>>360を試して動かなかったとき
ちゃんとコンパイル時に型エラーになったこと
Haskellの型システムやるじゃん、みたいな
363デフォルトの名無しさん:2012/04/14(土) 15:54:35.13
ねえねえ、1 から 3 までの fizz n の戻り値に対して、文字列なら全大文字化、整数なら 10 倍にして
map するコードを [1, 2, "Fizz"] に対して同じことをするコードとまったく同様に書いて
問題なく実行できるかどうか試しみててよ! クイズの要件をみたしていればできるよね!
もちろんいうまでもなく追加定義や修正は無しだよ。Ruby や F# のはもちろんできるよ!
364340:2012/04/14(土) 16:01:06.17
>>360
fizz (HasA s n) = HasA (s ++ if mod n 3 == 0 then "Fizz" else "") (10 * n)
365340:2012/04/14(土) 16:02:40.14
あ、ごめん>>363だった
それはさておき、後だしでルール追加するの本当に好きだね
366デフォルトの名無しさん:2012/04/14(土) 16:06:40.84
>>363
じゃあ、組み込みクラスをグローバルに汚染するのも禁止しようぜ
classbox等で一部に制限できるならアリ
367デフォルトの名無しさん:2012/04/14(土) 16:07:57.17
というか、ここのHaskellerはどうしてこうも要求仕様を読み取れないくせに
あまつさえ勝手な解釈で適当なコード書いてドヤ顔なの? バカなの? 死ぬの?
368デフォルトの名無しさん:2012/04/14(土) 16:11:06.66
>>367
誰もお前の頭の中なんて知らないし興味ないんだから
言わないと分からないっつーの
ここはお前の要求仕様を満たす場じゃねーし
馬鹿はお前

あと、まさかコードも書かずに議論参加してたとか無いよな
書いたコードのレス示せよ
俺は>>340書いたぞ
369デフォルトの名無しさん:2012/04/14(土) 16:16:29.12
(defmacro defun-fizz-buzz (name divisor)
`(defmacro ,name (form)
`(multiple-value-bind (int str) ,form
(values int
(if (= (mod int ,',divisor) 0)
(concatenate 'string str (string ',',name))
str)))))

(defun-fizz-buzz fizz 3)
(defun-fizz-buzz buzz 5)
(defun-fizz-buzz gizz 7)
370デフォルトの名無しさん:2012/04/14(土) 16:21:51.37
>>367
> ドヤ顔なの?バカなの? 死ぬの?
w
いまどき、こんな台詞をわざわざ書くやつがいるんだww
371デフォルトの名無しさん:2012/04/14(土) 16:23:54.35
勘違いしたふりして頓珍漢なコード出してきて、
言語や自分の発想の限界とかクリティカルなところはなんとか避けようとしているんだよ。
仕様を取り違えてるよってやんわりチェック方法をしめすと、
ルールを増やすな、後出しだ、仕様が欠陥だってなんやかやクレームつけて
相手が根負けして要求仕様のほうが変わるのを粘り強くじっと待つ戦略なんだ。
ある意味、賢いよ。
372デフォルトの名無しさん:2012/04/14(土) 16:26:54.36
お題提出者の解答ってもう出てるの?
373デフォルトの名無しさん:2012/04/14(土) 16:29:32.45
>>363
> map するコードを [1, 2, "Fizz"] に対して同じことをするコードとまったく同様に書いて

Haskellは静的型付けだから数と文字列を同じリストには入れられないんだ
そんなことも知らずに議論してたんじゃないよね?
374デフォルトの名無しさん:2012/04/14(土) 16:32:03.01
>>371

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

って書いてるのに示さないってことは、まさか本当にコード書いてなかったの?
375デフォルトの名無しさん:2012/04/14(土) 16:33:37.46
まさかの口だけ野郎説浮上www
376デフォルトの名無しさん:2012/04/14(土) 16:44:57.11
>>363は問題が頓珍漢だけど(静的型で [1, 2, "Fizz"] はねーよw)
最大限エスパーして書いてみた

>>283はこんな感じ

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

>>340はこんな感じ

conv (HasA s n) = HasA (map toUpper s) (10 * n)
main = do
  print $ map conv [1, 2, "Fizz" `HasA` 3]
  print $ map conv $ map fizz [1,2,3]
377デフォルトの名無しさん:2012/04/14(土) 17:03:29.49
>> xs = (1..3).map{ |n| n.fizz }
=> [1, 2, "Fizz"]
>> xs.map{ |x| case x when Integer then x*10 when String then x.upcase end }
=> [10, 20, "FIZZ"]
>> ys = [1, 2, "Fizz"]
=> [1, 2, "Fizz"]
>> ys.map{ |x| case x when Integer then x*10 when String then x.upcase end }
=> [10, 20, "FIZZ"]
378デフォルトの名無しさん:2012/04/14(土) 17:45:03.77
◆QZaw55cn4c が出てきて有耶無耶になってるけど
「Javaドカタはコード書けない」説はまだ有効
379デフォルトの名無しさん:2012/04/14(土) 17:57:01.51
◆QZaw55cn4c はドカタではないとでも
380デフォルトの名無しさん:2012/04/14(土) 18:26:18.94
Haskellでコード書くだけで天才になれた気がした15の夜
381デフォルトの名無しさん:2012/04/14(土) 18:49:30.59
敵はハスケラだけと思ってるところがウケるw
どんな言語使いから見ても口だけ野郎は最底辺のゴミだぞwww
382デフォルトの名無しさん:2012/04/14(土) 18:52:07.05
おまえもなw
383デフォルトの名無しさん:2012/04/14(土) 19:54:38.00
コード書けないドカタは「なでしこ」使えば良いんじゃないか?
運が良ければ日本語で書いた戯れ言が
実行されるかもしれないぞ
384デフォルトの名無しさん:2012/04/14(土) 21:39:02.30
>>383
お前は詳しそうだな、その言語。
興味持って使ってみたのか?w
385デフォルトの名無しさん:2012/04/15(日) 10:22:56.77
まだPythonは出てなかったので


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

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

print [fizz(buzz)(gizz)(x) for x in [1,3,5,7,15,21,35,105]]
386デフォルトの名無しさん:2012/04/15(日) 10:31:36.36
F#、さすがだな。
387デフォルトの名無しさん:2012/04/15(日) 10:48:20.05
>>385
可能なら、
gizz(buzz(fizz(105))) is "FizzBuzzGizz" となるようなヤツをお願いします。
388デフォルトの名無しさん:2012/04/15(日) 10:55:31.60
>>387
理由を聞いても良い?
Pythonでは>>385のほうがデコレータでも使えて良いんだけど……

@fizz
@buzz
def bizz(x):
    if x % 11 == 0: return 'Bizz'
    else: ''
389デフォルトの名無しさん:2012/04/15(日) 11:03:37.43
静的型言語にIntを返したりStringを返したりする関数って縛りがそもそも無理
390デフォルトの名無しさん:2012/04/15(日) 11:07:14.65
391デフォルトの名無しさん:2012/04/15(日) 11:08:32.55
PerlとかSchemeの、多値をうまく使ったのが一番エレガントかな。

RubyとかJSは、同じようなコードをStringとNumberの両方に生やすとか、
見事に汚い解だw
392デフォルトの名無しさん:2012/04/15(日) 11:13:32.41
関数を返す関数(カリー化されてりゃ普通)にケチがつくとか
スゲーなこのスレ
393デフォルトの名無しさん:2012/04/15(日) 11:16:23.31
>>390
ちゃんと「など」って書いてるぞー

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

それとも高階関数は関数じゃないんですかー
394デフォルトの名無しさん:2012/04/15(日) 11:20:37.25
>>389
それだけじゃない。
継続の状態如何で関数に振る舞いを変えさせるとか
関数型には無理な事ばかり要求している。
悪意に満ちたクイズだ。
395デフォルトの名無しさん:2012/04/15(日) 11:23:20.66
>>394
素直に考えれば、オープンクラスのある言語が良いという
意見に持っていきたい問題だからね

でも出てきた解はRubyが一番汚いという
396デフォルトの名無しさん:2012/04/15(日) 11:25:11.88
>>389
型クラスとかってこういう時には使えないの?
397デフォルトの名無しさん:2012/04/15(日) 11:30:40.55
要求による。

問題の「#=> "FizzBuzz"」が意味しているものが、REPLでそのように表示されるもの、
という意味なら、Show型クラスでいいんだけど、String型([Char]型)を要求してるなら無理。
398デフォルトの名無しさん:2012/04/15(日) 11:32:07.68
静的型 vs 動的型スレ向きの問題だよね
399デフォルトの名無しさん:2012/04/15(日) 11:52:01.47
>>391
いやあ俺は>>341のF#(er)が一番エレガントだと思うぞ。
無茶な要求仕様も黙ってすべて満たしつつ、簡潔できれいなコード出してきてるし。
400デフォルトの名無しさん:2012/04/15(日) 11:57:38.79
>>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))));}
402デフォルトの名無しさん:2012/04/15(日) 12:22:36.47
>>368
>あと、まさかコードも書かずに議論参加してたとか無いよな

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

このスレの特徴まとめ
403デフォルトの名無しさん:2012/04/15(日) 12:34:01.13
>>399
グローバル変数ではまずいと考えてThreadLocalにしたみたいに見える
まずいという認識がありながら、それを上に報告しないのはおかしい
結局、要求に対する不平不満は正直に言えばいいんだよ
404デフォルトの名無しさん:2012/04/15(日) 12:52:12.22
コード書けないドカタとプログラマでは綺麗さの認識が違う
405デフォルトの名無しさん:2012/04/15(日) 13:06:57.34
そうだね
お前のコードかけないドカタって概念がおかしいけどねw
406デフォルトの名無しさん:2012/04/15(日) 13:29:07.47
>>405
あれ?まだこのスレに居たの?
派遣仕事で使い慣れたJavaを使って良いから
早くエレガントな解を出してくださいよwww
407デフォルトの名無しさん:2012/04/15(日) 13:32:57.13
くやしいんだねw
408デフォルトの名無しさん:2012/04/15(日) 13:55:54.00
仕事しろ。言語の勉強はするだけ無駄。

求められているのは動くアプリだ。
409デフォルトの名無しさん:2012/04/15(日) 14:23:06.70
そもそも関数としての体をなしてないのだから、
副作用を使わずにこのクイズは解けない。
よって純粋な関数型パラダイムでは対応不可。終了。
410デフォルトの名無しさん:2012/04/15(日) 14:32:35.61
Scalaならいろいろ駆使して書けそうだけどな
411デフォルトの名無しさん:2012/04/15(日) 14:38:59.15
>>393
この場合の「など」は、関数呼び出しにもいろいろありますよね、
buzz(fizz(3)) 、 (buzz (fizz 3)) 、buzz fizz 3 など―とかの「など」だと思われ。
412デフォルトの名無しさん:2012/04/15(日) 15:23:11.97
関数じゃないものを
関数型言語で作るには
どうしたらいいのだろうか?
413デフォルトの名無しさん:2012/04/15(日) 15:27:19.67
>>409
副作用なしに解いたSchemeさんが涙目です
414デフォルトの名無しさん:2012/04/15(日) 15:35:03.47
>>411
三つ目が>>385だね(カリー化されてれば)
それとも見た目だけの問題?
415デフォルトの名無しさん:2012/04/15(日) 16:42:00.03
F#でThreadLocal等の副作用もないバージョン。

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

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

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

> main { return [1; 3; 5; 7; 15; 21; 35; 105] |> List.map (fun x -> gizz(buzz(fizz x))) };;
val it : obj list =
  [1; "Fizz"; "Buzz"; "Gizz"; "FizzBuzz"; "FizzGizz"; "BuzzGizz"; "FizzBuzzGizz"]
416デフォルトの名無しさん:2012/04/15(日) 17:46:44.23
新ルール「カリー化禁止」
417デフォルトの名無しさん:2012/04/15(日) 17:53:43.12
>>415
mainがダウト、なんじゃないか?
418デフォルトの名無しさん:2012/04/15(日) 18:08:11.82
>>417
main { return ... } 部分をただのコードブロックとみせかけて
実は戻り値を変換しているという作戦だったのに、バレたか。
419デフォルトの名無しさん:2012/04/15(日) 18:31:37.86
Smalltalkが流行らないように関数型メインは流行らないよ
420デフォルトの名無しさん:2012/04/15(日) 18:34:04.58
ついに「流行らない」以外に縋るものがなくなっちゃったか
421デフォルトの名無しさん:2012/04/15(日) 18:34:51.92
副作用ありとは言え、唯一まともな解出しててF#△だったのに
この期に及んで汚ないチートとかなにこのものすごい残尿感。
422デフォルトの名無しさん:2012/04/15(日) 18:40:05.54
.NET発表時のHaskell.NETはどこに行ったんだよ?
423デフォルトの名無しさん:2012/04/15(日) 18:43:46.95
マクロ使っていいならそもそも多値なんぞ使わんでも楽勝だろ。
424デフォルトの名無しさん:2012/04/15(日) 18:47:39.47
FizzBuzzって流行ってるけど何が面白いの?
425デフォルトの名無しさん:2012/04/15(日) 18:52:45.85
低能はFizzBuzzすら書けないという事実が面白い
426デフォルトの名無しさん:2012/04/15(日) 18:53:02.18
>>423 具体的にドーゾ
427デフォルトの名無しさん:2012/04/15(日) 19:04:47.51
オープンクラスとか副作用有り等の
汚いコードだけが「合格」www

勝手に判定してる(コード書けない)バカのセンスが露呈してますな
428デフォルトの名無しさん:2012/04/15(日) 19:05:21.22
>>423
perl書いたのオレなんだけれどもさ、その通りなんだよな…
429デフォルトの名無しさん:2012/04/15(日) 19:08:10.88
C#とかも関数型言語のエッセンスを取り入れるけど
すげえ無理矢理くさくて笑えるw
関数型がオブジェクト指向を取り入れるのはもっと自然なのに

オブジェクト指向っていうかC系列はもう駄目なんだと思う
430デフォルトの名無しさん:2012/04/15(日) 19:18:55.29
守らなければならない資産がたくさんあるからな
そりゃ無理やりくさくもなるさ
431デフォルトの名無しさん:2012/04/15(日) 19:28:01.70
後付で入れなきゃならなくなる時点で失敗だったはずなんだけどなぁ。
最近のC#の機能なんてC#以前から概念として存在してたはずなのに。
必要ないという当初の目論見は外れてるわけだ。

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

C++、Java、C#、D言語
このへんは全て老害でしょ。
432デフォルトの名無しさん:2012/04/15(日) 19:30:26.05
C#、D言語は設計に一貫した思想がないからアホっぽくなるのは仕方ない。
433デフォルトの名無しさん:2012/04/15(日) 19:41:07.47
fizz 1 -- "1"
fizz 3 -- "Fizz"
buzz 5 -- "Buzz"
buzz fizz 15 -- "FizzBuzz"
だったらHaskellでも解ける?
434デフォルトの名無しさん:2012/04/15(日) 19:45:23.42
可変長引数とかさーー
435デフォルトの名無しさん:2012/04/15(日) 19:50:00.84
>>431
C系列でまともなのはCだけ
436デフォルトの名無しさん:2012/04/15(日) 19:50:26.06
>>433
型の不整合が生じるから無理
437デフォルトの名無しさん:2012/04/15(日) 19:52:02.10
>>432
C#はどんどんダメな方向に向かってる気はするわー。
438デフォルトの名無しさん:2012/04/15(日) 20:01:50.15
Javascriptは結構好きなのよん > C系文法族
439デフォルトの名無しさん:2012/04/15(日) 20:11:47.98
440デフォルトの名無しさん:2012/04/15(日) 20:19:32.18
>>431
後付で入れてもらったのがScala、Clojure、F#でしょ
なんで後付を悪く言うのかな
441デフォルトの名無しさん:2012/04/15(日) 20:41:24.35
C#は言語設計に一貫性がなく節操のないところが最大の魅力
偉い人にはそれがわからんのです
442デフォルトの名無しさん:2012/04/15(日) 21:08:30.57
>>440
アホか
それらは最初から関数型言語として作られてるでしょ。
関数型は糞、オブジェクト指向最高ってスタンスで作ってたはずのもんが
なんで今更関数型の要素を入れようとするんだよ。
443デフォルトの名無しさん:2012/04/15(日) 21:16:51.80
>>439
オーバーライドした toString() を println() に暗黙に呼ばせるとかいう
使い古されたチートをキメ顔で出してこられても…。
new myInteger(3).fizz() が "Fizz" を返せるとか少しは挑戦しようよ。
444デフォルトの名無しさん:2012/04/15(日) 21:17:08.32
「.Netファミリーに関数型言語入ったからC#でも使えるようにすっか!」
くらいのノリだろ。たぶん
dynamic型導入したときもそんな感じだったし
445デフォルトの名無しさん:2012/04/15(日) 21:18:37.55
いやC#の場合は「C#で〜が出来ないと言わせない」という一貫した姿勢があると思う。
もともとJavaへの嫉妬から始まった言語だし。
446デフォルトの名無しさん:2012/04/15(日) 21:21:52.66
>>442
手続き型言語がまずあって、
そこへOOの機能を取り入れた。
こんどはさらに関数型の機能も取り入れようとしているだけ。
447デフォルトの名無しさん:2012/04/15(日) 21:40:30.50
C#厨ってVB.NETをVB厨のための言語って馬鹿にしてたけど
C#だってCっぽくないとヤダヤダっていう老害のために
無理矢理作ってるんだから全然人のこといえねーわ。
ラムダとかそんなに良いんならなんで最初から関数型言語使わないんだよw
448デフォルトの名無しさん:2012/04/15(日) 21:46:15.09
>>442
> 関数型は糞、オブジェクト指向最高ってスタンスで作ってたはずのもんが
> なんで今更関数型の要素を入れようとするんだよ。

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

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

りんごの方程式とは何か?を考えれば
オブジェクト指向と関数型の関係がわかるだろう。
449デフォルトの名無しさん:2012/04/15(日) 21:48:54.81
C#作った奴らはvoidを型と思っていなかった。
だから、C#じゃクロージャ作るのに引数や戻り値にvoidがあると作れないw
やるには予めデリゲートを定義しなきゃならん。
クロージャを使うのを考えさせられる。
ありえん。手軽さが全然ない。

F#はローカル変数(厳密には違うが)を定義するのもクロージャを定義するのも同じ手間しかかからない。
クロージャをバンバン使っていけるのでクロージャの応用もどんどん閃ける。
F#やった方がC#が上手くなるという現実。
C#はやればやるほど馬鹿になる言語。
450デフォルトの名無しさん:2012/04/15(日) 21:50:04.90
速度やメモリ・言語ごとの風習で最適かどうかは変わるのだろうけれど、
関数型でOOPをするときは、返り値として変更したオブジェクトを返すより、新たなオブジェクトを返したほうが関数型ぽいのかね?
451 ◆QZaw55cn4c :2012/04/15(日) 21:51:05.55
>>447
F#のことも思い出してあげてください
452デフォルトの名無しさん:2012/04/15(日) 21:59:08.45
関数型言語でWindowsアプリを開発したいっつー需要がどれだけあるかだな
453デフォルトの名無しさん:2012/04/15(日) 22:00:17.15
>>442
どちらが糞でどちらが最高かなんて、問い詰められても答えなくていいと思うんだが
沈黙が正解って小学生でも知ってる奴は知ってるだろ
454デフォルトの名無しさん:2012/04/15(日) 22:54:52.02
>>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 をオーバーライドする、ってこういうときには普通にすることだと思っていたんですが、何かまずい問題でもあるのでしょうか?
455デフォルトの名無しさん:2012/04/15(日) 23:40:26.22
トイプログラムしか書かない奴は言語なんて何でもいいだろw
456デフォルトの名無しさん:2012/04/15(日) 23:47:29.56
>>443
>>303 の方針でがんばってみました。gizz() は最後に置かなければならない、と決めうちすることにしました。
http://toro.2ch.net/test/read.cgi/tech/1313183984/194
457デフォルトの名無しさん:2012/04/15(日) 23:49:17.32
苦しいねぇ
458デフォルトの名無しさん:2012/04/15(日) 23:50:41.61
>>454
> fizz() が "Fizz" を返してしまうと、もとの String("3") を忘れてしまい、buzz(), gizz() が処理できない

その一見回避不可能な問題を解決する方法を考えるのがこのクイズがクイズたるゆえんです。
言語によっては型システムの制約によりどうやっても実現できないこともあります。
459デフォルトの名無しさん:2012/04/16(月) 00:02:21.18
>>450
関数型に限らず、GCのあるOOPLだと
属性変更をせずに新規オブジェクトをサクサク作るやり方も結構使うね
460デフォルトの名無しさん:2012/04/16(月) 00:45:51.08
>>454
>>341の方法(元の数値をどこかにメモしておいて適宜参照)はJavaでも使えます。
461デフォルトの名無しさん:2012/04/16(月) 01:11:55.59
>>458
OOとPFの言語比較としてこのようなクイズを出したのは、
どのような観点からこれら両者のパラダイムの優劣を比較しようとしたのか
聞きたい
462デフォルトの名無しさん:2012/04/16(月) 01:13:44.79
もうこのお題はcloseでいいんじゃないの?
このクイズではせっかくの労力を生産的でないことに費やしている
463デフォルトの名無しさん:2012/04/16(月) 01:30:58.12
>>462
クイズなんかそんなもんだろ。しょせん暇つぶし。
つーか、こんな程度のクイズ解くのに「労力」なんか大仰なもん必要か?
464デフォルトの名無しさん:2012/04/16(月) 01:38:59.77
このクイズのくだらなさはかなり問題。
465デフォルトの名無しさん:2012/04/16(月) 01:48:07.75
くやしいのうw
466デフォルトの名無しさん:2012/04/16(月) 02:07:04.82
全然くやしくないぜよ。perlでobjectのnew版も多値版もさらりと書いた。
tieとマクロ使ったのも書こうと思ったけれど手間がもったいなくなってやめた。
パラダイム比較としてもうすこし書く値打ちのあるテーマ出せよ、
このクイズじゃ再帰は使いどころないし
javaのnewだめ静的型システムダメ
何を有利に誘導したいんだか
せめて前スレのpermutationレベルのテーマを出題の下限レベルとしてクレヨ
467466:2012/04/16(月) 02:18:35.03
大体fizz buzzってのが下らないんだよ
プログラムプロムナード、ナノピコ教室、Cマガ課題、オイラー4、AIアルゴリズム、OR最適化、
パーサ、マッチング、グラフ問題あたりの
小問題で再帰・高階/部分適用、遅延・カーリー化vsOOの比較できる題材が妥当かもな
step数は2chの1レスに収まるくらいの小問題でいいからサ
468466:2012/04/16(月) 02:26:58.99
最悪、基本アルゴリズムの再実装でもいいや
たとえばqsortはperlやhaskellでpivotを適当に選択して再帰した短いコードと
pivot選択くどくど頑張ったCやjavaの長いコード比較してファンクショナルの再帰はマンセーみたいな
サイトがあちこちにあるだろ、
あのレベルでも今回のFizzBuzzGizzよりましだろ
469466:2012/04/16(月) 02:35:35.13
あと、言い出しっぺの法則はナシだぞw
470466:2012/04/16(月) 02:44:04.67
つか、OOとPFの単純比較って何か意味あるのか?
どのみち記述する言語の特徴または弱点、癖の比較レベルの議論に落ちがちな稀ガス
ズット前スレでヨンだが、意味論的にはOOとPFは相容れない物らしい
しかし生々しい実装レベルではいまんとこ清濁併せ呑んで実現するし
まあいいや寝るか。ノシ
471デフォルトの名無しさん:2012/04/16(月) 02:46:25.77
多値使うアイデアはイケてたはずなのに、仕上げの文字列との結合やprintとの併用で
ズル呼ばわりされるわ、Rubyの>>377の挙動も再現できなかったしで散々だったしね。
472デフォルトの名無しさん:2012/04/16(月) 02:53:06.66
なぜかC++で挑み続ける俺。
これ以上C++では無理かも。0xだと知らんが。

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

int main()
{
  int     i = (gizz)(buzz)(fizz)1;
  std::string t = (gizz)(buzz)(fizz)15;
  std::string u = (gizz)(buzz)(fizz)105;
  std::string v = gizz((buzz(fizz(105)))); //こうも書けるね
  return 0;
}
473466:2012/04/16(月) 02:54:29.65
>>471
あれはね最初に書いたnewはだめって言われて仕方なくの面はあるのよ

$scalar = 関数(関数

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

Rubyの>>377に関しては読んでなかったから挙動の再現にそもそも着手してないよ。
rubyは文法がかなりカオスになって来ちゃって残念だね
474466:2012/04/16(月) 02:59:22.51
fizzbuzzgizzはいいんだどうでも。
それより前スレのpermutaion perl版はwebなど参照せず一から考えて書いて
オレなりに結構な自信作だったのに
なんの反応もなかったことの方が寂しかったな
475デフォルトの名無しさん:2012/04/16(月) 03:19:21.92
何このスレ
476デフォルトの名無しさん:2012/04/16(月) 06:20:08.75
ruby無双をしたかった奴が、もっとエレガントな解を他言語で出されて、
涙目でdisるスレです
477デフォルトの名無しさん:2012/04/16(月) 06:53:26.91
Rubyと違う解法が出る度に
必死に難癖付けてて笑ったわww
478デフォルトの名無しさん:2012/04/16(月) 08:13:17.85
頭が固くて馬鹿だから
数や文字列に状態持たせる以外の方法が
理解できないんだろう
479デフォルトの名無しさん:2012/04/16(月) 08:32:48.03
頭が固くて馬鹿だから
数や文字列に状態持たせる方法が
許容できないんだろう
480デフォルトの名無しさん:2012/04/16(月) 08:38:53.99
世の中は状態がある世界なのにねw
481デフォルトの名無しさん:2012/04/16(月) 08:50:48.96
じゃあFixnumのインスタンスに特異メソッド定義してみろRuby厨
482デフォルトの名無しさん:2012/04/16(月) 09:44:46.42
元ネタのCLのEQLスペシャライザならそういうことできたよな。

Haskellとかでコンストラクタ無しで1以外の引数をとるとコンパイル時に
型エラーになる関数って定義できたっけ?
483デフォルトの名無しさん:2012/04/16(月) 10:00:08.87
template< int n > void func(){int i="";}
template<> void func<1>(){}
・・・
func<2>();//エラー
484デフォルトの名無しさん:2012/04/16(月) 12:34:04.90
> cat FooTH.hs
{-# LANGUAGE TemplateHaskell #-}
module FooTH where
import Language.Haskell.TH
foo 1 = [| 1 |]
foo _ = error ""

> cat Main.hs
{-# LANGUAGE TemplateHaskell #-}
import FooTH
main = print $(foo 1) -- foo 2 に変えるとコンパイルエラー
485デフォルトの名無しさん:2012/04/16(月) 12:50:08.98
>>474
あれ覚えてるよ、実は感心してた
ていうか、このスレでPerlの評価が結構変わったよ(もちろん高い方へ)

でも、読み易さ優先で書いてあれとは
Perl使いとは分かり合えないな...と思ったけどw
486デフォルトの名無しさん:2012/04/16(月) 20:25:48.62
>>479
許容はしてるだろう
エレガントさから程遠いと言ってるだけで
487デフォルトの名無しさん:2012/04/16(月) 22:19:41.52
俺の基準における
エレガントってやつかw
488285:2012/04/17(火) 00:46:48.85
正直、あの問題は無いと思うよ
問題があれだし書き捨てだからやったが、実際には絶対にやりたくないな
489デフォルトの名無しさん:2012/04/17(火) 00:47:44.00
>>487
FizzBuzzすら書けない口だけ野郎の基準よりマシだろwww
お前はこのスレでは最底辺のカスなんだから敬語使えw
490デフォルトの名無しさん:2012/04/17(火) 00:53:04.36
>>481
ぶっちゃけ>>479のバカが理解できたのが
たまたまRubyのコードだっただけでRuby厨ですらねーと思うぜ
むしろバカにクソコード褒められてRuby可哀想ってなもんだ
491デフォルトの名無しさん:2012/04/17(火) 00:59:54.74
あの問題出したのぶっちゃけPython使いだと思う(陰謀説)
492466:2012/04/17(火) 01:35:17.45
>>491
アレは学部・卒研レベルの課題をここに投げたのかなーと
オレは感じた。(真相はシラネ)
もしかしてオレ様はボクちゃんに利用されたのかなとww
493デフォルトの名無しさん:2012/04/17(火) 10:56:11.26
F#のスレッドローカル(有り体にはグローバル変数)と同様の方法でSqueak Smalltalkの解。
オープンクラスは使わずにブロック(無名関数)で。

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

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

self assert: (fizz value: 1) = 1.
self assert: (fizz value: 3) = 'Fizz'.
self assert: (buzz value: (fizz value: 1)) = 1.
self assert: (buzz value: (fizz value: 3)) = 'Fizz'.
self assert: (buzz value: (fizz value: 5)) = 'Buzz'.
self assert: (buzz value: (fizz value: 15)) = 'FizzBuzz'.
self assert: (gizz value: (buzz value: (fizz value: 105))) = 'FizzBuzzGizz'.
self assert: (buzz value: (gizz value: (fizz value: 105))) = 'FizzGizzBuzz'.
494デフォルトの名無しさん:2012/04/17(火) 12:02:41.83
>>493
Pythonも同じ方針のやつ

import threading
fbdata = threading.local()

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

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

assert fizz(1) == 1
assert fizz(3) == "Fizz"
assert buzz(fizz(1)) == 1
assert buzz(fizz(3)) == "Fizz"
assert buzz(fizz(5)) == "Buzz"
assert buzz(fizz(15)) == "FizzBuzz"
assert gizz(buzz(fizz(105))) == "FizzBuzzGizz"
assert buzz(gizz(fizz(105))) == "FizzGizzBuzz"
495デフォルトの名無しさん:2012/04/18(水) 13:10:30.34
っていうか問題どこだよ
496デフォルトの名無しさん:2012/04/18(水) 13:31:40.56
スレタイに惹かれて開いたけどゴミスレだった・・・
497デフォルトの名無しさん:2012/04/19(木) 02:49:08.33
$t = sub { my $f = shift;
           sub { my $x = shift;
                $f->($f->($x)) } };
$rst = $t->($t)->($t)->($t)->(
    sub{ my $x = shift;
            $x + 1 })->(0);

print $rst, "\n";
498デフォルトの名無しさん:2012/04/19(木) 09:02:56.87
同じくRubyも。
ケチがついた、オープンクラス、メソッドチェーン、リフレクションは無しで

require 'test/unit'

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

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

class FizzBuzzQuizTest < Test::Unit::TestCase
def test_fbq
assert_equal( fizz(1), 1 )
assert_equal( fizz(3), "Fizz" )
assert_equal( buzz(fizz(1)), 1 )
assert_equal( buzz(fizz(3)), "Fizz" )
assert_equal( buzz(fizz(5)), "Buzz" )
assert_equal( buzz(fizz(15)), "FizzBuzz" )
assert_equal( gizz(buzz(fizz(105))), "FizzBuzzGizz" )
assert_equal( buzz(gizz(fizz(105))), "FizzGizzBuzz" )
end
end
499デフォルトの名無しさん:2012/04/19(木) 09:53:30.31
リフレクションやらスレッドローカルやら組み込みクラス汚染やら使った
クソみたいな実装が出てくる出題だったけど
言語比較に役立つ何かは得られましたか?
500デフォルトの名無しさん:2012/04/19(木) 10:07:54.14
あるときは数値またあるときは文字列を返すような関数は
動的型であれ作るもんじゃないという幼稚園児並みの洞察が得られました
501デフォルトの名無しさん:2012/04/19(木) 10:43:06.55
>>499
「数値と文字列の組」と「数値または文字列」の違いが不明瞭だった。
リフレクションや継承で二つのクラスを一組にしたいのか、
それとも一つのクラスを数種類に分けたいのか明示されていなかった。
502デフォルトの名無しさん:2012/04/19(木) 10:53:45.22
どうしてもスレッドローカル変数が必要になったとき
関数的にはどう記述したらいいのかよかったら教えてください。
503デフォルトの名無しさん:2012/04/19(木) 11:37:33.00
そもそもスレッド自体が処理系に依存した、言語パラダイムとは関係ない概念だから、
関数型的にもオブジェクト指向的にも、どう記述したらいいかとか答えようがない。
504デフォルトの名無しさん:2012/04/19(木) 12:23:49.22
Readerモナドでグローバル変数っぽいことをするには
どうすればいいのでしょうか。たとえば、状態をfizzとかbuzzから
(引数として渡すことなしに)参照したり更新したりしたいのです。
505デフォルトの名無しさん:2012/04/19(木) 12:50:34.08
ttp://www.haskell.org/haskellwiki/Thread-local_storage
いまんとこHaskellからTLSを使う、「これ」といった定番はないようだ
506デフォルトの名無しさん:2012/04/19(木) 12:58:07.14
個人的に、関数型でスレッドとかハードに近い領域の制御はしたくないな。
507デフォルトの名無しさん:2012/04/19(木) 13:20:53.20
>>504
それは基本的にStateモナドの領域。
Readerモナドの中で、さらにサブルーチン的に他のReaderモナドを呼び出す時に、
一時的に書き換えたように見せかけたい、っていう場合ならばlocal関数が使えるけど。

Readerモナドで更新したいって、読み取り専用変数に書き込みたいって言ってるのと同じ事なのはわかってるよな…?
508デフォルトの名無しさん:2012/04/19(木) 17:54:57.76
Reader
(s -> a) -> (a -> s -> b) -> s -> b
Writer
(a,s) -> (a -> (b,s)) -> (b,s)
State
(s -> (a,s)) -> (a -> s -> (b,s)) -> s -> (b,s)
509デフォルトの名無しさん:2012/04/20(金) 11:54:43.80
>>500
あるときは a
またあるときは m a
m a -> (a -> m b) -> m b
510デフォルトの名無しさん:2012/04/20(金) 17:52:20.76
なんつーか、FizzBuzzしたいんならHQ9F+使えばいんじゃね?
511デフォルトの名無しさん:2012/04/20(金) 22:29:27.34
お題出していい?
512デフォルトの名無しさん:2012/04/20(金) 22:55:07.28
・コンソール上で動く、カード(つーてもただの数字を表示するだけだが)を使ったミニゲーム
・1〜9のカードを各4枚ずつ用意、それをシャッフルして「ストック」とする
・ストックから7枚のカードを引く
・引いたカードの中から、プレイヤーは合計が15になるように数枚を選んで捨てる
(選ばせ方はプログラマが考える、ギブアップ手段も用意)
・捨てなかったカードと合わせて再び7枚になるか、もしくはストックが空になるまでストックからカードを引く
・また15になるように捨てる
・引いては捨ててを繰り返し、ストックと手札が共に空になったらおめでとう的な言葉を吐いて終了
513デフォルトの名無しさん:2012/04/20(金) 23:16:37.51
つまらない。
514デフォルトの名無しさん:2012/04/21(土) 01:27:35.30
>>512
Squeak Smalltalk で。

| ui stock player |
ui := UIManager default.
stock := (1 to: 9) gather: [:each | Array new: 4 withAll: each].
stock := stock shuffled asOrderedCollection.
player := (stock removeFirst: 7) asOrderedCollection.
[ | choice |
   [ | input |
      input := ui request: player asSortedArray asString, 'から合計が15になるようにチョイス'.
      choice := input subStrings collect: #asInteger.
      choice ifEmpty: [(ui confirm: 'ギブアップ?')
         ifTrue: [^self] ifFalse: [choice := {nil}]].
      (choice allSatisfy: #isInteger)
         and: [choice sum = 15]
         and: (player includesAllOf: choice)
         and: [choice asSet allSatisfy: [:card | (player occurrencesOf: card) >= (choice occurrencesOf: card)]]
   ] whileFalse.
   player removeAll: choice.
   player addAll: (stock removeFirst: (choice size min: stock size)).
   player notEmpty] whileTrue.
ui inform: 'おめでとう!'
515デフォルトの名無しさん:2012/04/21(土) 02:46:31.71
>>514
なぜこの人は今どきSmalltalkの末裔を使っているのか理由をうかがいたいので
おしえてくださいです
516デフォルトの名無しさん:2012/04/22(日) 01:52:01.88
# Ruby版、指定は半角空白区切り、EOFでギブアップ
class CardNotFoundException < RuntimeError; end
def remove_cards(specs, tableau)
    specs.each do |spec|
        if idx = tableau.find_index{|card| card == spec }
            then tableau.delete_at idx
            else raise CardNotFoundException.new(spec.to_s)
        end
    end
end
stock = ((1..9).to_a * 4).shuffle
tableau = []
until tableau.empty? && stock.empty?
    tableau.push stock.pop until tableau.size >= 7 || stock.empty?
    printf "stock=%d tableau=%p\n? ", stock.size, tableau
    k = gets or exit
    specs = k.chomp.split(' ').map{|s| s == 'giveup' ? exit : s.to_i }
    begin
        remove_cards specs,tableau.dup
        if (total = specs.inject{|result,n| result + n }) == 15
            then remove_cards specs,tableau
            else puts "total(#{total}) not equal to 15"
        end
    rescue CardNotFoundException => e
        puts "not found `#{e}'."
    end
end
puts 'Congraturations !'
517デフォルトの名無しさん:2012/04/22(日) 02:31:25.32
>>514をRubyに翻訳してみた版

stock = ([*1..9]*4).shuffle
player = stock.shift(7)
loop do
  choice = nil
  loop do
    puts player.sort.inspect + "から合計が15になるようにチョイス"
    choice = gets.split(/[, ]/).map(&:to_i)
    choice.delete(0)
    if choice.empty?
      puts "ギブアップ?[Y/n]"
      !(gets=="n\n") ? exit : choice = [0]
    end
    break if choice.all?(&:integer?) and
      choice.reduce(&:+) == 15 and
      choice.uniq.all?{ |card| player.count(card) >= choice.count(card) }
  end
  choice.each{ |e| player.delete_at(player.index(e)) }
  player += stock.shift([choice.size, stock.size].min)
  break if player.empty?
end
puts "おめでとう!"
518デフォルトの名無しさん:2012/04/22(日) 12:27:13.72
Squeakは入れたことあるが(てか今も入ってるけど)何をどうしたらいいのか判らん
>>514 のコードをどこに入力して、どう実行したら動くんだ?
519デフォルトの名無しさん:2012/04/22(日) 17:54:43.65
>>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以降であれば動作するようです。
ただし公式英語版などでは日本語が化けますので適宜英語などに置き換えてからペーストしてください。
日本語版であってもペースト時にエラーがでるようならそのときの対処も同様です。
520デフォルトの名無しさん:2012/04/22(日) 21:05:31.50
// F#で入出力以外の副作用なし
let rec input hands =
    printfn "合計が15になるように捨てるカードをスペース区切りで指定(ギブアップの場合は指定なし)"
    match System.Console.ReadLine() with
    | "" -> None
    | inp ->
        try
            let discardCount = inp.Split([|' '|]) |> Seq.map int |> Seq.countBy id |> Map.ofSeq
            let handCount = hands |> Seq.countBy id |> Map.ofSeq
            if discardCount |> Map.exists (fun n c -> defaultArg (Map.tryFind n handCount) 0 < c)
                || discardCount |> Map.toSeq |> Seq.sumBy ((<||) (*)) |> (<>) 15 then input hands else
            handCount |> Map.map (fun n c -> c - defaultArg (Map.tryFind n discardCount) 0)
            |> Map.toList |> List.collect (fun (n, c) -> List.replicate c n) |> Some
        with _ -> input hands

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

let random = System.Random()
[for i in 1 .. 9 do yield! List.replicate 4 i] |> List.sortBy (fun _ -> random.Next()) |> play []
521デフォルトの名無しさん:2012/04/23(月) 00:28:55.28
>>519
ありがと。何か前に入れたバージョンでやってみたら「[ | input |」の行の左に「Period or right bracket expected ->」とか出たけど、実行の仕方自体は判ったから色々試してみる。
522デフォルトの名無しさん:2012/04/23(月) 00:33:02.59
ああ、インデントを一旦削って入れ直したら動いたわ。thx
523デフォルトの名無しさん:2012/04/23(月) 07:26:59.30
あ、動的にいたスモールトーカーだ。よろしく!
524デフォルトの名無しさん:2012/04/24(火) 12:35:28.99
日本語でおk
525デフォルトの名無しさん:2012/04/25(水) 13:12:07.32
お題:
コンウェイのライフゲームで、
配列の配列(あるいはリストのリスト)で表わされた格子を受け取り
次世代を返す関数lifeを定義せよ。

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

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

また作成した同関数を用いて、500x500のランダムな状態の格子の
500世代目を算出するのにかかった時間(無理なら、算出可能な
世代数とその時間)を計測して示せ。
526デフォルトの名無しさん:2012/04/25(水) 13:54:49.01
くだらん
527デフォルトの名無しさん:2012/04/25(水) 14:03:57.26
Java8でラムダ式が言語仕様に入るようだね
javaもマルチパラダイム化が進むな

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

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

と考えても良いお題は思いつかないんだけどね
528デフォルトの名無しさん:2012/04/25(水) 15:26:58.18
Javaって今でも組み込み型以外は参照型でしか扱えないの?
関数型言語使うようになってから、nullを持たない参照型とか、イミュータブルな値型がいかに重要か思い知った。
しかも、イミュータブルな値型を基本として、nullを持った参照オブジェクト型、nullを持たない参照オブジェクト型って形で扱えないと厳しい。
これは言語仕様として取り込まれていないとどうしようもない。
そういう意味では、C++は結構惜しいところまで行ってたと思う。
529デフォルトの名無しさん:2012/04/25(水) 16:37:33.03
C++にはpure virtual function callというのがあって、仮想関数がnullを持つ。
値型でも仮想関数があったら元も子もない。
仮想関数をやめてswitchを使う覚悟がないと厳しい。
関数型言語のパターンマッチはswitchと同じ方式だ。
530デフォルトの名無しさん:2012/04/25(水) 16:43:26.43
>>528 関数型言語はむしろ全てが参照型とも言えるんだが
531デフォルトの名無しさん:2012/04/25(水) 17:35:29.26
>>525
Squeak Smalltalk (4.2-ja w/CogVM), 1.8GHz Core i7で5分弱。

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

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

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

cells := (1 to: 500) collect: [:row | (1 to: 500) collect: [:cell | #(0 1) atRandom]].
[500 timesRepeat: [cells := life value: cells]] timeToRun "=> 267282(msec) "
532デフォルトの名無しさん:2012/04/25(水) 20:45:17.23
>>531をRubyに翻訳してみた版。1.9だが50世代に4分以上かかってしまう。
翻訳の手間を省くのにArray#*,#+を置き換えちゃったのが足を引っ張ったか?

require "benchmark"

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

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

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

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

cells = (1..500).map{ (1..500).map{ [0,1].sample } }
p Benchmark.measure{ 50.times{ cells = life(cells) } }
533デフォルトの名無しさん:2012/04/25(水) 22:15:29.46
1.6GHz Core i5で2分


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

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

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

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

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

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

main = do
  rs <- newMTGen Nothing >>= randoms
  let board = randomBoard (map (`mod` 2) rs) 500 500
  print $ L.foldl' (\x _ -> updateBoard x) board [1..500]
534533:2012/04/25(水) 22:20:37.27
instance Show Lattice where
  show (Lattice m n v) = concat $ snd $ L.mapAccumL (\i x ->
    if i == n-1 then (0, show x ++ "\n") else (i+1, show x)) 0 $ V.toList v

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


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

# 出力
01100
01010
00000
00000
00100
535デフォルトの名無しさん:2012/04/26(木) 20:54:15.37
(_, _)   (`mod` 2)   (\x _ ->
536デフォルトの名無しさん:2012/04/26(木) 20:56:38.97
最近Lispさんを見かけないけどもう廃れちゃったの?
537デフォルトの名無しさん:2012/04/26(木) 21:25:38.01
言語仕様を共通にするというトレンドは終わった
個別の実装は始まってなかった
538デフォルトの名無しさん:2012/04/27(金) 01:17:14.79
Rで
life <- function(ary2d) {
  sum <- rbind(ary2d[ncol(ary2d),], ary2d[-ncol(ary2d),]) + ary2d + rbind(ary2d[-1,], ary2d[1,])
  sum <- cbind(sum[,nrow(sum)], sum[,-nrow(sum)]) + sum + cbind(sum[,-1], sum[,1])

  ifelse(sum == 3 | (ary2d == 1 & sum == 4), 1, 0)
}
539デフォルトの名無しさん:2012/04/27(金) 08:45:31.15
>>536
2chで世間が判った気になり始めたら色々ヤバイな。
540デフォルトの名無しさん:2012/04/27(金) 10:14:19.97
>>538
500x500 500世代で測ったら 1.8GHz Core i7 で 68秒だった。けっこう速いね。
541デフォルトの名無しさん:2012/04/27(金) 11:00:18.10
ライフゲームで関数型とオブジェクト指向の何を比較したいんだろう?

>>525は次世代を返す関数としてるけどオブジェクト指向側は
 lg = new lifegame(500,500);
 for(i=0;i<500;i++)lg.life();
 console(lg);
って感じでいいの?
そうしないと関数型 vs 手続き型みたいなことになるよね
542デフォルトの名無しさん:2012/04/27(金) 11:37:20.76
例えばF#とC#を比較したら関数型言語と手続き型言語の比較になる
本物のOOは言語に依存しない
関数型言語と対立するようなOOは偽物
543デフォルトの名無しさん:2012/04/27(金) 12:00:12.21
>>541
ライフゲームは単純だけどパラダイムの特徴をかろうじて出せるくらいの規模はあるんじゃない?
お題にあるlifeという関数名(メソッド名)にこだわらなくていいと思うよ。
要は小さな例での正常動作と、500x500セル 500世代(必要なら50世代とかに軽減して)
にどのくらいかかるかが示せていればOKかと。
544デフォルトの名無しさん:2012/04/27(金) 12:17:25.49
>>543
規模の大きさは良いと思うけど、
データの破壊的操作ができると有利な御題のほうが
違いが出て良いと思った

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


import Data.Array

life ary = array ((1,1),(x,y)) [((i,j), f i j) | i <- [1..x], j <- [1..y]]
  where
    (x,y) = snd $ bounds ary
    f i j = let n = sum [ary ! (g x (i+a), g y (j+b)) | a <- [-1,0,1], b <- [-1,0,1]]
            in if n == 3 || (n == 4 && ary ! (i,j) == 1) then 1 else 0
    g x i = if i < 1 then x else if i > x then 1 else i
545デフォルトの名無しさん:2012/04/27(金) 14:36:04.79
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
546デフォルトの名無しさん:2012/04/27(金) 20:27:45.31
てきとーにCで書いてみた
500回はさすがに秒数制限に引っかかったけど、50回で0.69秒

http://ideone.com/a7mH5
547デフォルトの名無しさん:2012/04/27(金) 22:35:14.09
F# 2.6GHz Core2Duo 500世代で2分57秒

let life (field : int[,]) =
    let height, width = field.GetLength 0, field.GetLength 1
    field |> Array2D.mapi (fun y x c ->
        let s =
            seq { y - 1 .. y + 1 } |> Seq.sumBy (fun y' ->
                seq { x - 1 .. x + 1 } |> Seq.sumBy (fun x' ->
                    field.[(y' + height) % height , (x' + width) % width]))
        match s, field.[y, x] with 4, 1 | 3, _ -> 1 | _ -> 0)
548デフォルトの名無しさん:2012/04/27(金) 22:37:08.83
手続き型言語F#で書くと>>547と同じ環境で500世代9秒

let life (field : int[,]) =
    let height, width = field.GetLength 0, field.GetLength 1
    let result = Array2D.zeroCreate height width
    for y = 0 to height - 1 do
        for x = 0 to width - 1 do
            let mutable s = 0
            for y' = y - 1 to y + 1 do
                for x' = x - 1 to x + 1 do
                    s <- s + field.[(y' + height) % height, (x' + width) % width]
            result.[y, x] <- match s, field.[y, x] with 4, 1 | 3, _ -> 1 | _ -> 0
    result
549デフォルトの名無しさん:2012/04/28(土) 00:03:43.28
OOPならセルごとにオブジェクトで、と思ったが、
仕様が全状態の配列から配列への変換なのね。
550デフォルトの名無しさん:2012/04/28(土) 00:54:50.29
>>549
べつにこだわらなくてもいいでしょ。組みやすいように組めば。
要は小さな例での動作確認出力結果と、
500x500セル 500世代(必要なら50世代とかに軽減して)の計測結果を示せればOK。
551デフォルトの名無しさん:2012/04/28(土) 04:39:34.80
まあ出題者が関数的なアタマなんだろう
552デフォルトの名無しさん:2012/04/28(土) 06:37:42.91
セルごとにオブジェクトとかねぇよww
553デフォルトの名無しさん:2012/04/28(土) 07:45:09.18
問題領域がどこかわかれば何処をオブジェクトにしたら良いか分かるよ
554デフォルトの名無しさん:2012/04/28(土) 09:32:38.01
なかなか面白いじゃないか。
オブジェクト指向で設計されたライフゲーム、頼む。
555デフォルトの名無しさん:2012/04/28(土) 09:44:59.90
この題じゃ>>541くらいにしかならんだろ
オブジェクト指向をどういうもんだと思ってんだよw
556デフォルトの名無しさん:2012/04/28(土) 10:37:13.10
セル毎にオブジェクトか、面白そうだしちょっとやってみるかな
557デフォルトの名無しさん:2012/04/28(土) 10:51:25.73
セル毎にオブジェクトってこんなの?(コードはPython)


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


全部は長いのでこっち
http://ideone.com/3WKkG
558デフォルトの名無しさん:2012/04/28(土) 11:05:27.26
8coreのXeonマシンでOpenMP使ってCのコードを並列化したら
500*500の500世代で1秒切ったわw
559デフォルトの名無しさん:2012/04/28(土) 12:11:25.24
>>557
他スレで遊んでる内に作られてしまった…
560デフォルトの名無しさん:2012/04/28(土) 12:13:20.34
>>552
ライフゲームは生物が単純だから変に思えるかもしれないけど、
これがゲームのキャラクターと考えればごく普通の考え方。

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

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

マルチプレイヤー・ネットワーク・ゲームTerrarium
http://www.atmarkit.co.jp/fdotnet/wwebserv/wwebserv010/wwebserv010-001.html
> プレイヤーは各自プログラミングした動物を持ち寄り、フィールド上で動物同士を戦わせる。
561デフォルトの名無しさん:2012/04/28(土) 12:23:40.64
やっぱりオブジェクト指向だと規模が大きくなる。

逆に言えば、規模が大きい場合は
オブジェクト指向が有利ってことか。
562デフォルトの名無しさん:2012/04/28(土) 12:42:19.17
大規模で全貌の把握がしづらいものを
個々人では把握できないままでも比較的扱いやすいのがOOPLだと思ってる
563デフォルトの名無しさん:2012/04/28(土) 12:57:03.02
全体を統一しづらい規模になると言語は一つではなくなる
Objective-C++/CLIのような状態
564デフォルトの名無しさん:2012/04/28(土) 16:19:14.44
>セルがオブジェクトなら
>実際の生物みたく、オブジェクトごとに能力を変えることだって出来る

大抵のOOPLにはマルチメソッドすらないのに、
良くそんな大口たたけるな。
565デフォルトの名無しさん:2012/04/28(土) 16:24:25.86
無いのはマルチメソッドを実現するための言語仕様であって、
マルチメソッド自体は実装できるからね。
566デフォルトの名無しさん:2012/04/28(土) 16:25:24.90
>>564
突然何言い出してんのこの子(´・ω・`)
567デフォルトの名無しさん:2012/04/28(土) 16:28:06.39
ホーミングミサイルの話でボコボコにされたやつだ。
気にすんな
568デフォルトの名無しさん:2012/04/28(土) 18:10:20.59
>>565
関数型言語でも実装できる
パラダイムじゃなく言語間の比較スレなんだから
そんなこと言っても意味ない
569デフォルトの名無しさん:2012/04/28(土) 18:15:28.58
>>561
仮に「OOPだと規模が大きくなる」が真だとしても
そこから「規模が大きいとOOPは有利」は導けない
570デフォルトの名無しさん:2012/04/28(土) 18:53:58.34
静的型付けの割に簡潔に書けて、かつ型チェックも厳しくやってほしい

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

争いは不毛だ
571デフォルトの名無しさん:2012/04/28(土) 19:06:33.77
> 静的型付けの割に簡潔に書けて、かつ型チェックも厳しくやってほしい
なんとなくC#を思いだしたけどC#で書く人いないね
572デフォルトの名無しさん:2012/04/28(土) 19:31:55.12
争わなかったらスレの存在意義がないだろ
573デフォルトの名無しさん:2012/04/28(土) 20:25:37.43
>>571
C#のジェネリックってダックタイピングできないんでしょ?簡潔かなぁ。
574デフォルトの名無しさん:2012/04/28(土) 20:41:49.41
>>560
ライフゲームのセルっていう文脈だからねぇよって言ったわけで
ゲームのキャラクターのオブジェクト化まで否定はしてねぇよw

>>564
またホーミングの子www
575デフォルトの名無しさん:2012/04/28(土) 21:39:52.98
>>570
Scalaがそう。

静的言語で、簡潔に書けることを
証明した言語。
576デフォルトの名無しさん:2012/04/28(土) 21:45:24.53
>>575
このスレでまだ一回もScala出て来てないぞ
ライフゲームで良いからコードで証明してみてくれ
577デフォルトの名無しさん:2012/04/28(土) 23:03:24.87
「Scalaは簡潔に書けると証明した」=>「じゃあチョット書いてみて」=> 逃亡


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

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

| lattice |
lattice := Cell newLatticeFrom: {{0. 1. 1. 1. 0}. {0. 1. 0. 0. 0}. {0. 0. 1. 0. 0}. {0. 0. 0. 0. 0}. {0. 0. 0. 0. 0}}.
Cell updateLattice: lattice. "=> {{0. 1. 1. 0. 0}. {0. 1. 0. 1. 0}. {0. 0. 0. 0. 0}. {0. 0. 0. 0. 0}. {0. 0. 1. 0. 0}} "
580デフォルトの名無しさん:2012/04/29(日) 00:22:22.02
純粋な関数型言語って、参照するたびに値が変化する変数みたいなのは作れるの?
たとえば乱数とか、参照した時点の現在時刻を値として持ってる変数とか
581デフォルトの名無しさん:2012/04/29(日) 00:31:18.37
>557をscalaでベタ移植してみた。

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

scalaの機能を余り活用できていない感じ。
582デフォルトの名無しさん:2012/04/29(日) 01:14:20.15
これで静的型付け言語なんだぜ。

val msg = if (true) "true dayo" else "false dayo"
583デフォルトの名無しさん:2012/04/29(日) 01:27:13.41
せっかくなのですべてのセルが並行に動くように>581を修正

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

evaluate/updateの分割が不要になったので少し短くなったか
584デフォルトの名無しさん:2012/04/29(日) 01:30:58.02
これで静的型付け言語なのか。
本当に短いコードは動的型付け言語だけの特権じゃないことを
証明してしまったな。
585デフォルトの名無しさん:2012/04/29(日) 02:11:32.74
ただ静的型にしては遅いよね。
500x500 500世代で動的な >>579 が 112秒なのに、>>581 は 196秒。
586デフォルトの名無しさん:2012/04/29(日) 02:18:22.73
>>585
それ事前コンパイルしてないだろ?
587デフォルトの名無しさん:2012/04/29(日) 02:35:44.97
>>583
これって一回のlifeのコール後、
すべてのセルがアップデートを終えるのをどこで待ち合わせているの?
588デフォルトの名無しさん:2012/04/29(日) 06:27:13.54
>>582
そんなんで感動できるとか何時の時代の人?

OCaml : let msg = if true then "true" else "false"
Haskell : let msg = if True then "true" else "false"
589デフォルトの名無しさん:2012/04/29(日) 06:30:26.82
どうせ、RubyとかLLばっかり使ってる人だろw
590デフォルトの名無しさん:2012/04/29(日) 07:52:20.17
C++,C#にも導入されたね
C++11 : auto msg = true ? "true dayo" : "false dayo";
C#(3.0) : var msg = true ? "true dayo" : "false dayo";
591デフォルトの名無しさん:2012/04/29(日) 08:14:29.69
最近どんどん動的型付け言語の
メリットがなくなっていくね。
592デフォルトの名無しさん:2012/04/29(日) 08:47:25.44
>>590
…それでmsgの型を推論しろってか。
593デフォルトの名無しさん:2012/04/29(日) 09:24:13.53
>>591
この戦いが終わったら全ての武器のメリットがなくなるんだ
594デフォルトの名無しさん:2012/04/29(日) 09:42:55.39
機械語のメリットがなくなってゆくね、とか言ってる奴の同類だよなぁw
595デフォルトの名無しさん:2012/04/29(日) 09:43:05.44
でも静的型はコンパイルが必要でREPLももっさり、型推論も万能じゃない
スクリプト言語はこれからも残るよ
596デフォルトの名無しさん:2012/04/29(日) 10:59:45.94
trueって名前の変数を作って、遅延評価によってmsgを参照したときの変数trueの値によりmsgの値も変わるってことでいいんかの
変数trueに再代入できたりしないとあんま意味なくね?
いや違ってたらすまんが
597デフォルトの名無しさん:2012/04/29(日) 11:11:11.60
>>590は型推論の話じゃないの?
"true dayo"も"false dayo"も文字列リテラルなので
三項演算の条件のtrue/falseを問うことなくmsgの型を文字列と確定できる
598デフォルトの名無しさん:2012/04/29(日) 11:27:23.87
>>597
ああなんだそういうことか、勘違いしてたわ
599デフォルトの名無しさん:2012/04/29(日) 11:55:08.69
変数に互換性がない別の型の値を
再代入できる言語はクソです。
600デフォルトの名無しさん:2012/04/29(日) 12:10:48.87
>>586
Scalaって事前(?)にコンパイルする以外になんか実行方法あったっけ?
601デフォルトの名無しさん:2012/04/29(日) 12:18:53.17
>>600

>>581はコンパイルしたらエラーがでます。
602デフォルトの名無しさん:2012/04/29(日) 12:21:46.03
コンパイルしない場合は、そのまま動きます。
603デフォルトの名無しさん:2012/04/29(日) 12:31:37.65
>581はscalaスクリプトだから、コンパイルする場合は
-Xscript XXX オプションをつける必要があるかと
604デフォルトの名無しさん:2012/04/29(日) 12:42:00.90
動くね

$ time scala Lifegame.scala
0,1,1,0,0
0,1,0,1,0
0,0,0,0,0
0,0,0,0,0
0,0,1,0,0
scala Lifegame.scala 1.44s user 0.09s system 4% cpu 37.965 total
AMD MV-40 1.6GHz シングルコア
605デフォルトの名無しさん:2012/04/29(日) 12:42:30.36
>>599
それで、代入を禁止するのと共用体を禁止するのは、どっちが良いんですか
606デフォルトの名無しさん:2012/04/29(日) 12:48:02.58
スクリプト実行
time scala LifeGame.scala
0,1,1,0,0
0,1,0,1,0
0,0,0,0,0
0,0,0,0,0
0,0,1,0,0
real 0m1.819s
user 0m0.704s
sys 0m0.104s

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

コンパイル時間の分、スクリプト実行だと起動に時間がかかるね
607デフォルトの名無しさん:2012/04/29(日) 12:48:20.97
>>605
両方いいです。
608デフォルトの名無しさん:2012/04/29(日) 12:51:30.57
>>597
よく見れ。
msgにtrueを代入してる。
609デフォルトの名無しさん:2012/04/29(日) 12:53:31.56
>>608
どのtrueを代入してるんですか?

全文を引用して、該当のtrueを【】でくくって下さい。
610デフォルトの名無しさん:2012/04/29(日) 13:04:26.07
>>601
コンパイル通らないのでAppにして通したんだけどこれでも遅いままなのかな?

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

>>603
あ、Scalaスクリプトなんてモードがあるんですね。
実行オプションでそんなに差が出るものなんですか?
611デフォルトの名無しさん:2012/04/29(日) 13:31:36.87
Javaの実行環境に詳しくないとまともにベンチとれないんじゃないかと思う

>>608
$ cat hello.cs
class Program {
public static void Main() {
var hoge = true ? "*true*" : "*false*";
System.Console.WriteLine(hoge); } }
$ mono hello.exe
*true*
612デフォルトの名無しさん:2012/04/29(日) 13:56:15.31
>>608
お前が良く見た方がいい
613デフォルトの名無しさん:2012/04/29(日) 14:10:28.74
括弧を省略する言語は危険
式と文を区別しない言語も危険
614デフォルトの名無しさん:2012/04/29(日) 14:12:28.08
>>613
蛇の国からようこそおこしやす
615デフォルトの名無しさん:2012/04/29(日) 14:22:29.08
Lisp系から見るとHaskellも括弧省略言語だな
616デフォルトの名無しさん:2012/04/29(日) 19:36:04.13
λ式に比べたらLispだって
617デフォルトの名無しさん:2012/04/30(月) 00:25:42.19
>>616
Lispの関数は
apply = foldl ($)
(((f x) y) z) == (apply f) [x, y, z]
省略ではなく、式を変形している
(x, y, zの型が異なる場合、Haskellは上の式が間違っていると主張する)
618デフォルトの名無しさん:2012/04/30(月) 01:24:53.48
>610
core i5で90s程度だね。
ちなみに
 def life() {
  cells.foreach(_.foreach(_.evaluate))
  cells.foreach(_.foreach(_.update))
 }

 def life() {
  cells.par.foreach(_.foreach(_.evaluate))
  cells.par.foreach(_.foreach(_.update))
 }
にして並列化すると30s。
まだまだ遅いけど。
619デフォルトの名無しさん:2012/04/30(月) 01:28:51.62
>>587
遅くなって悪い。確かに待ち合わせが抜けてるね。
BoardもActorをextendsしてlifeを以下のactに替えればよさそう。
 def act() {
  cells.foreach(_.foreach((c:Actor) => {link(c); c.start}))
  var count = 0
  loopWhile(count < m * n) { receive { case _ => count += 1 } } andThen { print(this) }
}
620デフォルトの名無しさん:2012/04/30(月) 01:42:08.34
やっぱり手続き型のC言語が
こういうのは一番早いね。
621デフォルトの名無しさん:2012/04/30(月) 06:36:40.19
つまりCの関数を簡単に呼べる言語が優秀
622デフォルトの名無しさん:2012/04/30(月) 08:02:32.77
なんだ。Rubyが最強ってことか。
623デフォルトの名無しさん:2012/04/30(月) 09:21:02.55
>>546のCの関数を呼び出してみた


from __future__ import print_function
from ctypes import *

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

x = [[0,1,1,1,0], [0,1,0,0,0], [0,0,1,0,0], [0,0,0,0,0], [0,0,0,0,0]]
a, b = (POINTER(c_int) * 5)(), (POINTER(c_int) * 5)()
for i in xrange(5):
    a[i], b[i] = (c_int * 5)(*x[i]), (c_int * 5)()
clife.life(a, b, 5, 5)
print('\n'.join(''.join(str(b[i][j]) for j in xrange(5)) for i in xrange(5)))
624デフォルトの名無しさん:2012/04/30(月) 15:16:50.31
Haskell(GHC)からC関数を使用


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

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

main = do
  x' <- newArray $ concat xss :: IO (Ptr (CInt))
  y' <- mallocArray (m * n)
  x <- f x' =<< peek x'
  y <- f y' =<< peek y'
  cLife x y (fromIntegral m) (fromIntegral n)
  z <- peekArray (m * n) y'
  mapM_ free [x, y]
  mapM_ free [x',y']
  print $ unfoldr (\xs -> if null xs then Nothing else Just $ splitAt n xs) z
  where
    xss = [[0,1,1,1,0], [0,1,0,0,0], [0,0,1,0,0], [0,0,0,0,0], [0,0,0,0,0]]
    m = length xss
    n = length (concat xss) `div` m
    f p h = newArray [plusPtr p (sizeOf h * i * n) | i <- [0..m-1]]
625デフォルトの名無しさん:2012/04/30(月) 20:00:22.80
速度が必要な極一部の処理だけ
速い言語(C/C++/Java)で書けば良いのに
クソ遅い言語で速度競っててワロタwww
626デフォルトの名無しさん:2012/04/30(月) 20:14:25.98
なんだJava厨か
627デフォルトの名無しさん:2012/04/30(月) 20:25:46.03
Ruby「実行速度とかそんなの求めてませんから(キリッ」
628デフォルトの名無しさん:2012/04/30(月) 21:11:28.94
>>546のコードをJavaにベタ移植したんですが
C言語に比べて物凄く遅いです(6.5倍遅い)
(出力が遅すぎるので、そこをコメントアウトしてもまだ遅いです)

http://ideone.com/FoYga

どうやったら速くなりますか?
629デフォルトの名無しさん:2012/04/30(月) 21:27:32.39
すいません正しく移植したら速くなりました
http://ideone.com/oLyyb
630デフォルトの名無しさん:2012/05/01(火) 03:28:55.35
関数型言語で書くとどうしてもボトムアップになる,
そこが問題,
小さい処理ならそれでいいが,大きなシステムだとはなしにならん
631デフォルトの名無しさん:2012/05/01(火) 03:59:53.53
関数型言語はトップダウンでもボトムアップでも組む事が出来る
出来ないのはそいつが未熟なだけ
632デフォルトの名無しさん:2012/05/01(火) 04:44:27.14
>>630
自分は逆に関数型言語でトップダウンだが・・・
入れ子になった関数を変更するときぐらいだな。ボトムアップな感じになるのは
633デフォルトの名無しさん:2012/05/01(火) 05:04:37.25
マクロな関数(処理)から書き始め、マクロな関数から呼ばれる
ミクロな関数は入出力の型だけ決めて実装は後回し

なんでこんな簡単なことが>>630には出来ないの?
634デフォルトの名無しさん:2012/05/01(火) 07:57:45.80
トップダウンはどうしても車輪の再発明になる
再利用はどうしてもボトムアップになる
635デフォルトの名無しさん:2012/05/01(火) 09:19:19.80
え?
636 ◆QZaw55cn4c :2012/05/01(火) 12:12:45.49
>>634
実感として、トップダウンとボトムアップの出会うところでうんうんうなっています。
637デフォルトの名無しさん:2012/05/01(火) 15:17:57.73
>>634
ボディを違う色で塗って「ニューモデル」っていうだけだろ
638デフォルトの名無しさん:2012/05/01(火) 19:35:01.49
Excel内臓の関数型言語の普及率はすげぇよな。
窓際に座ってる禿ですら操作できるんだからなぁ。
http://research.microsoft.com/en-us/um/people/simonpj/Papers/excel/index.htm
639デフォルトの名無しさん:2012/05/01(火) 19:48:21.14
simonpj先生の勤務先都合仕事だからだまされないで!
640デフォルトの名無しさん:2012/05/01(火) 19:53:04.34
騙されるも何も、内容は事実じゃん。
641デフォルトの名無しさん:2012/05/01(火) 19:57:17.64
スプレッドシート猿によるアホな決定というリスクマネジメントのための学会?
642デフォルトの名無しさん:2012/05/01(火) 20:11:03.69
現実には使えないExcelの拡張の話だけどなw
643デフォルトの名無しさん:2012/05/01(火) 20:20:54.13
拡張せずとも、普通に計算するだけで関数型だろ?
何言ってんだ?
644デフォルトの名無しさん:2012/05/01(火) 20:54:33.43
A1=3
A2=A1-32
A3=A2*5/9

これは静的単一代入 (SSA) です。
SSAは関数型に入りますか?
645デフォルトの名無しさん:2012/05/01(火) 20:59:05.32
y = x + 5 は一次関数。あとは説明要らんよな。
646デフォルトの名無しさん:2012/05/01(火) 21:02:58.15
そもそも、型に入るとか入らないとかいう型の理論が要らない
647デフォルトの名無しさん:2012/05/01(火) 21:47:34.44
型がないと、実行時にしかメソッド名の解決ができない。
これは開発工数が伸びる原因になる。
648デフォルトの名無しさん:2012/05/01(火) 21:56:43.18
なんという緻密な分析
649デフォルトの名無しさん:2012/05/01(火) 22:03:59.52
関数"型"の話してんだろコミュ障
650デフォルトの名無しさん:2012/05/01(火) 22:36:11.12
>>649
だから、型ですよね?
651デフォルトの名無しさん:2012/05/01(火) 22:36:32.17
型だよ型。
652デフォルトの名無しさん:2012/05/01(火) 22:37:00.05
型の話しようぜ。
653uy: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
654デフォルトの名無しさん:2012/05/02(水) 03:53:50.68
ぶっちゃけ関数型もオブジェクト指向もどうでも良くて
自分が使ってる言語以外をdisりたいだけだよね
655デフォルトの名無しさん:2012/05/02(水) 11:28:46.31
>>653
まだpermutationやってんのかよ、こんなもんがそんな面白いか?

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

main = print $ perm [1,2,3]
656デフォルトの名無しさん:2012/05/02(水) 11:34:39.78
こっちは要素の重複を取り除かないバージョン

import Data.List
perm' [] = [[]]
perm' xs = [x:y | x <- xs, y <- perm $ delete x xs]
657uy:2012/05/02(水) 13:23:15.71
>>655
Rubyのpermutationって誰も知らないのか話題にならないから俺が最初に2chにコード投下したやつじゃん(半年前くらいに)
67の冗長ゴミカスRubyソースコードを添削しただけだよ
658デフォルトの名無しさん:2012/05/02(水) 13:33:49.06
へえー、これ良いね。
659デフォルトの名無しさん:2012/05/02(水) 15:29:43.37
>>658
いやHaskellでもRubyでも標準添付や組み込みのライブラリに入ってますし…
660デフォルトの名無しさん:2012/05/03(木) 10:07:46.90
>>655
要素の重複を取り除くところでバグるかもしれない点は面白い
661デフォルトの名無しさん:2012/05/03(木) 14:24:19.11
>>655 を Squeak Smalltalk で書いてみた。バグもそのまま。

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

perm value: #(1 2 3) "=> #((1 2 3) (1 3 2) (2 1 3) (2 3 1) (3 1 2) (3 2 1)) "
662デフォルトの名無しさん:2012/05/03(木) 20:11:32.07
>>653 も書いてみた。これも重複要素があるとバグる。

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

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

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

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

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

  def swap!(a, b); self[a], self[b] = self[b], self[a] end
end
663デフォルトの名無しさん:2012/05/04(金) 12:04:28.46
F#で遅延評価

let bind m f = seq {for x in m do yield! (f x)}
let ret x = Seq.singleton x
let rec perm xs =
  if Seq.isEmpty xs then ret Seq.empty else
    bind (seq {0 .. (Seq.length xs - 1)}) (fun n ->
      bind (perm (Seq.append (Seq.take n xs) (Seq.skip (n+1) xs))) (fun ys ->
        ret (seq {yield (Seq.nth n xs); yield! ys})))
664デフォルトの名無しさん:2012/05/05(土) 00:05:09.38
 ttps://metalab.at/wiki/Lambdaheads
こんなひとおる?
665デフォルトの名無しさん:2012/05/06(日) 08:01:00.40
未だに関数型言語の機能が欲しいと思ったことがない。
俺みたいな奴は案外多いんじゃないかね。
そんなことよりトランザクショナルメモリはよ。
666デフォルトの名無しさん:2012/05/06(日) 09:25:35.24
欲しいと思う機能はそれほど多くない
だが変な機能をゴリ押しされるとそれに対抗するものが欲しくなる
ゴリ押しを断るために、先約があるとかいって他のを抜擢するみたいな話は案外多い
667デフォルトの名無しさん:2012/05/06(日) 11:09:05.44
うむ。関数型言語というより
コレクションライブラリがあれば
十分だったりするw

Guavaおすすめ
668デフォルトの名無しさん:2012/05/06(日) 12:23:52.01
ム板の関数型言語派の大半は「関数型言語派」ではなく「型推論派」だろ
669デフォルトの名無しさん:2012/05/06(日) 12:33:51.12
スレタイが無知だな。

手続型 vs 関数型
構造化設計 vs オブジェクト指向設計
670デフォルトの名無しさん:2012/05/06(日) 12:34:57.95
>666
メタプログラミングなんてどう?
LISPのように構文を犠牲にしないMPといえば、OO系が主流だろう。
671デフォルトの名無しさん:2012/05/06(日) 12:59:41.15
コレクションにもpush型とpull型があって
push型は一昔前のOO
pull型は遅延評価できるので関数型に近い印象がある

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

メタプログラミングは、共通のVMまたはC言語の上に好きな言語を乗せるのが主流
672デフォルトの名無しさん:2012/05/06(日) 13:07:46.75
メタオブジェクトプロトコルみたいな話は最近どうなったのか
673デフォルトの名無しさん:2012/05/06(日) 16:21:50.38
>>671
一昔前がよくわからないのでpull型とpush型の違いがよくわからんです
674デフォルトの名無しさん:2012/05/06(日) 17:41:19.49
>>673
getterを呼び出したり成功か失敗か調べたりするのがpull型
getter反対派はpush型
675デフォルトの名無しさん:2012/05/06(日) 19:43:30.18
言語はなんでもいいので具体例をプリーズ。
676デフォルトの名無しさん:2012/05/06(日) 20:31:27.12
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);
 }
});
677デフォルトの名無しさん:2012/05/06(日) 20:34:08.65
いまさらだけど、>>671
pullとpushの言葉の使い方逆じゃね?
678デフォルトの名無しさん:2012/05/06(日) 20:43:49.33
>>677
放置したほうがいい人だと思うがどうか?

"Push-Pull Functional Reactive Programming"風に、
pull: demand driven
push: data driven
ってことでいいかと。
679デフォルトの名無しさん:2012/05/06(日) 20:45:09.00
言葉のままに捉えればよいんじゃない?

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

pushは押す。
huga( result );
piyo( result );
hoge( result );
680デフォルトの名無しさん:2012/05/06(日) 20:59:16.39
>>678
遅延評価はdemand drivenだから、671は合ってるだろ
681デフォルトの名無しさん:2012/05/06(日) 21:05:42.54
一箇所だけ取り上げてそんな事言われても困りますよ。
682デフォルトの名無しさん:2012/05/06(日) 21:16:14.00
>>677は0箇所ですよ
0箇所よりも1箇所の方がいいんじゃないか
683デフォルトの名無しさん:2012/05/06(日) 21:18:45.89
pullとかpushって>>671が作った言葉だろ?

手続きタイプと、コールバックタイプとかでいいんじゃね?
684デフォルトの名無しさん:2012/05/06(日) 21:23:25.41
なんだ、オレオレ用語かよ
685デフォルトの名無しさん:2012/05/06(日) 21:44:18.93
>>682
まあそりゃそうだねw

push/pullは、上に上げたようにFRPでも取り上げられてるし、
他にはWebアプリフレームワークとかXML系APIとか、
いろいろなところでAPIデザインの選択肢として語られてる。
大げさに騒ぐような概念じゃないけど。
686デフォルトの名無しさん:2012/05/06(日) 21:51:58.49
http://ja.wikipedia.org/wiki繊維強化プラスチック

繊維強化プラスチック(せんいきょうかプラスチック、Fiber Reinforced Plastics、FRP)は、
ガラス繊維などの繊維をプラスチックの中に入れて強度を向上させた複合材料のこと。

単に FRP と書いて、ガラス繊維強化プラスチックを指すことも多いが、
ガラス繊維であることを明示したい場合は GFRP または
GRP (Glass fiber reinforced plastics, Glass-reinforced plastics) と書かれる。
687デフォルトの名無しさん:2012/05/06(日) 22:02:41.17
688デフォルトの名無しさん:2012/05/06(日) 22:14:04.87
でも、FRP自体は明らかに関係ない概念だよね?
pullとpushの概念引っ張ってくるためだとしても。

それに、Getter/SetterをPull or Pushに分類しようとするのは
独自解釈が過ぎるでしょ
689デフォルトの名無しさん:2012/05/06(日) 22:15:07.62
なんだF#用語か。http://pro.art55.jp/?eid=1303925
690デフォルトの名無しさん:2012/05/06(日) 22:19:52.64
>>671 はオレオレ定義すぎ。
>>676 の下がpush。上はシラネ。

だろ。普通にpull/pushを考えるなら。
691デフォルトの名無しさん:2012/05/06(日) 22:23:38.07
>>688
> でも、FRP自体は明らかに関係ない概念だよね?

ちょっと難しい例でごめんね。
692デフォルトの名無しさん:2012/05/06(日) 22:28:26.04
>>691
難しい例もなにも、普通にFRP関係ない例しかでてないぞ。
関係あるんなら関係ある例になるコードをださんと。
693デフォルトの名無しさん:2012/05/06(日) 23:30:20.47
>>688
つまり、まず質問をして、独自ではない回答が出るまで待っていればいいんですかね

関数型言語がgetterの使用を制限しない理由は何でしょうか
694デフォルトの名無しさん:2012/05/07(月) 06:32:00.39
関数型ってパターンマッチとか、再帰とか、モナドとか、そんな程度のものなの?
もっとすごい秘密兵器があるんじゃないかなぁと期待しているんだけど、イマイチ見えてきません。
型クラスのメリットは、クラスを使った不完全な抽象データ型オブジェクト指向より
定式化され優れているとわかるとしても、両者は必ずしも背反するものではないですよね?
参照透明性にしても抽象度やモジュラリティは上げられる反面、直感的でない回りくどい処理や
そのための記述を強いられたりする局面も少なからずあるし、そうしたやり難さと引き換えに
関数型でゴリ押しするメリットってどこら辺にあるのでしょうか?
695デフォルトの名無しさん:2012/05/07(月) 09:50:54.31
高階プログラミングではないかと昨夜から今朝にかけて思った。

いわゆるメタプログラミングや自己反映計算を実現する方法として、
自己書き換え→テンプレやマクロ→...というように発展してきて、
関数合成とかでプログラミングをするようになった、というか。
696デフォルトの名無しさん:2012/05/07(月) 10:34:09.89
関数合成はメタプログラミングに入りますか?
697デフォルトの名無しさん:2012/05/07(月) 11:00:16.79
>>694
代入を制限する関数型が、get/setの両方を制限するオブジェクト指向よりも回りくどい
と言われるのは何故ですか?
698デフォルトの名無しさん:2012/05/07(月) 11:08:18.79
Smalltalkが普及しなかったようにHaskellは普及しない
699デフォルトの名無しさん:2012/05/07(月) 11:19:44.93
「get/setの両方を制限」のところがよくわからないので具体的にお願いします。
あとなんでその「get/setの両方を制限」が関数型の再代入制限に対応すると
思われたのでしょうか?
700デフォルトの名無しさん:2012/05/07(月) 11:50:13.94
こうかいかんすう
701デフォルトの名無しさん:2012/05/07(月) 12:01:35.13
高階関数って関数オブジェクトがファーストクラスなら
どうということなく使えますよね。それでもやっぱり
関数型の秘密兵器なんでしょうか?
カリー化が自動だったり関数合成演算子が組み込みなのは嬉しいけど、
OOPLであっても関数オブジェクトがそうであればいいだけって気もしますし、
ポイントフリースタイルで書こうとしてパズルみたいになるのも
何だか本末転倒な感も否めません。
702デフォルトの名無しさん:2012/05/07(月) 12:15:37.81
OOPLでもできるって
頑固なOOPLのスタイルを変えさせることができるなら凄い兵器だ
703デフォルトの名無しさん:2012/05/07(月) 12:35:48.84
頑固なOOPLのスタイルってどんなの?
704デフォルトの名無しさん:2012/05/07(月) 12:54:07.33
>>701
別に秘密兵器でも何でもなく、関数型の思想のうち
手続き型でも適用出来そうな部分は既に受け入れられてるってことさ
705デフォルトの名無しさん:2012/05/07(月) 15:35:46.86
>>694
「ゴリ押しする」ってのは、あなたの心の問題じゃないの?
706デフォルトの名無しさん:2012/05/07(月) 15:47:21.06
関数型の主力は副作用が無いこと
手続き型の主力は副作用が有ること
OOPは副作用の局所化を目指すもの

異論は認める
707デフォルトの名無しさん:2012/05/07(月) 17:50:02.95
副作用があるのはsetterだけ
getterの局所化には副作用以外の目的があるだろう
708デフォルトの名無しさん:2012/05/07(月) 18:08:27.94
そうかしら?
709デフォルトの名無しさん:2012/05/07(月) 18:09:54.21
>>707
一体いつからgetterに副作用が無いと錯覚していた?

getで内部キャッシュを生成,保持しても良く
副作用は外から分からずとも、仕様(期待)通り動作すればいい
710デフォルトの名無しさん:2012/05/07(月) 18:47:24.86
しかし実際にはオブジェクトが他のオブジェクトの参照を握ってたりして、
一回のメソッド呼び出しがどんどんたらい回しされてって。
特にオブジェクト指向では多態のためにメソッドのシグネチャを固定化するから、
オブジェクトが他のオブジェクトの参照を握る傾向は強い。
つまり、オブジェクト指向で副作用の局所化はされないし、元々狙っても無い。
オブジェクト指向はオブジェクトに関するコードや変数の依存関係を纏めたってだけ。
これを手続き型で実行すれば、処理がオブジェクトを跨いであちこちに飛び回る。
このとき、副作用は局所化されない。
副作用の局所化するためには、処理がオブジェクトを跨がないように
する必要がある。
しかし、それはオブジェクト指向とは関係無く、手続き型一般における、設計のテクニックだ。
711デフォルトの名無しさん:2012/05/07(月) 19:01:14.42
・シグネチャを固定化 → 他のオブジェクトの参照を握る
・副作用の局所化するため → 跨がないように
この辺前後の関連がよく分からないので詳しくお願いします
712デフォルトの名無しさん:2012/05/07(月) 19:09:28.48
どう言えばよいんだろうね。
オブジェクト指向はオブジェクト単位で色々纏めるが、これらは変数やコードといった、
静的な要素を分類したに過ぎない。
言い換えれば、「ソースコード」をオブジェクト単位で分類したに過ぎない。
一方で副作用はソースコード上には現れない。
実行時に「処理」にくっ付いて現れる。
だから、副作用を局所化するためには、処理の流れそのものを
局所化する必要があって、これは手続き型一般の設計の問題で、
OOだからどうこうという話ではない。
OOはあくまでソースコードをオブジェクト単位で局所化するだけで、
それ以上は助けてくれない。
713デフォルトの名無しさん:2012/05/07(月) 19:26:38.69
>>709
それはgetterを作って良いし副作用が有って良いという意見だな
そういう自由な考え方が定着すれば、OOに反対する人はいなくなると思う
714デフォルトの名無しさん:2012/05/07(月) 19:29:05.25
そんでついでに言うと、
オブジェクト指向は処理の流れに関して凄く無頓着な一面がある。
というのも、仮想関数だ多態だといってな。
そんで、むしろソースコードみたいな静的なものは怖くねーよ、
こんなの綺麗に分類するより、
処理の流れとその副作用の方がよほど怖えーよ、そっち整理しろよ、
って考え方もあって、OOは使いどころが難しく、2chなんかで議論もこじれる。
だから皆だんだん嫌になってきて、
処理の流れそのものを気にしなくて良い関数型に白羽の矢が立ったってわけ。
715デフォルトの名無しさん:2012/05/07(月) 19:48:12.05
俺にとっての副作用を局所化というのは
「この変数を触るのはこの処理だけ」といった
スコープを小さくしたり責任範囲の壁を作ったりすることなんだけど

>>712にとっての副作用の局所化というのは
何かのメソッド呼んだときに変化するN個のオブジェクトのN個の変数とか
その辺りに言及してるのかな?

メソッドの中で自身(A)が持ってる別のオブジェクト(B)のメソッドを呼んだとして
そこから先でファイルアクセスが発生しようと
それはBの範疇なのでAの中での局所化には関係無い
というスタンスかな、俺はね

>処理の流れに関して凄く無頓着
そうかもね
他のオブジェクトは外面(インターフェイスと仕様)しか見ないので
処理の内容は「あとは任せた」って感じだし
716デフォルトの名無しさん:2012/05/07(月) 20:17:37.37
>>715
これは物凄く悪い例なんだけど、
AがBのメソッドを呼び出して、
そのメソッドの中でBがAのメソッドを呼び出したら、
カプセル化は壊れるんだよね。
そんな設計はするな、と言われそうだが、
これが結構良くあるんよ。
親が子の参照を持ってて、子も親への参照を持ってるとか。
717デフォルトの名無しさん:2012/05/07(月) 20:22:02.86
循環参照は注意だが、カプセル化は別に崩れてなくね?
718デフォルトの名無しさん:2012/05/07(月) 20:22:28.51
カプセル化は言葉が悪かった。
整合性だね。
719デフォルトの名無しさん:2012/05/07(月) 20:40:40.96
AがcallするならBはreturnすればいいのに、なぜかBもcallしようとするんだな
なぜreturnを避ける設計をしてしまうのか
720デフォルトの名無しさん:2012/05/07(月) 20:46:15.19
>719 てめぇ、CPSさんDisってんのか?
721デフォルトの名無しさん:2012/05/07(月) 20:49:59.90
>>716
>これが結構良くあるんよ。
わかる・・・

イベントハンドラとかのインターフェイスの実体として子に自身を渡すとか
木構造で高速化のためAが別のA(親)を持つとかは許容出来るけど
一つずつ順にコンパイル出来ないような定義レベルでの循環参照は俺も嫌い
722デフォルトの名無しさん:2012/05/07(月) 21:04:21.69
>>720
末尾呼出しなら問題なさそうだ
問題は、Aのメソッドの途中でAが参照されること
723デフォルトの名無しさん:2012/05/07(月) 21:18:02.26
>>718
言葉が悪いんじゃない。関係ないんだよ。
724デフォルトの名無しさん:2012/05/07(月) 21:29:27.23
>>722
ACTORさん(以下略
725デフォルトの名無しさん:2012/05/11(金) 20:23:27.60
それぞれのオブジェクトがメッセージを投げ合い、
その結果でたらめな順序で副作用が起こっても問題が無い
仮に問題あっても例外投げときゃ無問題

そういうイイカゲンなシステム開発にオブジェクト指向は最適
726デフォルトの名無しさん:2012/05/11(金) 21:46:23.18
さすがにそこまでいい加減なシステムは品質を確保できないだろ。バカにし過ぎ。

「そのように組むことができる」ことと「実際にそうする」は別問題。
Haskellでも副作用が発生する処理と、そうでない処理をごちゃ混ぜにすることは可能は可能だし。
727デフォルトの名無しさん:2012/05/12(土) 18:57:50.97
ここの人らなら詳しそうだから教えてくれ。

0 :: Integer
0 = 0

みたいな感じで、数値を関数化できる言語ってないの?
0関数にラムダ与えたら、ラムダの実行を無視して、
0以外の数値関数にラムダ与えたらラムダを実行するようにしたい
728デフォルトの名無しさん:2012/05/12(土) 19:03:59.81
は?

関数なら 'a -> 'b みたいな型を持ってるはずだけど。
Integer という型は整数の型であって、関数じゃないよ。
729デフォルトの名無しさん:2012/05/12(土) 19:09:46.34
別にそこの式は、数値を関数化したいって例であって
関数を返すとかとは関係ないよ
730デフォルトの名無しさん:2012/05/12(土) 19:21:16.56
「数値を関数化」ってのが、たとえば「文字列を虚数化」みたいに意味不明。

むしろ、
> 0関数にラムダ与えたら、ラムダの実行を無視して、
> 0以外の数値関数にラムダ与えたらラムダを実行するようにしたい
こっちをソースコードで表現できたら、少しはなんとかなるかもしれない。
731デフォルトの名無しさん:2012/05/12(土) 19:41:40.45
あ゛?チャーチ数ディスってんのかメーン
732デフォルトの名無しさん:2012/05/12(土) 23:05:55.96
>>727
「0」というシンボルと、何らかの関数を結び付けたいということ?

関数型ならそもそも、既に何かに結び付けられてるシンボルに
別の値を結び付けるのは再代入そのものだろうし
手続き型関数型問わず、特定リテラルの意味だけを変更するのはちとマズくないかな
733デフォルトの名無しさん:2012/05/12(土) 23:10:21.88
common lispに変数としての値と関数としての値を区別するということなのか
734デフォルトの名無しさん:2012/05/12(土) 23:11:42.30
ごめん、脱字した。

common lisp(のよう)に変数としての値と関数としての値を区別するということなのか
735デフォルトの名無しさん:2012/05/13(日) 00:06:48.19
>>732
Smalltalkなら実現してたべ

value := 0.
value message.
こんな感じで、数値にメッセージを送ると、
数値に紐付いたメソッドを呼ぶ事ができた。
1にメッセージを送れば、1のメソッド。
2にメッセージを送れば、2のメソッドみたいにね。
736デフォルトの名無しさん:2012/05/13(日) 01:07:22.66
本のお題がどういうものだが今一歩ピンとこないが、
チャーチ数を計算する型なしラムダ式処理系なら結構転がってる。
数値や真理値は短形表示できるが。
737デフォルトの名無しさん:2012/05/13(日) 02:06:34.64
>>735
何が言いたいのか分からん
value message と function value は語順が違うだけじゃね?
738デフォルトの名無しさん:2012/05/13(日) 02:12:38.75
>>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関数を実行
739デフォルトの名無しさん:2012/05/13(日) 02:36:28.73
>>738
なるほど分かった
0や1といったリテラルに関数を割り当てたいってことだね

どっちかというと関数型 vs. オブジェクト指向じゃなくて
静的型 vs. 動的型になりそうな気配
740デフォルトの名無しさん:2012/05/13(日) 02:40:45.66
ところで>>727のいう「ラムダ」の引数は何?
それは何時渡すの?
741デフォルトの名無しさん:2012/05/13(日) 02:44:08.62
>>740
値が関数だって事の説明用だから引数はなんでもいいんですが
742デフォルトの名無しさん:2012/05/13(日) 02:49:18.06
>>741
意味論的には関数型言語の値は「ゼロ引数関数」という関数
743デフォルトの名無しさん:2012/05/13(日) 08:04:27.03
いずれにしろ 0 :: Integer では、関数になってないから
744デフォルトの名無しさん:2012/05/13(日) 10:20:35.18
OO信者の俺ですら数値クラスにメソッド追加するような
コードは勘弁して頂きたい
オープンクラスではしゃぐのは初心者時代で終わらせてほしい
745デフォルトの名無しさん:2012/05/13(日) 11:09:32.18
>>735>>738
シングルディスパッチでは第一引数を特別扱いしてるだけで
x.foo y z と foo x y z に本質的な差は無い

シングルディスパッチ脳には理解出来ないかもしれんけど
746デフォルトの名無しさん:2012/05/13(日) 11:16:35.94
難しい問題だね。
func( o1, o2 )
こういった関数は後からいくらでも追加できるけど、
o1.func( o2 )
との本質的な違いはスコープだけだからな。
多態出来る出来ないの違いは有るけど、それは言語上の制約ってだけだからね。
クラスの外のスコープにいくらでも関数が定義できるのに、
クラスの中のスコープにメソッドを追加することは出来ません、
って制約に一体どれほどの意味があるかって言われると、ねぇ。
特に動的言語では。
747デフォルトの名無しさん:2012/05/13(日) 11:37:40.06
あんたの恣意的な分類で「本質」とか「言語上の制約ってだけ」とか言われても
わかりませんわ。
748デフォルトの名無しさん:2012/05/13(日) 12:25:07.97
別に恣意的ではないと思うけど。
本来、どこのスコープに何を追加しようが勝手なものなんじゃないの?
静的言語では実行効率の理由で制限がかかってくるのも分かるけどさ。
749デフォルトの名無しさん:2012/05/13(日) 12:32:53.64
Haskellでやっつけ
お題の真意が掴めてないので、たぶん条件を満たしてない

http://ideone.com/pTYEL
750デフォルトの名無しさん:2012/05/13(日) 12:39:04.98
0がどうのこうのの話は、まだ続いてたの?
0と1は同じ型だろうから、同じ関数にディスパッチされるのが当たり前だしさ。
751デフォルトの名無しさん:2012/05/13(日) 15:59:42.13
>>742
そういう形式化もあるという程度の話。
752デフォルトの名無しさん:2012/05/13(日) 18:30:14.35
このスレには時代遅れのSmalltalkを使ってる
奇特な人が居るから質問するんだけど、
あのIDEモドキを立ち上げずにプログラム実行する方法無いの?

それと動的型付けで実行が遅いから、せめてボトルネックだけでも
C/C++で書いて実行できないとトイプログラムでしか
使いモノにならないと思うけど、簡単にC/C++のライブラリとリンクできるの?
753デフォルトの名無しさん:2012/05/13(日) 19:25:11.00
たとえば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
754デフォルトの名無しさん:2012/05/13(日) 19:48:37.96
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
755727: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を評価しない

数値を関数化できないかというのは、数値を評価したとき、このような
振る舞いをするように数値を定義できなる言語は無いかという事でした。
尤も、言語レベルで最初から数値をチャーチ数と同じように評価できるなら
新たに関数として数値を再定義できる必要は無いんですが。
756デフォルトの名無しさん:2012/05/13(日) 20:00:39.51
>>752
時代遅れってアホか、通信・製造・金融・保険・政府。
お前がしらんだけで第一線で新規開発されとるわ。
国内企業なら、東洋ビジネスエンジニアリングとかが導入してんだぞ。
757デフォルトの名無しさん:2012/05/13(日) 20:17:42.17
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 = ()
758デフォルトの名無しさん:2012/05/13(日) 20:19:29.56
>>755
Integer と () -> Bool は違う型なので、
同じ数値(関数)の型が文脈に応じて変化する言語でなければ不可能。
759727: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を評価する
760デフォルトの名無しさん:2012/05/13(日) 20:20:46.22
>>758
できる言語はあるかと聞いているのですが?
あとboolは関係ないですよね
761デフォルトの名無しさん:2012/05/13(日) 20:24:09.03
>>760
じゃあ Integer と (() -> a) -> a

それはともかく、関数型とか全然関係なくって
まともな静的型なら無理って言ってるんだけど、
動的型しか使った事無い馬鹿には分からないかな?
762デフォルトの名無しさん:2012/05/13(日) 20:25:17.06
>>761
だから、できない言語の事は聞いてなくて、出来る言語はあるかと聞いてるんですけど。
763デフォルトの名無しさん:2012/05/13(日) 20:29:16.10
>>762
スレ違いだし問題としても糞詰まらんから
どっか行けって言ってんだけど?
764デフォルトの名無しさん:2012/05/13(日) 20:29:54.03
何か値を返さなきゃならないみたいなので、>>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
765デフォルトの名無しさん:2012/05/13(日) 20:32:20.89
>>763
NGにしたいんでトリでも付けてもらえます?
スレ違い以前に話が通じないので
766デフォルトの名無しさん:2012/05/13(日) 20:42:57.75
>>763
まず日本語の通じないお前がどっか行けよ
767デフォルトの名無しさん:2012/05/13(日) 20:44:48.51
>>764
オブジェクトで出来てもあんまり嬉しくないんですが・・・
768デフォルトの名無しさん:2012/05/13(日) 20:46:00.83
>>765>>766
型付けの問題だって理解できない自分の低能さを
日本語の問題にすり替えるなよw
769デフォルトの名無しさん:2012/05/13(日) 20:52:46.02
>>761
「コンセントの付いている車はありますか?」
「軽トラなら無理です」
お前が言ってるのはこういう事だという自覚は有るのか?
普通は「あります」「ありません」この2択だろ
頭おかしいな
770デフォルトの名無しさん:2012/05/13(日) 20:53:58.75
>>767
Int32はラッパークラスとかではなく、プリミティブかつオブジェクトなんだけど。
まぁそれでもダメというならどうしようもない。
771デフォルトの名無しさん:2012/05/13(日) 20:55:35.08
>>764 のような Execute 的な関数を使うのってダメじゃね?
これアリなら難しくも何ともないじゃん


(|.) 0 _ = Nothing
(|.) x f = Just $ f ()

main = do
  print $ 0 |. (\_ -> "zero")
  print $ 1 |. (\_ -> "one")
  print $ (1 - 1) |. (\_ -> "zero")
  print $ (1 + 1) |. (\_ -> "two")
772デフォルトの名無しさん:2012/05/13(日) 20:57:08.31
>>770
すいません。
関数と互換性をもってて欲しいんですよ。
773デフォルトの名無しさん:2012/05/13(日) 21:06:51.99
>>771 >>772
てっきり拡張メソッド的なものを要求してるのかと思ってた。
Scalaなら暗黙型変換あるからできそうな気がする。
774デフォルトの名無しさん:2012/05/13(日) 21:08:02.77
>>773
なるほど。Scalaですか、調べてみます。
775デフォルトの名無しさん:2012/05/13(日) 22:46:41.69
で、Scalaなら出来たの?
776デフォルトの名無しさん:2012/05/14(月) 00:37:38.04
マイナー言語使い共が
可読性皆無のコード書く御題で
型付けの弱さを競うスレはここですか?

時代に逆行してて笑えるwww
777デフォルトの名無しさん:2012/05/14(月) 01:46:05.41
誰だって0と1は同じ型だと考えるのに、違った振る舞いをさせたいってのは、
何か前提がおかしいんだろうね。
元々何がしたかったのか聞ければよいんだけど、
彼にそういった振る舞いが出来るとも思えないしなぁ。
778デフォルトの名無しさん:2012/05/14(月) 07:07:11.76
うーん。一番良く分からんのは、>>767を読むと出題者は>>764を見て
オブジェクトとしてなら「出来ている」認定してるっぽい処だな。
779デフォルトの名無しさん:2012/05/14(月) 07:40:52.01
出題者がOOP厨だからオブジェクトには甘いだけだろ
別に不思議でもなんでもない

もちろん出題者は底なしのアホだけど
780デフォルトの名無しさん:2012/05/14(月) 17:54:42.36
お題:
等確率N種類のカードをコンプするのに必要なガチャ回数のM回試行時の頻度分布から、
最小および最大のガチャ回数と最多頻度のガチャ回数を抽出して出力するコードを書き、
N=10、M=1000000のときの結果とその算出にかかった時間を示せ。

遅い処理系ではMを減らした際の結果を示しても構わないがその旨を明記すること。
781デフォルトの名無しさん:2012/05/14(月) 18:47:07.65
OOPLでもメソッドの中は大体手続き型みたいなもんだから
関数型 VS 手続き型 って感じになりそう
782デフォルトの名無しさん:2012/05/14(月) 19:41:29.94
では手続き型の 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} "
783デフォルトの名無しさん:2012/05/14(月) 19:54:50.29
>>778
これで、できてると言ってる訳ではなくて、
数値を関数化してラムダ演算をするのが目的であって
オブジェクトで雰囲気が近いことできても仕方ない
という事を書いたつもりです。

最終的な目標は>>759の様な(欲を言えばチャーチ数)演算が
できる言語を見つける事です。

>>775
よく知らないので、調べてる最中ですよ。
784デフォルトの名無しさん:2012/05/14(月) 20:17:53.30
チャーチ数?

型無しラムダな処理系なら、学生演習レベルのものならいくらでもあるだろ。
785デフォルトの名無しさん:2012/05/14(月) 21:01:05.79
チャーチ数が欲しいのか>>759が出来る何かが欲しいのかどっちだよ
786デフォルトの名無しさん:2012/05/14(月) 21:07:37.59
>>785
存在すればどちらでも構いません。
ただし誤解されてるかもしれませんが、
チャーチ数というのは、f x.x を直に表現できて
欲しいと思ってる訳ではなく。0なら f x.xと同じ振る舞いを
して欲しいという話で、今までの話とは大きく違いません。
チャーチ数と今までの話は、2以上の時、1回関数が評価されるのか、
2回評価されるのか程度の違いの意味で書いてます。
787デフォルトの名無しさん:2012/05/14(月) 21:14:35.72
間違えました

×2回評価されるのか
○その数だけ評価されるのか
788デフォルトの名無しさん:2012/05/14(月) 21:50:45.36
いよいよ何がしたいのか良く分からないが、
再起でよいんじゃないの?
789デフォルトの名無しさん:2012/05/14(月) 22:49:56.49
>787
型なしラムダ計算でやりたいことがかける?
もしそうならLazy Kやunlambdaを使えばできるな。
790デフォルトの名無しさん:2012/05/15(火) 00:51:10.23
lispならevalいじりゃ何とか出来そうな気がするが
関数名が数値型だったら特別扱いすりゃいいだけだろ
791デフォルトの名無しさん:2012/05/15(火) 08:00:22.83
>>790
変数名が値だったらって何か変だぞ

変数は単に置き換えるのが目的であって
置き換えた後にどのような演算が出来るかというと、確かに何でも出来ると思う
しかしLispは要らない
792デフォルトの名無しさん:2012/05/15(火) 10:10:16.80
関数名って書(ry
793デフォルトの名無しさん:2012/05/15(火) 10:31:41.96
定数0を(\ f x -> x)に置き換えることはできないかもしれない
変数zを(\ f x -> x)に置き換えることはできる
なら定数を使わない言語を考えるのが普通で
定数の定義を書きかえるのは変だ
794デフォルトの名無しさん:2012/05/15(火) 14:05:34.62
定数というか、リテラルかな。
いずれにしろ、リテラルの意味を再定義できる言語、というのは珍しいが、無いわけじゃない。
Forthなんかモード切り替えで、"100" というワードが 10 進にも 16 進にも解釈される、
っていう仕様だったと思ったし。
795デフォルトの名無しさん:2012/05/15(火) 16:30:18.62
>むちゃくちゃになっていたので直します。何度もすいません。
>( 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を評価する

こう言ってるから、処理系の持ってる整数型はそのまま使いたいんだろうと思う。
その上で、整数値を関数としても定義したいと。
良く分からないのは、整数値を関数で定義せず、
引数で渡せばよさそうなものなのに、なぜそうしないかだな。
796795:2012/05/15(火) 16:41:00.21
あー、だから、整数の無い処理系もNGだろうし、
単純に整数をfunctorにしたいんだろう。
分からないのは、普通ならパラメータで渡せば直ぐ済むのに、
なぜそうしないかだとおもう。
その辺の説明が何も無いから、誰も答えられないんだと思う。
797デフォルトの名無しさん:2012/05/15(火) 18:43:21.09
チャーチ数でも良いらしいので、Haskellでチャレンジ

http://ideone.com/0LiFz
798デフォルトの名無しさん:2012/05/15(火) 18:49:15.95
ついでに>>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
799798: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 ()
800デフォルトの名無しさん:2012/05/15(火) 20:22:09.35
>>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)])
}
801デフォルトの名無しさん:2012/05/15(火) 23:05:25.41
>>780
JavaScriptで多分ベタなOOP
Core2Duo(3.16GHz) Node.js(Windows)で
試行回数=1000000 所要時間=1398msec 最小=10 最大=144 平均=29 最頻=23(44951回)

ソース(※こっちは10000回)
http://ideone.com/DkeKE
802デフォルトの名無しさん:2012/05/15(火) 23:14:59.88
>>801
コードそのものよりもNode.jsがspidermonkeyより
44倍も速いのが興味深い
803デフォルトの名無しさん:2012/05/15(火) 23:30:56.13
Node.jsの中身のV8はJIT持ってるので
804デフォルトの名無しさん:2012/05/15(火) 23:32:18.16
1000000回も試行してるのに各人の最大値がおおきくばらついてるのが気になる。
各処理系の乱数の質の差が反映されているのか。
805デフォルトの名無しさん:2012/05/15(火) 23:52:23.55
何度も気軽に試せるようにCで書いてみた
さすがに速い

http://ideone.com/WPpbW

同じプログラムでも試行ごとに最大値はばらつくみたいね
806デフォルトの名無しさん:2012/05/16(水) 00:08:03.51
書き捨てなのは分かるけど、
せめて void gacha(int n, int m, RESULT *r); くらいにロジック分離しようぜ。
807デフォルトの名無しさん:2012/05/16(水) 12:23:32.14
>>803
しかもx86,x64,ARMに特化されたかなり先進的なJITだしね。
808デフォルトの名無しさん:2012/05/16(水) 13:57:24.59
ところで、数値を関数にしたいと言ってた彼は
結局Scalaで望みのことが出来たの?

それとも、実はSmalltalk辺りのOOPLで
やりたいことは既に出来てて、あとは
「関数型言語で出来ないことがOOPLで出来る!OOPサイコー!!」
って言い出すタイミングをはかってるの?
809デフォルトの名無しさん:2012/05/17(木) 16:49:24.16
Smalltalkは実社会で何の価値もないので
せめてこういうスレのトイプログラムの御題でくらいは
存在感を出さないとね。
810デフォルトの名無しさん:2012/05/17(木) 16:53:53.95
既に引退の身ですが、現役の時はすごかったんですよ(棒読み
811デフォルトの名無しさん:2012/05/17(木) 19:18:25.65
Intは関数ではないけど forall a. ((Int -> a) -> a) は関数だよ
Intに限らず任意の型で同じことが言えるのでチャーチ数は関係ない
812デフォルトの名無しさん:2012/05/17(木) 19:53:36.50
関数を数リテラルとして表現できて
加算や減算ができるなら
チャーチ数で無くても文句無いんだろう、多分

ただし>>797のプログラムはチャーチ数でないと
加算減算が出来ないから成立しない
813デフォルトの名無しさん:2012/05/17(木) 20:37:57.99
静的言語 VS 動的言語スレとかないの?
814デフォルトの名無しさん:2012/05/18(金) 00:44:10.29
まずJavaかHaskellのどちらかを潰さないと
静的言語は一貫していない
815デフォルトの名無しさん:2012/05/18(金) 01:54:17.00
関数型言語も一貫してないから
それぞれで代表一つ以外は全て潰し
最後に決定戦とすべき
816デフォルトの名無しさん:2012/05/18(金) 07:15:42.96
クラスベースOOとプロトタイプOOの潰し合いとか
スレが幾つ在っても足りんだろ
817デフォルトの名無しさん:2012/05/18(金) 07:52:12.43
プロトタイプとか無視していいぞ
評判の良いやつだけで潰しあえ
818デフォルトの名無しさん:2012/05/18(金) 07:55:27.26
Javascript「えっ」
819デフォルトの名無しさん:2012/05/18(金) 08:10:51.95
動的言語の代表はLLバトルロワイヤルスレの勝者ですか?
820デフォルトの名無しさん:2012/05/18(金) 21:20:26.37
Scalaスレ見てたんだけど、リストがソート済みかどうか
判定する関数を書くのに苦労してた。
短く書けるとウワサのScalaですらそのレベルなんて、
静的型付け言語はダメダメだなぁ。
821デフォルトの名無しさん:2012/05/18(金) 21:56:20.82
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 }

型指定は面倒だね。
暗黙の型変換を定義すればもう少し簡潔になるかも。
822デフォルトの名無しさん:2012/05/18(金) 22:32:39.96
おお、想像以上に型注釈がうざいw
823デフォルトの名無しさん:2012/05/18(金) 22:38:39.58
関数プログラミング的に、比較演算子を引数で受け取るようにすると少しましかも。

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 }
824デフォルトの名無しさん:2012/05/18(金) 22:44:02.03
ソート済か?なんて調べる発想が変だろ
825デフォルトの名無しさん:2012/05/18(金) 22:52:26.14
そんなこと無いだろ
二分探索を使う前とかに調べるじゃん
826デフォルトの名無しさん:2012/05/18(金) 22:53:00.87
>>823
それなら十分許容範囲だね。
827デフォルトの名無しさん:2012/05/18(金) 22:55:38.83
ていうかscalaって型推論って
引数と返り値の型は推論してくれないんだっけ?
828デフォルトの名無しさん:2012/05/18(金) 22:56:20.29
つ amortized sortでcheck inする必要がある時にtestしながらinsert sort
829デフォルトの名無しさん:2012/05/18(金) 23:33:06.68
>>825
ソートしとけよ
してないなら、まずソートしろ
830デフォルトの名無しさん:2012/05/18(金) 23:37:28.63
実際にソートするのとソート済みか確認するのが
同じ計算量だと思ってる男の人って...
831デフォルトの名無しさん:2012/05/18(金) 23:57:52.40
動的言語は静的言語より3〜5倍くらい短く書けないと
静的型チェックのメリットと釣り合わない
832デフォルトの名無しさん:2012/05/19(土) 00:44:54.27
でもあまりに短いと、それはそれで暗号になっちゃうんだよ。
833デフォルトの名無しさん:2012/05/19(土) 01:06:57.97
チェックは保険だろ
釣り合う物を取り返そうとしたら保険の意味がなくなる
834デフォルトの名無しさん:2012/05/19(土) 01:10:31.94
>>830
ソートされてるかどうかわからない
なんてことになる設計がダメだしされてるんだろ
835デフォルトの名無しさん:2012/05/19(土) 01:27:57.13
はいはい
オブジェクト指向で静的型の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;
}
836デフォルトの名無しさん:2012/05/19(土) 03:31:46.88
isSorted xs = and $ zipWith (<=) xs $ drop 1 xs
837デフォルトの名無しさん:2012/05/19(土) 04:29:01.17
"Squeak Smalltalk"

SequenceableCollection >> isSorted
   self overlappingPairsDo: [:a :b | a <= b ifFalse: [^false]]. ^true
838デフォルトの名無しさん:2012/05/19(土) 07:54:30.96
大小関係を満たさないのが途中で分かってもソコで計算終了せず
全ての隣り合う組を比較するようなダメコードを書くダメプログラマは
まさかこのスレには居ないよね?
839デフォルトの名無しさん:2012/05/19(土) 09:09:24.99
>>831
コードの長さはあまり関係なくないか?
考えた処理をサクサクとコード化できるか、だと思う
840デフォルトの名無しさん:2012/05/19(土) 10:06:00.60
重要なのは品質,保守性,開発効率だな

>>833
保険というか、コンパイラに一部の整合性のチェックを任せられるので
作業量増加と引き換えに、開発者が気を使う要素が減る
トレードオフで負担を変化させる

[作業量が減る][気を使う要素が減る]どちらの開発効率が良いかは
ケースバイケースだと思うが
841デフォルトの名無しさん:2012/05/19(土) 10:58:17.40
単位が一貫していない量を比較するのは難しいね
842デフォルトの名無しさん:2012/05/19(土) 15:29:10.77
>>838
もしかしてHaskellについて言ってるなら、遅延評価だから途中で止まる
無限リストで試せば分かる

Prelude> isSorted [1,0..]
False
843デフォルトの名無しさん:2012/05/20(日) 09:55:31.76
>>838
もしかしてSmalltalkについて言ってるなら、どうせ遅過ぎてウンコだから
そんなところ気にしても仕方ない

メッセージング(笑)
844デフォルトの名無しさん:2012/05/20(日) 13:40:56.75
^falseってあるとおり、Smalltalkのもふつうに止まる。
Smalltalkerかアラン・ケイになんか嫌なことでもされたか?
845デフォルトの名無しさん:2012/05/20(日) 13:47:01.48
遅延評価ってこんなにすごいのに
なんで使うことってあまりないんだろうね。
846デフォルトの名無しさん:2012/05/20(日) 14:11:04.26
Haskell使ってれば基本は全部遅延評価だけど?
847デフォルトの名無しさん:2012/05/20(日) 14:15:09.70
関数型言語でも、効率とか速度とか(必要なら汚らしさとか)を度外視すれば、mainで
「N種類のカードをアトランダムにコンプするまで引く作業をM回繰り返して集計」
ってただそれだけのことをSmalltalkみたいにそのまんまに書き下すことも可能なのかな。
HaskellにもMultiSet(SmalltalkでいうところのBag)とかあるよね?
848デフォルトの名無しさん:2012/05/20(日) 14:18:36.97
>>846
内部で勝手に遅延評価してるってだけだから
そんな言語の話をしたってしょうがない。

遅延評価をしたい場面が無いって話をしてる。
849デフォルトの名無しさん:2012/05/20(日) 14:34:00.38
>>809
あ?政府から海運業、通信、保険、金融、音響。
お前がしらんだけで実際いろんな所で使われとるわ。
英語が読めん奴が覆いから日本人の開発者が少ないだけ。
850デフォルトの名無しさん:2012/05/20(日) 14:34:50.90
値を参照しようとするとその値の計算が始まる、
こういうイデオムはgetterのあるオブジェクト指向プログラミングだとよくある。
getterがないと値参照から関数呼び出しを引き起こせないので、
単に関数呼び出しをすることになってしまう。
ただしそのような場合でも遅延評価イデオムと呼ぶ場合もある。
例えば上に出たamotized sortは挿入時にやるべき並び替えを最後までやらずに、
細かい部分はサボって後回しにして、後でまとめてやっている。
こういうのは遅延実行の一種。
851デフォルトの名無しさん:2012/05/20(日) 14:42:50.92
Smalltalkが現実で使われてないと言ってるヤツは、
Smalltalkという実行環境が現存してると思ってんだろ
うんで「Smalltalkでググっても見つからないよー」とw
Linuxと同じように純粋なSmalltalkは存在しないのにな。
852デフォルトの名無しさん:2012/05/20(日) 14:45:54.09
>>851
よしわかった。
具体t系な実行環境を言ってくれ。

それに対して、使われているかいないか
判断することにしよう。
853デフォルトの名無しさん:2012/05/20(日) 14:52:32.76
>>852
Visual Works.
VA Smalltalk.

Squeak.
Pharo.
GNU Smalltalk.
854デフォルトの名無しさん:2012/05/20(日) 14:56:00.00
VA Smalltalkの前身であり、Eclipseの前身でもある
VisualAgeは、各種言語の統合開発環境でもあり
Smalltalkの実行環境なんだよな。
emacsのlispをSmalltalkに置きかえたと考えればわかりやすい。
855デフォルトの名無しさん:2012/05/20(日) 15:01:44.14
>>853-854
よし、じゃあ次にどれくらい使われてるか
公平に判断するために、どこかが発表した
ラインキングを見てみるとしよう。

何か希望はあるかね?
ないならこちらで適当なランキングを
もってくるが、それだと不満だろう?
856デフォルトの名無しさん:2012/05/20(日) 15:08:03.81
>>855
なんで回答者に左右されるランキングが必要なんだ?
製品のダウンロード件数でも調べてくりゃいいじゃねぇか。
857デフォルトの名無しさん:2012/05/20(日) 15:08:38.06
あと販売数も。
858デフォルトの名無しさん:2012/05/20(日) 15:16:04.37
MUMPSとかランキングにまず上がらんけど
物流や医療じゃ高確率で見かけるからな
その癖ググっても資料がでてこないから苦労する

あとCOBOLもまずランキングにのる事はないが
未だに金融じゃ必ずと言っていいほど見かける

ネットで見かける需要が現実の需要と
一致してるとは限らんよ(COBOLはみんな
嫌々使ってんだろうけど)
859デフォルトの名無しさん:2012/05/20(日) 15:18:14.23
>>856
> なんで回答者に左右されるランキングが必要なんだ?

個人の意見じゃ、回答者(個人)に
左右されるからじゃないかw

同じ回答者でも、たくさんの意見を聞いたほうが良い。
回答者(多数)の方が信頼性が高いって言ってるんだよ。
860デフォルトの名無しさん:2012/05/20(日) 15:28:53.00
>>859
個人じゃなく販売数とか、ダウンロード数とか
確実な値で調べろと言ってるんだが
マスコミがキムチピザをランキングの1位にしてたからって信じるのか?
まともな思考なら販売店の商品別売上実績を調べるだろ。
861デフォルトの名無しさん:2012/05/20(日) 15:35:06.94
>>859
>回答者(多数)の方が信頼性が高い

理論的にはね。現実にはそううまくは実情は反映されない。
だからTIOBEを人気ランキングと勘違いする情弱が量産されてるんだと気づけよ。
862デフォルトの名無しさん:2012/05/20(日) 15:38:32.51
Haskellのダウンロード数とSqueakのダウンロード数を比べえみたら良いんじゃない?
関数型言語のドマイナーさ加減が情弱にも理解できて少しはおとなしくなるだろう。
863デフォルトの名無しさん:2012/05/20(日) 15:43:00.81
Haskell, Lisp, Smalltalk押しの俺はどうしたらいいんだ
864デフォルトの名無しさん:2012/05/20(日) 15:47:26.30
>>853
Win専用だけどDolphin Smalltalkというすばらしい処理系も忘れないでいてください。

イルカと言えば名古屋のSmalltalk勉強会はAmber押しだよね。
http://dynagoya.info/index.html

京都はVisualWorks、東京はSqueak/Pharo系か。
865デフォルトの名無しさん:2012/05/20(日) 15:53:17.14
linuxユーザーだから忘れてたわ
すまんすまん
866デフォルトの名無しさん:2012/05/20(日) 15:55:15.81
でも、C言語なんかと比べたら全然なんでしょ?
その時点でどうでも良くない?
豆粒みたいな普及率をどうのこうの言ったって仕方ないし、
どうせ、数字の見方の問題に話がそれるだけでしょう。

それより、関数型言語のスレらしく、、
関数型言語の優れている点でも語り合ったら?
手続き型言語には副作用を簡単に表現できる利点があるから、
それを上回るメリットが関数型言語に無いことにはねぇ。
手続き型言語でも、副作用を禁止して書いていくことは出来るし、
その場合は副作用が無いからとても安全に記述できるわけだけど、
それと比べて関数型言語に一体どれだけのメリットがあるのか。
特に最近は遅延評価をサポートしている手続き型言語もあるし。
867デフォルトの名無しさん:2012/05/20(日) 15:55:37.97
>>864
えるしってるか どるふぃんはまっくでもうごくw

http://www.youtube.com/watch?v=Te4Cx0Mz1Gw
868デフォルトの名無しさん:2012/05/20(日) 15:58:39.62
>>866
普及率自体はどうでも良くて社会基盤の一部として実働してることが重要。
そもそも玩具だの言い出したから始まった話だし。
869デフォルトの名無しさん:2012/05/20(日) 16:02:56.95
F-22や米国兵器ぐらいにしか使われておらず
普及しているとは全然言えないからAdaは
おもちゃだと言ってるのに似てるね
870デフォルトの名無しさん:2012/05/20(日) 17:16:45.10
Haskellは案外ドカタ向きなのかもしれんな。w

https://twitter.com/#!/hajimehoshi/status/204083496610832385
871デフォルトの名無しさん:2012/05/20(日) 19:22:30.25
>>860
> 個人じゃなく販売数とか、ダウンロード数とか
> 確実な値で調べろと言ってるんだが

公表されてないから調べようがない。
872デフォルトの名無しさん:2012/05/20(日) 19:27:28.72
ランキング厨って、「世の中の仕事の99%は事務処理だから、プログラミング含め、創造的と言われてる仕事は重要でない」と宣う奴みたいだな。
そんなのが何でブログラムスレに居るのかは謎だが。
873デフォルトの名無しさん:2012/05/20(日) 19:30:44.25
重要かどうかはどうでもいいよ。

実際、使われてないんだろ?
874デフォルトの名無しさん:2012/05/20(日) 19:40:27.89
利用者数なんて使いやすさ/間口の広さの指標ぐらいにしかならないでしょ
価値と直結してるとか考えてる人はちょっとやばい
875デフォルトの名無しさん:2012/05/20(日) 19:42:58.25
>>873 池沼か?
876デフォルトの名無しさん:2012/05/20(日) 19:54:04.24
え、言語においては、たくさんの人が使っているものは、
それだけ価値があるんじゃないの?
877デフォルトの名無しさん:2012/05/20(日) 20:04:00.42
>>876
違う。

違うっていうことはどういうことか分かるか?

反対ってことだ。

つまりあまり使われてない言語のほうが価値がある。
878デフォルトの名無しさん:2012/05/20(日) 20:04:02.84
やっぱ池沼か。うざいからどっか行ってくんないかな。
879デフォルトの名無しさん:2012/05/20(日) 20:04:52.04
日本語プログラミング言語のひまわりとか?
880デフォルトの名無しさん:2012/05/20(日) 20:07:24.83
おいおい。使われないクソ言語はいくらでもあるだろう。
そこは、言語の価値はシェアや人気とは無関係って方向にもってけよ。w
881デフォルトの名無しさん:2012/05/20(日) 20:08:41.00
柳刃包丁の包丁市場に占めるシェアみたいなものか

自分で書いてて例えが微妙な気がした
882デフォルトの名無しさん:2012/05/20(日) 20:22:03.52
Smalltalkみたいなマイナー言語を長年使ってると
こんな>>877書き込みするようになっちゃうの?
ガチなら狂ってるとしか思えないんだけど
883デフォルトの名無しさん:2012/05/20(日) 20:30:01.51
>>880
> そこは、言語の価値はシェアや人気とは無関係って方向にもってけよ。w

無関係ではない。
統計とはそういうもの。
データを集めれば、
概ね正しい結果が出てくる。
884デフォルトの名無しさん:2012/05/20(日) 20:37:40.84
ほら下らない展開。
だから、>>866で止めようって書いたのに。
885デフォルトの名無しさん:2012/05/20(日) 21:04:24.94
人海戦術は統計学に入りますか?
886デフォルトの名無しさん:2012/05/20(日) 21:14:05.78
入りません
887デフォルトの名無しさん:2012/05/20(日) 21:15:43.37
>>883
えー、ホントに?
じゃあこの結果も概ね正しいんだね

http://attractivechaos.github.com/HN-prog-lang-poll.png
888デフォルトの名無しさん:2012/05/20(日) 21:19:32.06
正しい統計結果を出すための前提が>>883の中で欠落してる件について。
889デフォルトの名無しさん:2012/05/20(日) 21:20:26.39
>>873
導入事例が存在するんだから使われてるに決まってんだろ
890デフォルトの名無しさん:2012/05/20(日) 21:21:45.47
>>883
じゃADAは国家レベルの事業でしか使われてないから価値がないのか
891デフォルトの名無しさん:2012/05/20(日) 21:23:48.90
>>871
電話かけて聞けよ
892デフォルトの名無しさん:2012/05/20(日) 21:27:29.64
あれだよな、スパコンじゃ9割7分Fortranが使われてて
科学技術の基礎や応用を作り上げてるが
ランキングに乗っていない以上無価値なんだよな
893デフォルトの名無しさん:2012/05/20(日) 21:27:38.81
電話かけて聞けよ
電話かけて聞けよ
電話かけて聞けよ
894デフォルトの名無しさん:2012/05/20(日) 21:28:33.26
>>893
恥ずかしいならメールでもいいぞ
895デフォルトの名無しさん:2012/05/20(日) 21:41:51.60
>>868
> そもそも玩具だの言い出したから始まった話だし。

そんなレス在ったっけ?って検索しても無いから
遡って探したら前スレで見つけた。


> 382 : 営利利用に関するLR審議中@詳細は自治スレへ : 2012/03/31(土) 14:28:58.16
> かつてのSmalltalkファンが 
> 今ではRubyやPythonを使ってるってのは良く在る話 

> Smalltalkは構文がダサくて読み難いし 
> Squeak/Pharoは玩具過ぎるし 
> Visual Worksはまるで古いVBみたいだし


こんな前の話をまだ根に持ってたのかよw
執念深過ぎwww
896デフォルトの名無しさん:2012/05/20(日) 21:53:12.69
そんな前のレス引っ張り出してきてドヤ顔のお前もそーとーあれだぞ。
897デフォルトの名無しさん:2012/05/20(日) 22:02:41.55
>>809 の事だろ
>トイプログラムの御題でくらいは存在感を出さないとね。
898デフォルトの名無しさん:2012/05/20(日) 22:21:34.69
なんだよ>>895のマッチポンプかよ。いよいよヤバイ奴っぽいな。
899デフォルトの名無しさん:2012/05/21(月) 07:31:14.84
マイナー言語使いって少し煽るだけで
顔真っ赤にして反論するからスレが荒れてうっとうしい
HaskellしかりSmalltalkしかり
少しはスルーしろよ、どんだけ余裕が無いんだよ
つーか日曜日の昼から2chかよ家族はどうした
900デフォルトの名無しさん:2012/05/21(月) 09:12:40.56
志村っ! 日食! 日食!
901デフォルトの名無しさん:2012/05/21(月) 19:50:14.05
>>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)
902デフォルトの名無しさん:2012/05/21(月) 22:26:30.65
いろいろスゴイ!
903デフォルトの名無しさん:2012/05/24(木) 18:05:17.49
そもそも847はなぜ関数型で書けないと思ったのか
Smalltalkのコードだってブロック(クロージャ)多用してるのに
904デフォルトの名無しさん:2012/05/24(木) 18:34:08.78
副作用を前提としたクロージャと、Haskell のそれはだいぶ違うと思うけど。
905デフォルトの名無しさん:2012/05/24(木) 19:04:47.32
オブジェクト指向も最初はそんな感じだったじゃないか
C言語で同じことができると思う奴と
だいぶ違うと思う奴に分かれていた
906デフォルトの名無しさん:2012/05/24(木) 20:08:35.48
いいかげん関数型言語 = Haskellの図式で語るのをやめなさい
OCamlとF#とSMLが怒りますよ
907デフォルトの名無しさん:2012/05/24(木) 20:13:47.73
C言語は実際凄いだろ。副作用がかけるし。
908デフォルトの名無しさん:2012/05/24(木) 21:03:56.77
Haskellでも副作用は書けるけどね
副作用の有無が型でキッチリ区別されて
静的型チェックの対象になるだけで
909sage:2012/05/25(金) 08:12:50.15
今時OOPが本当に優れていると考えているヤツなんているのかよ。
OOPなんて、回路基盤 -> アセンブリ -> C言語の延長線上にある、非常にアドホックな
考え方だと思うのだが。
多くの静的型付け関数型言語は次の利点があるのは有名だろ。

* 自動テストが容易
* 拡張に対する変更箇所が少ない
* 型で「ありえない状態」の存在を除去
* nullがない

関数型と比べて、OOPのいいことってなんだ?存在しないんじゃない?
910デフォルトの名無しさん:2012/05/25(金) 08:43:38.16
今どき、静的型のメリットと関数型のメリットを混同している奴がいるとはな。
あといい加減、OOP(あるいはもっと一般化した抽象データ型)と関数型は
型による抽象化か関数による抽象化かという抽象化手法の違いに過ぎず、
つまりそれぞれ得手不得手があるし互いにある程度補い合う事が可能な
考え方だってことに気づけよ。
911デフォルトの名無しさん:2012/05/25(金) 08:49:33.01
つまりOCaml(関数型+抽象データ型)とScala(抽象データ型+関数型)が最強というわけでつね。
912sage:2012/05/25(金) 09:13:10.98
>>910
OOPの得意な抽象化手法ってなんぞや。
カプセル化、多態性、継承はHaskellの方が優れていると思うのだが。
913デフォルトの名無しさん:2012/05/25(金) 10:00:48.53
関数型言語の方が優れていますが
同時に優れたプログラマを必要とするので流行りません
914デフォルトの名無しさん:2012/05/25(金) 10:07:25.99
どうりでRubyが流行るわけだ
915デフォルトの名無しさん:2012/05/25(金) 10:11:57.06
黒板言語とその仲間たちと、実用は別だからな。
916デフォルトの名無しさん:2012/05/25(金) 10:18:37.09
存在する処理系を認識できないような脳をしている >>915 のような人間もいるしな。
917デフォルトの名無しさん:2012/05/25(金) 10:26:44.60
>>912
カプセル化・継承・多態性というお題目は、OOPにおいてクラスを用いて
抽象データ型が実現されている(その恩恵〜かつてはそう信じられていた〜として
継承による差分プログラミングや、付随して多態性もある)ということを言い表わしてるだけなので
OOPで可能な抽象化手法を列挙したものではないってのはOK?
加えて、OOPにおいてクラスが単なる(SIMULAからの)借り物なのに対して、
抽象データ型を最初から視野においてよく練られたHaskellの型クラスが優秀なのは
あたりまえといえば当たり前。
Haskellはよく純粋な関数型と言われるけれど、OOPのように抽象データ型にクラスを使っていない
というだけで、言語としては関数型と抽象データ型のハイブリッド。

しいて言えば、クラスのように関数(メソッド)を型に内包する機構を使って
実現された抽象データ型の場合、関数型で好まれる関数を型の外に置く
抽象データ型(狭義の抽象データ型。CLUやAdaなんかもこの類)に比べて
型を追加する拡張が得意だし、その逆で後者は関数(その結果としてインターフェイス)を
増やす拡張が容易という程度の得手不得手はある。
http://www.cs.utexas.edu/~wcook/papers/OOPvsADT/CookOOPvsADT90.pdf
918デフォルトの名無しさん:2012/05/25(金) 10:39:11.21
>>912
Haskell のカプセル化って何?
カプセル化って副作用のための仕組みじゃないの?
919デフォルトの名無しさん:2012/05/25(金) 10:49:14.56
カプセル化→隠蔽工作
920デフォルトの名無しさん:2012/05/25(金) 10:50:04.22
>>917
出典がちょっと古いな。
今はハイブリッドもある。
921デフォルトの名無しさん:2012/05/25(金) 10:50:55.89
>>918
カプセル化っていうのは有り体に言えば抽象データ型、簡単にはユーザー定義型のこと。
あるいはその作業・手法のこと。OOPでは抽象データ型にクラスを使うから副作用の封じ込め的な
イメージがあるけれど、広い意味での抽象データ型においてはそれだけを意図したものではないよ。
922デフォルトの名無しさん:2012/05/25(金) 10:55:47.86
カプセル化というのはアクセス制御をちゃんとやることです
もっといえば必要なもの以外はpublicにすんな、ということです
923デフォルトの名無しさん:2012/05/25(金) 10:57:00.98
>>920
切り分ければそうだというだけで、別にクラスを使った関数(メソッド)を
内包させるタイプの抽象データ型と、内包しない狭義の抽象データ型の共存が
できないということを意味するものではないよ。
PythonとかScalaとかC#とか普通に(後者は特に巧妙に)やっているでしょう。
924デフォルトの名無しさん:2012/05/25(金) 11:04:29.57
>>922
坊や。危ないからこんなところに来ちゃだめだよ。ほらほらOOP村にお戻りなさい。
925デフォルトの名無しさん:2012/05/25(金) 11:09:01.64
>>921
だとしても「継承、多態、カプセル化」と並べられた場合
カプセル化が意味するところは封じ込めのほうで良いのでは?
926デフォルトの名無しさん:2012/05/25(金) 11:28:10.90
>>921
haskellでのカプセル化はモジュール化して公開するシンボルを制限することだと思うが

>簡単にはユーザー定義型
カプセル化とオブジェクト化を混同してないか
927デフォルトの名無しさん:2012/05/25(金) 11:38:11.45
>>925
必ずしも副作用の「封じ込め」に特化した作業や仕組み、を意図しないのであればはなから異論は無いよ。
それとも、この文脈における「カプセル化」を抽象データ型やユーザー定義型と
言い換えることがダメってこと? それなら君はエセ識者に間違った知識を植え付けられている。
http://www.cs.swan.ac.uk/~csulrich/ftp/adt/adt.pdf
http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.55.8524&rep=rep1&type=pdf
928デフォルトの名無しさん:2012/05/25(金) 11:49:49.56
ADTは、カプセル化の型システムからの射影。
929デフォルトの名無しさん:2012/05/25(金) 12:01:22.74
OOPの文脈で
データの抽象化:データと振る舞いを一つにまとめること(クラスベースやプロトタイプベースで実現)
カプセル化:整合性を保つため内部への直接の操作を制限すること(アクセス指定子やクロージャで実現)
930デフォルトの名無しさん:2012/05/25(金) 12:32:36.76
抽象化:派生クラスが何個あるのか気にしない
カプセル化:メンバ変数が何個あるのか気にしない

「obj.fooとobj.barは絶対にアクセスするなよ」と言われると逆に気になってしまう
931デフォルトの名無しさん:2012/05/25(金) 14:12:53.84
OOPのカプセル化も公開するシンボルの制限にすぎんだろ

副作用を制限するって言ってるけど、OOPでカプセル化すれば
同じメソッド呼び出しが常に同じ結果を返すようになるんか?
ならないなら副作用の何を制限してるんだ?
932デフォルトの名無しさん:2012/05/25(金) 15:16:47.49
>>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} "
933デフォルトの名無しさん:2012/05/25(金) 21:14:49.94
>>932
HaskellのMultiSetはimmutableだから、SmalltalkのBagとはその点で違うよ

immutableなコレクションに値を次々突っ込んでいく場合、
foldl等使って次々に新しいコレクションを生成する必要があるけど、
mutableなデータ構造で同じことやっても無意味に遅いだけだし

だからSmalltalkで真似したときに意味を見出せないのは当然だと思う
934デフォルトの名無しさん:2012/05/25(金) 21:22:35.75
immutableなデータ構造や副作用の隔離による
ミス防止の恩恵は、うっかりなプログラマには嬉しいものだが
全く必要としないプログラマも居るんだよな

SmalltalkerにはHaskellのメリットなんて拘束具にしか見えんのかもしれんね
935デフォルトの名無しさん:2012/05/25(金) 22:02:29.67
>>931
副作用をもたらす経路を制限出来る、というのは副作用を許す言語にとってかなり大きいことだよ
936デフォルトの名無しさん:2012/05/26(土) 00:09:31.75
>>934
つまり、マルチセットをイミュータブルにして、その状態は
リストや再帰コンテキストに封じ込めて破壊的操作の代替にするのは
ミス防止のためっていう理解であってます?
具体的にはどんなミスが想定されて、イミュータブルにすることで
どうしてそれが防げるのか教えてもらえますか?
937デフォルトの名無しさん:2012/05/26(土) 00:41:19.76
>>936
同じ値が複数箇所から参照されてるケースを考えれば分かるよ。
938デフォルトの名無しさん:2012/05/26(土) 01:14:49.41
そういや>>932ってどのくらいの実行速度だったの?
次世代高速CogVM(笑)だから速いんだよね?
939デフォルトの名無しさん:2012/05/26(土) 09:47:01.25
暫定ダイナブック環境ww
老害しか使わないOSもどきの玩具www
940デフォルトの名無しさん:2012/05/26(土) 10:21:30.92
レッテル貼りしかできない馬鹿wwwwwwww
941デフォルトの名無しさん:2012/05/26(土) 16:49:39.04
オブジェクト指向言語って今でもあるのか。
942デフォルトの名無しさん:2012/05/26(土) 18:02:27.90
>>941
お前が何の言語を知っているのか
すごく不安になるwwww
943デフォルトの名無しさん:2012/05/27(日) 17:36:36.53
自分で作った訳でもない言語をドネーションも無しで手に入れて、他の言語ファンを叩くのに使うのが楽しい人って何時の世でも居るんだな。

訂正:本当に使ってるかは判らんか。
944デフォルトの名無しさん:2012/05/27(日) 17:56:22.96
ドネーションの意味がわからない。
どないしよん。

>>943
笑うところだよ。
945デフォルトの名無しさん:2012/05/27(日) 17:59:29.34
HaskellやSmalltalk使ってる人達は
JavaやC#使ってる人達をドカタ呼ばわりして
見下してるから好感が持てる
946デフォルトの名無しさん:2012/05/27(日) 18:06:23.19
>>945
最後の行で不覚にも
947944:2012/05/27(日) 18:26:08.71
・・・
948941:2012/05/27(日) 19:55:08.90
>>942
Smalltalkっていう言語があったのは知ってるけど。あの言語の
ような徹してオブジェクト指向という言語はあるのかい?
949デフォルトの名無しさん:2012/05/27(日) 20:01:34.46
値打ちのわからない者には何の役にもたたないということ。
950デフォルトの名無しさん:2012/05/27(日) 20:24:44.13
>>948
> ような徹してオブジェクト指向という言語はあるのかい?

中置演算子っぽく見せかけて実は他のメッセージと同じ扱いなので
2 + 3 * 4 => 20 になるような言語ってこと?
951デフォルトの名無しさん:2012/05/28(月) 08:52:12.04
Rubyをdisろうとして失敗してる?
952デフォルトの名無しさん:2012/05/28(月) 19:40:32.58
お題:
整数型を引数に取る、次の性質を満たす関数fを定義せよ。

f(f(x)) = -x

OOPLで解く場合は x.f.f = -x でも良い。
953デフォルトの名無しさん:2012/05/28(月) 20:02:24.48
def f(x):
 return complex(0, x)
954デフォルトの名無しさん:2012/05/28(月) 20:31:07.66
>>953
二回目の関数適用でfの引数が複素数になるぞ。
955 ◆QZaw55cn4c :2012/05/28(月) 20:43:18.80
場合わけはOK?
f(x) = -x (x >= 0)
f(x) = +x (x <= 0)
956デフォルトの名無しさん:2012/05/28(月) 20:46:51.86
operator=だかoperator==だかを置き換えればいいのだな!
957 ◆QZaw55cn4c :2012/05/28(月) 20:50:52.15
>>955
ごめん。これ x < 0 のときf(f(x)) = x だった。
降参だ。
958デフォルトの名無しさん:2012/05/28(月) 20:58:11.75
>>957
何か問題でも?
959デフォルトの名無しさん:2012/05/28(月) 21:38:52.33
>>958
御題の条件が自然数なら問題ないけど、整数だからね
960デフォルトの名無しさん:2012/05/28(月) 21:41:12.33
f(f(x)) = -x
なので
f(f( f(f(x)) )) = x

引数が整数型なので戻り値も整数型
オブジェクトもタプルも複素数も使えない

分かんね
961デフォルトの名無しさん:2012/05/28(月) 21:58:10.67
こんな感じかな。

f 0 = 0
f k | k > 0 = if odd k then k+1 else 1-k
f k = - f (-k)
962デフォルトの名無しさん:2012/05/28(月) 21:59:05.84
>>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 "
963デフォルトの名無しさん:2012/05/28(月) 22:02:39.76
あ、いかん。負数の実行例を忘れた。

-1 f f "=> 1 "
-2 f f "=> 2 "
-3 f f "=> 3 "
964デフォルトの名無しさん:2012/05/28(月) 22:15:18.79
>961が正攻法なんだろうけど、>962も面白いな。
965デフォルトの名無しさん:2012/05/28(月) 22:18:46.71
>>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]
966デフォルトの名無しさん:2012/05/29(火) 17:56:51.52
-----------まとめ----------
「馬鹿は死なねば治らないのであり、だからこそアナトール・フランスは
『愚かな者は、邪悪な者よりも忌まわしい』と言ったのだ。
 邪悪な者は休むときがあるが、愚かな者はけっして休まないからである。」
(ホセ・オルテガ・イ・ガセット 1883〜1955)

http://toro.2ch.net/test/read.cgi/tech/1336122899/247
>ゲームは作らんから知らんが、
224 == 247 == 704 == 717 == http://logsoku.com/thread/toro.2ch.net/tech/1335361193/46
口癖はコンポジション、ミサイルとホーミングミサイルの設計について1ヶ月間も考え続けてる
http://toro.2ch.net/test/read.cgi/tech/1336122899/772
>ゲーム作らなくてもお前よりマトモ
タスクの実行順序を意識しないとゲームが作れない(笑)
http://toro.2ch.net/test/read.cgi/tech/1336122899/767
敵機 → プレイヤー の順序でタスクを実行するとタスクがぶっ壊れる
OOを得意げに語っているつもりが、やっている事が20年前のC言語だったという事実
バイナリの書き換えがわからない
コンパイラ言語のことをコンパイル言語とか言っちゃう
タイプミスの数々、右手の人差し指と中指をケガしてる模様
http://toro.2ch.net/test/read.cgi/tech/1336122899/190
http://toro.2ch.net/test/read.cgi/tech/1336122899/297
http://toro.2ch.net/test/read.cgi/tech/1325246820/837-839
http://toro.2ch.net/test/read.cgi/tech/1336122899/318-320
http://toro.2ch.net/test/read.cgi/tech/1336122899/332-334
http://toro.2ch.net/test/read.cgi/tech/1336122899/818
http://toro.2ch.net/test/read.cgi/tech/1336122899/956
967デフォルトの名無しさん:2012/05/29(火) 20:37:17.13
このスレもそろそろ終わりか

関数型言語を覚えられない頭の可哀想なPGだけが
オブジェクト指向言語を使う、でFA
968デフォルトの名無しさん:2012/05/29(火) 21:34:33.15
お前ん中ではなwwwww
969デフォルトの名無しさん:2012/05/29(火) 22:06:07.06
関数型の駄目なところやその使い手のコミュ障っぷりはよく分かったけど
メリットはいまいち見えてこなかったなぁ…
970デフォルトの名無しさん:2012/05/29(火) 22:48:47.42
自分の脳に障害があると疑ったほうがいいぞwwwww
971デフォルトの名無しさん:2012/05/30(水) 01:36:49.43
でも手続き型のほうが副作用を簡単に書けて便利じゃないですか。
972デフォルトの名無しさん
手続き型言語は確かに沢山あるけど、オブジェクト指向言語なんて
呼べるものはほとんどないのではないかな。