関数型言語は何故普及しないのかを考える

このエントリーをはてなブックマークに追加
952デフォルトの名無しさん:2010/10/11(月) 16:05:38
Perlはオブジェクト指向言語だっけ?
953デフォルトの名無しさん:2010/10/11(月) 16:07:28
>>952
packageをクラスに見立ててオブジェクト指向は実現できるよ。
954デフォルトの名無しさん:2010/10/11(月) 16:08:23
>>951
それ、nakeと命令したら、にゃーにゃーと言って、
sineと命令したら、ぎゃーと言って、
namaeと言ったら、タマと言う猫になってるよw

人語を話す猫はちょっと想定外w
955デフォルトの名無しさん:2010/10/11(月) 16:09:04
>>953
あぁ、Perlだからオブジェクト指向の例だったのね。
956デフォルトの名無しさん:2010/10/11(月) 16:15:22
>>955
オブジェクト指向版
my $cat = neko->new;
$cat->namae;
$cat->nake;
$cat->sine;

package neko;

sub new {
my $self = shift or die $!;
my $hash = { namae => 'タマ' };
return bless $hash, $self;
}

sub namae {
my $self = shift or die $!;

print $self->{namae}, "\n";
}

sub nake {
my $self = shift or die $!;

print "にゃーにゃー\n";
}

sub sine {
my $self = shift or die $!;

print "ぎゃーーー\n";
}
957デフォルトの名無しさん:2010/10/11(月) 16:15:33
>>948
get系メソッドで状態が変化するわけではないので
letかwhereで束縛するだけでいいのでは
958デフォルトの名無しさん:2010/10/11(月) 16:17:34
>>954
>>944が作って欲しいのはこう言うのじゃないの?

>>955
いや、>>951はプロセス指向版
959デフォルトの名無しさん:2010/10/11(月) 16:18:21
>>956
理解した!
スレッドつかったら、プロセス指向になるんだ!
960デフォルトの名無しさん:2010/10/11(月) 16:19:33
さすがperl使いだな
仕事が早いw
961475:2010/10/11(月) 16:20:28
>>950
>IO モナドをどう使えば何が出来るか、何が出来ないか、
>Arrow を使えばどう記述しやすくなるか、ならないか、

あ、スマンが、それを分かり易く、言い換えると「数学用語を使わずに」説明してくれないかな?
>>935で書いたけど、自分はモナド/アローと格闘中。で、一時的に敗北を認め、
今は代数の勉強からやり直しているところ(群と束までは何となくイメージが湧くんだけどね)。
だから、説明してくれるとすごく嬉しいね。

>逆に訊くが、バーコード表示コンポーネントに
>圏論の概念の何が必要か挙げてくれ。

バーコード表示コンポーネントなら不要かもしれない。スマン。
ただ、事務系処理と圏論の概念という話題は、>>475の関数指向設計技法の話と関連するかもしれない。
まだモヤモヤした状態なので、後からレスするよ。
962475:2010/10/11(月) 16:21:47
>>957
えーと、変数 tama に「何」を束縛するの?
963デフォルトの名無しさん:2010/10/11(月) 16:23:44
>>959
スレッドでもいいんだけど、ネイティブスレッドは非常に重いので、
今必死で各方面でerlangのような軽量プロセスを実装しようと試みている人がいるよ。
perはメモリ周りが柔軟なので、ネイティブだけど割と軽い。
Cと比べたら激遅なんだけどねw

あと、スレッドを使うだけではなくて、ロック機構を全く使っていないことに注目して欲しい。
メッセージパッシングにスレッドセーフなキューを採用している。
964デフォルトの名無しさん:2010/10/11(月) 16:25:17
なんだ。結局プロセス指向って
オブジェクト指向言語での
書き方の一つなんじゃねーか。
紛らわしいw
965デフォルトの名無しさん:2010/10/11(月) 16:26:33
>>964
いや、ちょっとまって、どこをどう見たら>>951>>956がおなじに見えるの?
966デフォルトの名無しさん:2010/10/11(月) 16:34:52
これだけは前提としてくれ

オブジェクト指向のインスタンスのメソッドをたたくことをメッセージというが
これは
プロセス指向のメッセージパシングのメッセージとはぜんぜん別物。

しかたがないから名前つけるか。
前者:オブジェクト指向メッセージ(略してOM)
後者:プロセス指向メッセージ(略してPM)

以上
967デフォルトの名無しさん:2010/10/11(月) 16:39:46
もう少しだけ分かりやすいプロセス指向のコードをperlで書いてみた。
use threads;
use Thread::Queue;

