ようこそ!浜村拓夫の世界へ

    ブログ内検索

    最近の記事

    ブックマーク数の多い記事

    Blog Translation

    Powered By FC2ブログ

    Powered By FC2ブログ
    ブログやるならFC2ブログ


    FC2ブログ LOGIN

    with Ajax Amazon

    関数型言語とメソッドチェーン

    このエントリーを含むはてなブックマーク はてなブックマーク - 関数型言語とメソッドチェーン あとで読む
    関数型言語が活用できていない。
    今のところ、関数型言語の出番はないんだけど、切り札はたくさん持っていた方が、いざというときに困らない。
    プログラム言語の選択肢の一つとして、関数型言語の使いどころについては理解しておきたい。

    関数型言語の本質って、そもそも何なんだろう?
    eugenio moggi | Tumblr

    TuringとChurchとMoggiの狭間で
    チューリング: コンピュータの基礎を考えたよ.どんなプログラムもチューリングマシンで実行できるよ.

    チャーチ: 書き換え?逐次処理?そんな方法だと数学的にナンセンスだよ.それよりラムダ式を使おうよ.プログラムは函数だよ.

    モッジ: プログラムを函数だと思うと,ダイナミックな入出力を考えた時に組合せ爆発するよ.プログラムはクライスリ圏の射だよ.



    おおざっぱには、(非関数型言語でも使われている)「メソッドチェーン」と似たようなもんかな?と思ったけど、「副作用」に対する考え方とか、やっぱ根本的に全然違うのかな?

    検索してみたら、いろいろな参考情報が出てきた。
    関数型言語 メソッドチェーン - Google 検索

    ●関数型言語
    以前、LispやOCamlを、ちょろっと使ってみた。
    これらのプログラム言語は、プログラミング・パラダイムを学ぶ上で参考にはなったが、「すごい便利だ!」という感動はなかった。
    たかだか、動的なWebサイトを作る程度なら、PHPで十分だった。

    関数型言語 - Wikipedia

    関数型言語(functional language)は、関数型プログラミングに向いた特徴を持つプログラミング言語、関数型プログラミング言語である。引数に関数を作用(applicate)させて計算をおこなうことから、作用型言語(applicational language)ともいう。データフロープログラミング言語も関数型言語の一種である。

    ここでの「関数」とは、数学でいう「関数」であり、手続き型プログラミングなどにおける「関数」ではないことをまず注意する。典型的には原則としては副作用がないものであることが挙げられる。

    関数への引数がプログラムへの入力で、関数を引数に作用させて評価して得られる値がプログラムからの出力であるとすると、コンピュータプログラムはある種の関数であると考えることができる。ここで、入力や出力は記憶装置中のファイルのようなものばかりではなく、マウスの動きの情報といった入力や、画面への表示といった出力も考えられる。
    複雑なコンピュータプログラムに相当する関数を作るために、第一級関数を扱えることなどが関数型言語には必要である。



    第一級関数 - Wikipedia

    計算機科学において、第一級関数(first-class function、ファーストクラスファンクション)とは、関数を第一級オブジェクトとして扱うことのできるプログラミング言語の性質、またはそのような関数のことである。

    具体的にはプログラムの実行時に生成され、データ構造に含めることができ、他の関数の引数として渡したり、戻り値として返したりすることのできる関数をいう。この概念はメタプログラミングとは異なり、コンパイラ呼び出しやeval関数によって生成された関数は含まれない。

    第一級関数は関数型言語には必要不可欠であり、高階関数のような形で日常的に用いられる。
    例として、関数とリストを引数に取り、リストの各要素に関数を適用した結果のリストを返すmap (mapcar) 関数が挙げられる。map関数をサポートするプログラミング言語は、何らかの形で関数を関数の引数として渡すことを許容しなければならない。



    高階関数 - Wikipedia

    高階関数(higher-order function)とは、第一級関数をサポートしているプログラミング言語において、関数を引数にしたり、あるいは関数を戻り値とするような関数のことである。
    引数や戻り値の関数もまた高階関数となり得る。
    これは主に関数型言語やその背景理論であるラムダ計算において多用される。
    数学でも同様の概念はあり、汎関数と呼ばれる。



    手続き型言語における高階関数
    手続き型言語や、手続き型をベースにしたオブジェクト指向言語でも、同等かそれに近い機能を実現させる機構を備えているものがある。C/C++における関数ポインタなどがその一例である。またC#にはデリゲートという機能がある。
    一方、関数を戻り値とする関数を書くことは難しい。これは戻り値となる関数の実行時にその関数を定義した時点での環境が必要になる(クロージャ)ためである。



    クロージャ - Wikipedia

    クロージャ(クロージャー、closure、閉包)はプログラミング言語における関数オブジェクトの一種。
    引数以外の変数を実行時の環境ではなく、自身が定義された環境(静的スコープ)において解決することを特徴とする。
    関数とそれを評価する環境のペアであるともいえる。
    まれに、関数ではなくとも、環境に紐付けられたデータ構造のことをクロージャと呼ぶ場合もある。

    概要
    典型的にはクロージャは、外側の関数(以下、エンクロージャ)の内側の関数リテラルや、ネストした関数定義によって必要になる。
    言語により、そのような内側の関数内に出現する自由変数(内側の関数の仮引数でもなく、内側の関数自身のローカル変数でもない変数)の扱いは異なるが、自由変数が、その呼び出しにおけるエンクロージャのその名前の変数を、レキシカルに参照するのがクロージャであり、実行時に外部の関数が実行された際、クロージャが形成される。クロージャは内部の関数のコードとエンクロージャのスコープ内の必要なすべての変数への参照からなる。

    クロージャはプログラム内で環境を共有するための仕組みである。
    レキシカル変数はグローバルな名前空間を占有しないという点でグローバル変数とは異なっている。
    またオブジェクトのインスタンス変数とは、オブジェクトのインスタンスではなく関数の呼び出しに束縛されているという点で異なる。
    クロージャは関数型言語では遅延評価やカプセル化のために、また高階関数の引数として広く用いられる。



    副作用 (プログラム) - Wikipedia

    プログラミングにおける副作用(ふくさよう)とは、ある機能がコンピュータの(論理的な)状態を変化させ、それ以降で得られる結果に影響を与えることをいう。代表的な例は変数への値の代入である。

    例えば与えられた数字を二倍して返す機能"double"があるとする。
    このような機能では次のことが成立する。
    ・同じ条件を与えれば必ず同じ結果が得られる
    ・他のいかなる機能の結果にも影響を与えない

    このような性質を参照透過性という。
    参照透過な機能はそれ自身状態を持たないことで副作用と独立している。

    一方状態を持つ機能"add"を考える。
    addは外側の変数eを増加させて返すものとすれば、このような機能では見えない所で条件を変化させてしまうために、参照透過性の一つ目の仮定が崩れ、また他のeを利用する機能の結果も変化させるので二つ目の仮定も成立しない。
    addは副作用を持つ機能である。

    ノイマン型のアーキテクチャは副作用を前提として動作するため、多くのプログラミング言語では変数の破壊的代入機能を持つ。一方関数型言語では原則として副作用を存在しないものとみなし、モナドなどの手法で抽象化している。

    機能が副作用を持たないことの利点は、いかなる状況でも常に同じ結果が得られるために、機能を純粋にアルゴリズムとして定義でき、状況依存でのバグの発生が抑えられるということである。反面副作用を持たない言語設計はノイマン型アーキテクチャと反りが合わず、効率の点で不利になることが多い。また単純な逐次処理を行う場合は状態を中心に命令的な思考をした方が扱いやすい場合がある。このためLISPやMLなどは原則として関数型ながら、副作用を許容する設計になっている。



    モナド (プログラミング) - Wikipedia

    計算機科学におけるモナド(Monads)とは、計算機科学者のEugenio Moggiによって提案されたモジュール性を持たせた表示的意味論の枠組みを言う。
    プログラムとはクライスリ圏の射である(program is arrow of Kleisli category)、という要請から合成規則としてクライスリトリプル(Kleisli triple)というモナドと等価なものが用いられる。
    モナドの名称は、圏論のモナド(モノイド+トライアド)に基づいており、ライプニッツのモナド(単子論)とは無関係である。



    圏論 - Wikipedia

    圏論(けんろん、英語:category theory)とは、代数的な構造の変換の自然さを形式化するために導入された理論である。射のクラスである圏とその間の対応である関手、構造の自然さを表す自然変換が主な道具立てである。



    圏論とは - はてなキーワード

    圏(カテゴリー)は、ある公理系を満たすような構造全体を考察する際の“定式化の枠組み”を与える。

    ホモロジー代数、トポロジー、代数幾何などでは、圏論が基本的な道具となっているが、様々な分野において、構造に関する理論を整理して記述する枠組みとしても重宝する。
    また近年では、物理やコンピューティング・サイエンス(情報科学)にも圏論が応用される傾向にある。
    その例として、量子計算の高水準の記述、ラムダ計算の意味論、型理論の定式化、諸々の計算効果/計算現象の(モナドによる)整理などが挙げられる。



    数学の勉強が不十分だったので、圏論ってのがよく分からんかった。
    はじめての圏論 その第1歩:しりとりの圏 - 檜山正幸のキマイラ飼育記
    モナド的代数系と一般化クライスリ圏 - 檜山正幸のキマイラ飼育記

    関数型言語を理解するときのキーワードは、
    ・第1級関数
    ・副作用
    ・参照透過性
    ・モナド
    ・圏論
    とか、かな?

    ●データと処理
    プログラムを構成する要素には、「データ」と「処理」の2つがある。
    データと処理 - 浜村拓夫の世界

    プログラミングとは一言でいえば、データを扱うための処理を作ることだった。

    どんなに複雑なコンピューターのプログラムであってさえも、その構成要素は、
    ・データ
    ・処理
    というたった2つの要素に分解、還元できる。

    このことに気付くと、プログラミング技法の学習は、スッキリとした見通しのもとに進めることができる。



    「処理」すなわち「計算」とは、
    (1) データの入力 (=引数)
    (2) データの加工
    (3) データの出力 (=戻り値)
    の3つのパートから成っている。

    関数型言語は、この(1)と(3)の、データの入出力において、「関数」を扱えるということだな。
    Lispみたいにカッコをズラズラ並べて、処理を数珠繋ぎにしている様は、メソッドチェーンと似てると思った。

    関数型言語とメソッドチェーンの違いとして、
    ・関数型言語 → 宣言 → 静的
    ・メソッドチェーン → 逐次 → 動的
    という、感覚的な隔たりがあるのだろうか?

    やってて楽しいプログラミング言語は? 3言語

    921 :デフォルトの名無しさん:2012/05/15(火) 08:30:54.40
    >>919
    >環境が変化する順(フロー)を意識しなければならないメソッド呼び出しは、
    >宣言的とは言いがたいと私は思います。


    これは、Haskellでもdo構文使えば同じように手続き的になると思うのですが・・・

    それは置いておいて、rubyやsmalltalkのような純粋なOOだと、メソッドチェーンが繋がりやすいのですが、これは関数型言語も関数適用の連鎖で最終的にほしい関数を作るのに似てるな・・・と感じます
    ただ、ほしい関数(やメソッド)の部品として作られた関数(やメソッド)の作り方が関数型言語はやっぱり関数適用であるのに対して、オブジェクト指向は手続き的になるな・・・と感じました

    そして、順序を意識したHaskellのdo構文は、関数数適用という考え方のまま、手続き型をエミュレートしてるという感覚を最近感じています



    関数型言語では、プログラムを、木構造(ツリー)としてとらえると、分かりやすいようだ。
    全てが式になる,全てが木になる,全てが式木になる - NyaRuRuが地球にいたころ

    gauche.nightで出た話題だけど、関数型プログラマはプログラムを木だと思ってるらしい。
    関数型プログラマは関数呼び出しの中に関数を書くことに抵抗がない。
    でもC言語とかだとさ、関数呼び出しの中に関数って書かないじゃん、普通。すごく短いやつを除けば、だいたい一旦変数に代入するでしょ。
    そのへんの違いが関数型言語を学ぶときの抵抗になってるのかなぁと思った。
    そういう目で見れば、Rubyのメソッドチェーンは「木構造を使わずに関数的な処理を書くための発明」っていう風に見えてきませんか?

    大多数のプログラマにとって,関数呼び出しは関数呼び出しだし,変数代入は変数代入,ストリーム演算子はストリーム演算子,みたいな意識の壁がある.



    ここら辺が、関数型言語の取っつきにくい原因かな?
    関数型言語が普及しない理由 - 偏見プログラマの語り!

    プログラムは副作用を起こすために存在しているのですが、それ以外の部分は副作用で書く必要など無いのです。この視点こそがオブジェクト指向言語から関数型言語へ飛び移るチケットではなかろうかと思うのです。

    関数型言語はひたすら副作用の無いものを組み合わせて全体を組み立て、副作用は局所化して扱うようにプログラミングするための言語ですきっと。



    副作用の局所化

    関数プログラミングスタイル - 八発白中

    関数プログラミングスタイルを貫くには、
    1. 副作用を必要以上に使わない
    2. やむを得ず使う場合はmain関数にまとめる
    3. コードを短い関数に分散する



    関数型言語へ引越しする準備として、
    ・副作用を使わないように意識して、プログラミングする。
    ・木構造を意識して、メソッドチェーンを活用する。
    とか、コーディング規約を設ければ、移行しやすいかな?

    まあ、関数型言語の出番は今のところないんだけど、バグを防ぐコンセプトは参考にしたい。
    関連記事

    コメント

    コメントの投稿


    管理者にだけ表示を許可する

    トラックバック

    トラックバックURL:
    http://hamamuratakuo.blog61.fc2.com/tb.php/842-99bde59a

    FC2Ad