トップページ⇒tech
1001コメント388KB

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

■ このスレッドは過去ログ倉庫に格納されています
0001営利利用に関するLR審議中@詳細は自治スレへ2012/04/07(土) 21:26:47.61
一般的には、オブジェクト指向型言語が優勢でが
一部には関数型言語を崇拝している人もいます

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

前スレ http://toro.2ch.net/test/read.cgi/tech/1331328955/
0605デフォルトの名無しさん2012/04/29(日) 12:42:30.36
>>599
それで、代入を禁止するのと共用体を禁止するのは、どっちが良いんですか
0606デフォルトの名無しさん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

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

全文を引用して、該当のtrueを【】でくくって下さい。
0610デフォルトの名無しさん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スクリプトなんてモードがあるんですね。
実行オプションでそんなに差が出るものなんですか?
0611デフォルトの名無しさん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*
0612デフォルトの名無しさん2012/04/29(日) 13:56:15.31
>>608
お前が良く見た方がいい
0613デフォルトの名無しさん2012/04/29(日) 14:10:28.74
括弧を省略する言語は危険
式と文を区別しない言語も危険
0614デフォルトの名無しさん2012/04/29(日) 14:12:28.08
>>613
蛇の国からようこそおこしやす
0615デフォルトの名無しさん2012/04/29(日) 14:22:29.08
Lisp系から見るとHaskellも括弧省略言語だな
0616デフォルトの名無しさん2012/04/29(日) 19:36:04.13
λ式に比べたらLispだって
0617デフォルトの名無しさん2012/04/30(月) 00:25:42.19
>>616
Lispの関数は
apply = foldl ($)
(((f x) y) z) == (apply f) [x, y, z]
省略ではなく、式を変形している
(x, y, zの型が異なる場合、Haskellは上の式が間違っていると主張する)
0618デフォルトの名無しさん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。
まだまだ遅いけど。
0619デフォルトの名無しさん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) }
}
0620デフォルトの名無しさん2012/04/30(月) 01:42:08.34
やっぱり手続き型のC言語が
こういうのは一番早いね。
0621デフォルトの名無しさん2012/04/30(月) 06:36:40.19
つまりCの関数を簡単に呼べる言語が優秀
0622デフォルトの名無しさん2012/04/30(月) 08:02:32.77
なんだ。Rubyが最強ってことか。
0623デフォルトの名無しさん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)))
0624デフォルトの名無しさん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]]
0625デフォルトの名無しさん2012/04/30(月) 20:00:22.80
速度が必要な極一部の処理だけ
速い言語(C/C++/Java)で書けば良いのに
クソ遅い言語で速度競っててワロタwww
0626デフォルトの名無しさん2012/04/30(月) 20:14:25.98
なんだJava厨か
0627デフォルトの名無しさん2012/04/30(月) 20:25:46.03
Ruby「実行速度とかそんなの求めてませんから(キリッ」
0628デフォルトの名無しさん2012/04/30(月) 21:11:28.94
>>546のコードをJavaにベタ移植したんですが
C言語に比べて物凄く遅いです(6.5倍遅い)
(出力が遅すぎるので、そこをコメントアウトしてもまだ遅いです)

http://ideone.com/FoYga

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

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

これは静的単一代入 (SSA) です。
SSAは関数型に入りますか?
0645デフォルトの名無しさん2012/05/01(火) 20:59:05.32
y = x + 5 は一次関数。あとは説明要らんよな。
0646デフォルトの名無しさん2012/05/01(火) 21:02:58.15
そもそも、型に入るとか入らないとかいう型の理論が要らない
0647デフォルトの名無しさん2012/05/01(火) 21:47:34.44
型がないと、実行時にしかメソッド名の解決ができない。
これは開発工数が伸びる原因になる。
0648デフォルトの名無しさん2012/05/01(火) 21:56:43.18
なんという緻密な分析
0649デフォルトの名無しさん2012/05/01(火) 22:03:59.52
関数"型"の話してんだろコミュ障
0650デフォルトの名無しさん2012/05/01(火) 22:36:11.12
>>649
だから、型ですよね?
0651デフォルトの名無しさん2012/05/01(火) 22:36:32.17
型だよ型。
0652デフォルトの名無しさん2012/05/01(火) 22:37:00.05
型の話しようぜ。
0653uy2012/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
0654デフォルトの名無しさん2012/05/02(水) 03:53:50.68
ぶっちゃけ関数型もオブジェクト指向もどうでも良くて
自分が使ってる言語以外をdisりたいだけだよね
0655デフォルトの名無しさん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]
0656デフォルトの名無しさん2012/05/02(水) 11:34:39.78
こっちは要素の重複を取り除かないバージョン

import Data.List
perm' [] = [[]]
perm' xs = [x:y | x <- xs, y <- perm $ delete x xs]
0657uy2012/05/02(水) 13:23:15.71
>>655
Rubyのpermutationって誰も知らないのか話題にならないから俺が最初に2chにコード投下したやつじゃん(半年前くらいに)
67の冗長ゴミカスRubyソースコードを添削しただけだよ
0658デフォルトの名無しさん2012/05/02(水) 13:33:49.06
へえー、これ良いね。
0659デフォルトの名無しさん2012/05/02(水) 15:29:43.37
>>658
いやHaskellでもRubyでも標準添付や組み込みのライブラリに入ってますし…
0660デフォルトの名無しさん2012/05/03(木) 10:07:46.90
>>655
要素の重複を取り除くところでバグるかもしれない点は面白い
0661デフォルトの名無しさん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)) "
0662デフォルトの名無しさん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
0663デフォルトの名無しさん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})))
0664デフォルトの名無しさん2012/05/05(土) 00:05:09.38
 ttps://metalab.at/wiki/Lambdaheads
こんなひとおる?
0665デフォルトの名無しさん2012/05/06(日) 08:01:00.40
未だに関数型言語の機能が欲しいと思ったことがない。
俺みたいな奴は案外多いんじゃないかね。
そんなことよりトランザクショナルメモリはよ。
0666デフォルトの名無しさん2012/05/06(日) 09:25:35.24
欲しいと思う機能はそれほど多くない
だが変な機能をゴリ押しされるとそれに対抗するものが欲しくなる
ゴリ押しを断るために、先約があるとかいって他のを抜擢するみたいな話は案外多い
0667デフォルトの名無しさん2012/05/06(日) 11:09:05.44
うむ。関数型言語というより
コレクションライブラリがあれば
十分だったりするw

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

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

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

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

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

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

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

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

push/pullは、上に上げたようにFRPでも取り上げられてるし、
他にはWebアプリフレームワークとかXML系APIとか、
いろいろなところでAPIデザインの選択肢として語られてる。
大げさに騒ぐような概念じゃないけど。
0686デフォルトの名無しさん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) と書かれる。
0687デフォルトの名無しさん2012/05/06(日) 22:02:41.17
URL貼れってか
http://conal.net/papers/push-pull-frp/push-pull-frp.pdf
0688デフォルトの名無しさん2012/05/06(日) 22:14:04.87
でも、FRP自体は明らかに関係ない概念だよね?
pullとpushの概念引っ張ってくるためだとしても。

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

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

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

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

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