my $q = Thread::Queue->new;
my $th = neko($q);
my $q2 = Thread::Queue->new;
my $th2 = neko($q2);
$q->enqueue({command=>'namae', namae=>'タマ'});
$q2->enqueue({command=>'namae', namae=>'シロ'});
$q2->enqueue({command=>'nero'});
$q->enqueue({command=>'nake'});
$q->enqueue({command=>'sine'});
$q2->enqueue({command=>'sine'});
$th->join;
$th2->join;

sub neko {
my $q = shift or die $!;

return threads->new(sub {
my $namae = '';

while (1) {
my $message = $q->dequeue();

if ($$message{command} eq 'namae') {
$namae = $$message{namae};
print "命名:$namae\n";
} elsif ($$message{command} eq 'nake') {
print "にゃーにゃー\n";
968475:2010/10/11(月) 16:40:00
では、(>>844が言うところの)プロセス指向言語でもある GHC(KL1) で参戦w

% オブジェクト TAMA の定義

tama(InqueryStream, ReplyStream) :- tama(InqueryStream, ReplyStream, 'TAMA').

tama([namae | InqueryStream], [Name | ReplyStream], Name) :- tama(InqueryStream, ReplyStream, Name).
tama([nake | InqueryStream], ['NYA NYA' | ReplyStream], Name) :- tama(InqueryStream, ReplyStream, Name).
tama([shine | InqueryStream], ['GYA---' | ReplyStream], Name) :- tama(InqueryStream, ReplyStream, Name).


% オブジェクトTAMA の使い方。ここで、instream はキー入力(標準入力)に、outstream は画面出力(標準出力)に相当する。

?- instream(InqueryStream), tama(InqueryStream, ReplyStream), outstream(ReplyStream).
969デフォルトの名無しさん:2010/10/11(月) 16:40:28
} elsif ($$message{command} eq 'nero') {
print "$namaeが寝ます。\n";
sleep(3);
print "$namaeが起きました。\n"

} elsif ($$message{command} eq 'sine') {
print "$namaeが死んでしまいました\n";
last;
}
}
});
}
970967:2010/10/11(月) 16:45:13
よく見て欲しいのが$namae変数。
これは一つの関数のローカル変数に過ぎない。
関数型言語なら引数に与えて再帰することで状態を持たずに済むので、
プロセス指向は非常に関数型言語にとって有利な方法なんだ。
971デフォルトの名無しさん:2010/10/11(月) 16:49:10
>>961
> あ、スマンが、それを分かり易く、言い換えると「数学用語を使わずに」説明してくれないかな?

IO モナドを使えば IO との入出力ができる。
印刷ライブラリも呼べる。
FFI を使って Haskell 用には書かれていないライブラリにも
IO モナドとしてアクセスできる。

バーコードを印刷するアプリの「モナド」に関しては
これくらい知ってるだけで基礎知識としては十分。
あとは自分でライブラリを探して利用することができる。

代数や圏論など出る幕ではない。


>>961
んだよ、じゃあ帳票印刷パッケージでいいよ
代数やら圏論やらの理解がどれほど必要だ?
972デフォルトの名無しさん:2010/10/11(月) 16:51:06
>>971
> 帳票印刷パッケージ
そんなもんそのへんの乞食にやらしとけよw
100円ぐらいやってくれるんじゃね?

俺らの仕事は数億円の仕事だからさw
一緒にしないでよw
973デフォルトの名無しさん:2010/10/11(月) 16:51:35
>>971
おっとスマン

FFI を利用して外部ライブラリを呼ぶのなら、
メモリ領域破棄のタイミングについても知っていないと、
商用のアプリやライブラリとしてはちょっとお粗末だった。

でも、やっぱり代数や圏論の知識は要らんな。
974デフォルトの名無しさん:2010/10/11(月) 16:56:53
>>932
俺じゃなくて、745 に言ってくれ。
彼が >>941 で自ら例を挙げたんだから。

彼は、君が乞食にやらしとけよと言うモノを作るのに、
代数やら圏論やら難しい概念を正確に理解することが必要なんだと言っている。
975デフォルトの名無しさん:2010/10/11(月) 17:00:04
fizzbuzzがやっと書けるレベルでも印刷アプリぐらいつくれるだろw
976475:2010/10/11(月) 17:01:57
>俺らの仕事は数億円の仕事だからさw
>一緒にしないでよw

事務系処理であれば、大企業の基幹システム開発とか銀行の勘定系システムだと、
ハード抜きソフト開発費だけで数億の案件なんてザラにあるんだよ。
君が言う100円くらいでやってくれるというCOBOLプログラマが奮闘している。

ところでHaskellで数億円って、どんなお仕事なの?教えて欲しいなーーーーw
977デフォルトの名無しさん:2010/10/11(月) 17:02:13
100円の仕事やらせるのに難しい知識なんていらないんだよ
978デフォルトの名無しさん:2010/10/11(月) 17:04:33
>>976
鉄道関係でZ言語使って設計したよ。
実装は他の言語だがな。
979475:2010/10/11(月) 17:17:37
>>978
Zは形式的仕様記述言語だろ。関数の概念も使うけど、それを言い出せば手続き型言語でも関数は使う。
レスとしては、適切ではないな。

で、HaskellでHaskellで数億円って、どんなお仕事なの?
980デフォルトの名無しさん:2010/10/11(月) 17:21:55
君の仕事が乞食相当100円の仕事だと言われたと思って怒ってるの?
それ以前にHaskellで商売してるって誰が言ってるの?
981デフォルトの名無しさん:2010/10/11(月) 17:25:43
>>979
Zは述語論理の言語だよ。
982デフォルトの名無しさん:2010/10/11(月) 17:29:48
475 は下らん奴らの相手をしている暇があるなら、
帳票印刷パッケージで代数やら圏論やら
難しい概念を正確に理解する必要性を説いてくれないだろうか。

バカの戯言など無視して集中してくれ
983デフォルトの名無しさん:2010/10/11(月) 17:30:12
>>970
> よく見て欲しいのが$namae変数。
> これは一つの関数のローカル変数に過ぎない。
> 関数型言語なら引数に与えて再帰することで状態を持たずに済むので、
> プロセス指向は非常に関数型言語にとって有利な方法なんだ。

それは名前を取得しているだけだから
ローカル変数ですむんだろ?

function get_namae() {
 return "tama"
}
と同じこと。

現実的には、名前を決めるメソッドも必要。この場合はどうなるのさ。
984デフォルトの名無しさん:2010/10/11(月) 17:31:52
>>983
オブジェクト指向では状態を持たないとやりたいことは実現できないよ。
985デフォルトの名無しさん:2010/10/11(月) 17:41:14
>>983
> と同じこと。
ぜんぜん違う。
その方法ではオブジェクト指向的には、
タマバージョンとシロバージョンの2種類のクラスを別々に作る必要が出てくる。
一つのクラスでやろうと思ったら名前をつけるメソッドを用意して、
フィールドにnamae変数を用意しなければならない。

一方でプロセス指向ではフィールドに該当するものを持っても良いし持たなくても良い。
関数型言語を使うなら持たなくても良い。
986デフォルトの名無しさん:2010/10/11(月) 17:50:01
>>984-985

それでプロセス指向ならどうするか
って答えがでてないよ。
987デフォルトの名無しさん:2010/10/11(月) 17:55:20
>>986
>>967

コードを良く読んでいないでしょ?
実行すらしていないんじゃないの。
988デフォルトの名無しさん:2010/10/11(月) 17:57:14
Queueは副作用あるから関数型じゃないし
オブジェクト指向はObserverパターンを散々推奨しておいて今更dequeue()はないだろ

両方とも詰んでるんだよ
989475:2010/10/11(月) 17:57:52
>>971,973,982
>>475で始めた一連のカキコでは「関数指向設計技法」というものを提案した。
で、入出力データを代数的データ型で定義するところまでは説明したけど、
それら入出力集合間の写像(関数)をどのように定義する方法論については、以下のように
曖昧な表現で終わっており、それを>>500でツッコまれていた。

>>497
>(2)副関数群への分解手順(アルゴリズム)について、JSP法の考え方に沿って(JSP法を模倣して、あるいは
>   JSP法の用語を使って)、指導者が普通のプログラマへ説明する

実は、事務系処理は(100円でもやってもらえるような)比較的単純な機械労働のように
見られがちだけど、世界中のソフトウェア工学の権威が取り組んできていたにもかかわらず、
未だに解決できていない領域の一つだったりする。

上の写像定義であれば、入出力集合間の関係が準同形であれば比較的たやすい。
形式的な関数定義を導出することが可能。(言い換えると、プログラムの自動生成が可能。)
ところがそうでない場合、これをJSP法では「構造不一致」と呼ばれているが、
case-by-caseで、言い換えると設計者の「経験と勘」で対応せざるをえないのが現実。

JSPにおける構造不一致(structure clashs)については、以下の文献を参照してくれ。(英語だよ)

・The Jackson Development Methods (Michael A Jackson 1992)
  http://www.jacksonworkbench.co.uk/resources.htm

(長いので続く)
990デフォルトの名無しさん:2010/10/11(月) 17:59:29
>>987
そのコードのどこに、名前を変更する処理が入ってるのさ?
インスタンス生成時に、値設定しているだけじゃないか。

> タマバージョンとシロバージョンの2種類のクラスを別々に作る必要が出てくる。
それから、これ訂正すべきだな。

クラスは1種類(猫クラス)だけで十分。
インスタンスは複数必要だが。
事実プロセス指向とやらでも、インスタンスは複数あるよな。

> $q->enqueue({command=>'namae', namae=>'タマ'});
> $q2->enqueue({command=>'namae', namae=>'シロ'});
991デフォルトの名無しさん:2010/10/11(月) 18:01:03
つまり、プロセス指向とやらは、
インスタンスを、その言語で定義されたインスタンスというもので表すか、
perlのようにハッシュをインスタンスとして使うかの違いでしかないのか?
992デフォルトの名無しさん:2010/10/11(月) 18:02:55
手続き型言語では、データ(構造体)とそれを扱う関数が分かれていた。
プロセス指向は、その構造体をハッシュにすることで
構造体の型の定義を作らないですむようにしたもの。

これでいいのか?
993デフォルトの名無しさん:2010/10/11(月) 18:09:31
C#にはクラスのインスタンス時のみに値を設定できるreadonlyって属性があるんだわ。
http://msdn.microsoft.com/ja-jp/library/acdd6hb7(VS.80).aspx

これを使えば、あと状態を変えることができなくなる。

プロセス指向ってのは、このように
状態を最初に設定することだけできて、
後から設定する変数を持たないようにしたクラスと同じ。

プロセス指向だけで、ソフトウェアが作れることはまずなくて、
状態をあとから変更できないようにしておけば、
バグが少なくなるよって考え方のことだろう。
994475:2010/10/11(月) 18:15:26
>>988
えーと、>>968では副作用なんてありませんですよ。関数型言語じゃなくて論理型言語だけどねw
Prologだとretract/assertみたいな副作用が必須だったけど、並列論理型言語では副作用無しに状態を保持し、
ストリームを応用してクラス間の継承(インヘリタンス)すら記述できます。

というか、Haskellでの参戦者はいないの? (自分は、このスレじゃHaskellに批判的な立場だから書かないぜ)
ストリーム(無限リスト)を使えば、>>968相当の処理は、もっとエレガントに記述できるんだけど。
これは関数型的思考プロセス段位であれば「中級」に相当するレベルだよ。>>909
誰も皆、モナド・モナド・モナド・モナド・モナド・モナド・モナド・モナド.... ばかり考えているから、
昔の純粋関数型言語におけるストリーム指向プログラミング技法なんて忘れ去られてしまったのかな?

>>993
(>>844が言うところの)プロセス指向を間違って理解しちゃってますヨ
995デフォルトの名無しさん:2010/10/11(月) 18:19:37
出発点がおかしいんだわ。

ソフトウェアを状態を持たないで作ることは不可能なんだよね。
それが関数型言語で言えばモナドになる。
オブジェクト指向で言えば、インスタンスのこと。
(インスタンスではないクラスはメソッドの集まりなんで状態を持ってないよ。基本的に。)

実体を持たないメソッドを抽象メソッドと呼ぶように、
状態を変更しないメソッドを、関数とかプロセス指向(?)とか
言っているだけではないか?

結局は特殊な性質を持ったメソッドに、さもえらそうな名前をつけているだけ。
996デフォルトの名無しさん:2010/10/11(月) 18:21:51
> 状態を変更しないメソッド

あぁ、C++でいうconstメソッドのことねw
997デフォルトの名無しさん:2010/10/11(月) 18:40:54
語尾に指向をつければ、なんでもすごく感じるメソッド指向
998デフォルトの名無しさん:2010/10/11(月) 18:44:19
俺えんてっど
999デフォルトの名無しさん:2010/10/11(月) 18:47:21
>>995
メソッドって特殊な性質を持った手続きのことでしょ
1000デフォルトの名無しさん:2010/10/11(月) 18:47:36
1000なら関数型言語は普及しない。
10011001
このスレッドは1000を超えました。
もう書けないので、新しいスレッドを立ててくださいです。。。