関数型言語を採用するプロジェクトが増加、果たして本当に開発効率は高いのか? 83
ストーリー by reo
二極化とかさあ 部門より
二極化とかさあ 部門より
insiderman 曰く、
ソフトウェア開発に Scala や Haskell、Erlang といった関数型言語を採用する企業が増えているそうだ (ITpro の記事より) 。
関数型プログラミング言語には「迅速に開発できる、バグを抑えやすい、アプリケーションの性能を向上させやすい」といった特徴があるとし、これらは新規のサービス開発に向いているという。「言語選定が競争力に直結」といった意見も記事には掲載されている。
これだけだといいことずくめのようにも聞こえるが、関数型言語は習得しにくく、ライブラリなども C/C++ や Java と比べるとまだ少ない。使いこなせるプログラマも少なく、関数型言語で大規模システムの設計を行えるエンジニアはまだ少ないのではないだろうか。関数型言語を使える人材はある程度スキルの高い人であり、そのために生産性が高いのではという疑問もある。今後日本で関数型言語の採用は進んでいくのだろうか?
バグを抑えやすい、かー (スコア:2)
Haskellを触ってみた感じ、デバッグが難しそうなんだけど、バグ自体が少ないから構わないって言うのかな?
Re:バグを抑えやすい、かー (スコア:5, 参考になる)
Haskell のデバッグは絶望的に難しい。従来の手続型言語のようなステップ実行によるデバッグは、あんまり役に立たない。
自分は GHC しか知らないけど、クラッシュした時にスタックトレースすらとれない。
というか、基本が遅延評価の Haskell は原理的にスタックトレースに意味がないので、たいていはどこでクラッシュしたのかすらわからない。
バグの個数は 100分の1になるけど、残り1%のバグが 100 倍強力になって襲い掛かってくる感じ。
つまらない NullPointerException や ClassCastException に悩まされるようなことはほぼなくなるから、そういう意味ではバグを抑えやすいのは確かかもしれないね。
デバッグが難しい代わりにテスト周りは充実していて、QuickCheck [nikkeibp.co.jp] なんかはすごい便利。
だからとにかく丁寧にテストを積み重ねていって、あとはバグに遭遇しないことを神に祈るのが Haskell 流だと思う。
Re:バグを抑えやすい、かー (スコア:4, 参考になる)
バグ自体が少ないと言っているのは,
・プロジェクト数が少ない
・実行時バグの余地が少ない
と2通りあります.
前者は仕方のないことで,
別に批判されるべきことじゃありませんよね.
後者については型システム(およびコンパイラ)が,
性質を静的に保障してくれることが多く,
これは開発のうえで非常に強力です.
デバッグの難しさについては,
ちょっと真面目にすごいH [amazon.co.jp]で勉強した私はそうは思いません.
まず, テストのしやすさは手続型言語よりも容易です.
また, 従来再現しにくいバグの発見に至っては, そもそも入力が同じであれば必ず再現できます.
「触ってみた感じ」ということですから, あまり体系的に勉強していないんじゃないでしょうか?
もし単に謙遜しているだけで,
実はベテランということだったら本当にごめんなさい.でも, その場合はデバッグがどう難しいかをコメントしてくれれば,
多くの人にとって, とてもinformativeなコメントになりますよ
Re:バグを抑えやすい、かー (スコア:2)
変数が無く、動かしながら確認するっていうのが難しいから、ひたすらソースコードを見てバグを突き止めざるを得ないと思った。
参照透明性があるからテストは容易なのだろうけど、printf的な出し方が面倒。
Re:バグを抑えやすい、かー (スコア:1)
Debug.Traceモジュールとか便利ですよ。
http://www.haskell.org/ghc/docs/latest/html/libraries/base-4.6.0.1/Deb... [haskell.org]
Re: (スコア:0)
すごいH本にデバッギングの解説ってあったっけ?あんまり精読してないので、見落としたかも。
今ちょっと日本語版が手元にないので英語版 [learnyouahaskell.com](無料で全部読めるよ!)の目次見たけど、
それっぽいのが見当たらない
Re:バグを抑えやすい、かー (スコア:2)
デバッギングの解説はないですが,
実行中の挙動について表示させる例はありましたよね.
そう, 12章の"Walk in the line"の例です.
失敗するかもしれない関数landLeft,landRightの仕様をMaybeという文脈つけて変更していました.
でも実はこれだけじゃなくて,
純粋な関数であったとしても, トレースを使えます.
山本先生のブログ記事 [hatena.ne.jp]
究極的には, プログラムがstuckするのは,
パターンマッチに転けた場合が多いです.
そのときパターンマッチした際の値を得ることで,
原因は大体わかりますよね
Re:バグを抑えやすい、かー (スコア:5, 参考になる)
自分の書いたコードのパターンマッチングで落っこちるとちゃんと行番号が出てくるし、オプションつければ漏れがあっても警告出るから問題ないね。
困るのはゼロ除算や head [] で落ちたりとか、クラッシュせずに誤った結果を返してくるときとかかな。
head [] なんて、エラーメッセージは "Prelude.head: empty list" だけだからね。どうやって原因を突き止めろと。
trace を埋め込む場所がわかるなら、バグは半分見つけたようなもので……。
自分はその山本さんの記事も読んだことあるんだけど、
あと、例外がどこから来たのか知りたい場合は、GHC のデバッガを使うといいでしょう。
という一文にがっかりした覚えが。その GHCi のデバッガが、ほとんど役に立たないんだよ……。
だいたい GHCi (Haskell 処理系のデファクトスタンダードだね)のデバッガのマニュアルがこんな調子なんだよ。
プログラムをデバッグしている時にしばしば問われる問いの一つに、「どうやってここに来たんだ?」というものがある。伝統的な命令的デバッガは通常何らかのスタックトレースの機能を持っていて、それを使ってアクティブな関数呼び出しのスタック(字句的呼び出しスタックと呼ばれることもある)を確認することができる。このスタックによって、現在の地点に至るまでのコード上の道のりが分かる。残念なことに、これをHaskellで用意するのは難しい。正格な言語と違って、実行は深さ優先ではなく必要に応じて進むからである。
もう一つデバッグ中によく発生する疑問として、「この例外はどこから来たんだ?」というものがある。errorやhead []によって発生する例外には文脈情報が付属していない。プログラム中のどのheadの呼び出しがエラーの原因になったかを調べるのは骨の折れる作業であり、通常Debug.Trace.traceを使ったり、プロファイル付きでコンパイルして+RTS -xc(5.3. 時間及び確保量のプロファイルを取るを見よ)を使ったりすることになる。
GHCiデバッガの提供する方法を使うと、このようなエラーを素早く、かつコードを再コンパイルすることなしに突き止めることが、うまくすればできるかもしれない。
http://www.kotha.net/ghcguide_ja/7.0.4/ghci-debugger.html [kotha.net]
うまくすれば (hopefully) っておい……。Haskell のデバッグの難しさを知りたければ、このマニュアル読むのが参考になると思う。
Re: (スコア:0)
場当たり的なコメントで申し訳ないですが,
head []はパターンマッチで書く方が筋が良い.
(listToMaybe的なものをつかっても一緒)
ゼロ除算はcatchするよりも,
Integerを使うか最初から除算に気をつければいい.
失敗するかもしれない演算なんだから.
手続き型言語の例外は最初から想定しているもので,
それぞれcatchすればいいよね, という風潮だけど,
関数型言語の例外は, 発生しないように書くという前提.
究極的には関数型言語を好きになるかどうかって,
例外が発生しうる範囲が非常に限定されているんだから, 最初から避けて設計するよね,
というのを受け入れるか否かの違いだと思う.
Re:バグを抑えやすい、かー (スコア:1)
んで、その「究極的には」の内容を実践できる人だけが、「いいねーいいねー」って言いながら使っているから、バグが少ないって「思われている」だけなんじゃなかろか?
VBやPHPなんかで、バグがそりゃもうひどいことになるのは、言語設計がどうのと言うよりも、技術屋のレベルの問題に落とし込める気がしてなぁ。
Re:バグを抑えやすい、かー (スコア:1)
つまりだ、Haskellで開発するから技術者集まれ!ってやると優秀なのだけ集まってくるって訳だな。
素晴らしい。
# 実際身の回りの関数型言語を好む人って優秀な言語フリークが多いイメージ。
# もしくは、そういう優秀なフリークに英才教育されてる感じ。
# ちゃんと生き残ってついて行ければ優秀に育つだろうなぁ。
# 数学的な訓練を受けていないとあまり直感的ではないので
# そもそも優秀なフリークが身近に居ないとはまりにくいと言うのと、
# コミュニティが狭いので優秀なフリークが直接手ほどき出来る程度の規模で
# 布教に熱心になりやすいというのはあると思う。
経営者視点からすると (スコア:2)
高度なプログラムを書く人間は人件費が高い
なので多少バグっても顧客のいうものを作れる使い潰しのきく安いプログラマーを連れてこい。
みたいな感じになるのでなかなか普及しないかも。
Re:経営者視点からすると (スコア:2)
>顧客のいうものを作れる使い潰しのきく安いプログラマー
これ、考えようによってはかなりスキルが高いのでは?
Re: (スコア:0)
実現するだけなら結構難しくはない。
それをバグ無し及び効率的な手段で、となると一気に難易度が上るだけで。
プログラムで言うならソートしたい時にバブルソート(ライブラリ使わず自力実装するとして)なら馬鹿でもできるけど
そうなると結果ソートはできても量が膨大だと効率が悪い。
しかし敏腕プログラマならもっと複雑な実装で効率のいいソートアルゴリズムが組める。
ロジックのバグとりは楽 (スコア:2)
関数型言語は、ちゃんとロジックに落ちている仕様を確実にプログラムにするあたりには役に立つようには思う。けど、多くのバグ、とくに悩ましいバグは、そのロジックに落とす前の「もやもや」っとした部分。
「やりたいことをこう整理すれば、希望する結果が得られるはず」と思ってアルゴリズム組むけど、そこに穴があって、orz ってことに。
あと、ロジックの実装ミスは、綺麗なコーディングに心がける(歪な局所抜け出しとかさせずに、入れ子構造を正しく保つ)とか naming ルールを整理しておけば、けっこう、ソースコードの形でバグが見えてきたりする場合があると感じている。関数型言語は、その歪さ検出を言語仕様に入れているだけ、というのは、浅はかな理解?
Re:ロジックのバグとりは楽 (スコア:1)
大体合ってると思います
有名な話に, 「A well typed program never gets "stuck"」があるように,
きちんと設計された関数型言語の一つの目的です
もっと言うと, そうした検出機能があると言うより,
そう書かなければ文法として正しくない.
# と言う割にHaskellはパターン漏れはデフォルトで許容してるんだよなあ
# デフォルトで-Wオプション使えってことかもしれないけど
C言語って関数型では・・・? (スコア:1)
同時に「構造化プログラミング」という手法もセットでしたが
Re:C言語って関数型では・・・? (スコア:1)
C言語の関数ポインタと、関数型言語でいう関数が違うものだということに納得できるまでには結構時間がかかりました。
例えば、C言語では、引数に基づいて新しく関数を作って、その関数を戻り値として返す関数、というものを実現できません。例えば、2引数の関数fに対し、引数を一つだけ適用した新しい関数を返す関数gは、Hakellで書けば、
g f x = f x
ですが、これをC言語で記述する方法は、私にはわかりません。
Re:C言語って関数型では・・・? (スコア:1)
こんな感じかな.
http://blog.pineapple.cc/post/13011926756/c [pineapple.cc]
Re: (スコア:0)
手続き型の呪縛を取り払って考えましょう。
Re:C言語って関数型では・・・? (スコア:1)
Re:C言語って関数型では・・・? (スコア:1)
C++のtemplate使えば関数型っぽいプログラミングは出来るね。
デバッグで軽く死ねるけど。
Re: (スコア:0)
これはひどい
Re: (スコア:0)
http://twitter.com/PG_sister_bot/status/298430516988874752 [twitter.com]
これ思い出した
因果関係はどっち? (スコア:1)
そもそも関数型言語を使いこなせるプログラマのレベルが高いから、結果として
ということは無い?
Re: (スコア:0)
間違いなくその通りだと思うけど、夢のないこと言うなよ。
関数型言語の特長だと言っておけばみんな幸せなんだ。
# どうせ一般レベルに普及するのはまだ先だし(その前に廃れるかも知れん)
なげやりに一言 (スコア:1)
そうだFORTHを使え
Lispを使えばいいじゃん (スコア:0)
FORTRANと並ぶ太古からの歴史のあるLispを使えばいいじゃないか
Re:Lispを使えばいいじゃん (スコア:3)
common lispで
パターンマッチさせたいならCLOSを。
マッチして高度に分解したいならoptimaを。
遅延評価させたいならCLAZYを。
メモ化させたいならfare-memoizationを。
複雑に繰り返したいならiterateを。
なんでもござれ、みなさんいらっしゃい・・・
新人。プログラマレベルをポケモンで言うと、コラッタぐらい
Re:Lispを使えばいいじゃん (スコア:2)
つい昨日、clでプログラムを組んだ卒論を提出したところなんですが、
ひょっとして20年前というのはANSI CLが存在する前なのでは・・・
新人。プログラマレベルをポケモンで言うと、コラッタぐらい
Re:Lispを使えばいいじゃん (スコア:2)
画像だけでいいならvectoで。
インタラクティブなGUIが必要ならcl-gtk2です。
新人。プログラマレベルをポケモンで言うと、コラッタぐらい
Re:Lispを使えばいいじゃん (スコア:2)
え、タートルグラフィックスのソフトウェアを作るということですよね?
新人。プログラマレベルをポケモンで言うと、コラッタぐらい
Re: (スコア:0)
関数型に馴染んでない素人(俺)がLispを使ってみると、
prognだのifだのを使いまくって手続き型じゃんってことに。
Re:Lispを使えばいいじゃん (スコア:2)
あれはメリットだと思うけどな。見た目はカッコだらけで異様(?)でも、実はスタイルや用途を選ばない万能言語。
Re: (スコア:0)
あ、それ俺だ
昔、LOGO を使ってアプリ組むバイトをしたんだが、思いっきり関数型的な
作り方でやっちゃった。
動作スピードも、関数型でやるよりずっと速くしたんだけどね
#誰だかばれるかな(汗
Scala は関数型言語界のC++ (スコア:0)
いぜんちょっと囓っただけだけど、Javaの言語仕様を包含してるのがメリットでありデメリットに感じた。
>ライブラリなども C/C++ や Java と比べるとまだ少ない。
javaのライブラリがそのまま呼べたはずなので、この問題だけはすくないけど、
記述が煩雑で言語仕様が無駄に複雑。
おかげでコードの読みにくさはかなりのもので、仕事で使いたいとは思わなかった。
Re:Scala は関数型言語界のC++ (スコア:1)
論理的に常に正しく考えられる頭のいい人しか使えない言語だと思います。
世の中の大半のプログラマがそこまで頭がいいわけではないので、現実問題として普及しないのではないかなあと。
問題が起きにくいけれど習得のハードルが高い言語よりも、習得しやすい言語のデバッグ環境を強化していく方向が現実解の気がします。
普及しないのは別の要因だと思う (スコア:0)
オブジェクト指向言語だって、オブジェクト指向らしいコードを書けるプログラマばっかりでないのに普及してるし。
Scalaみたいな言語も有力なところがプッシュしたら、関数型らしいコードが書けるプログラマが少なくても普及すると思う。
Re: (スコア:0)
オブジェクト指向はメリットが見えやすかったからね。
カプセル化なんて初心者プログラマでも「なるほど、確かに自然で分かりやすい!」だし、
切り分け方が非プログラマ(経営層、マネージャ層)にも分かりやすいのも良い。
UMLやらOO分析手法の助けもあって、上流から下流まで一貫性があるし。(震え声)
さて、関数型言語はどうだろう?
Re:普及しないのは別の要因だと思う (スコア:1)
関数型言語でユーザが関数を定義せずに8割方のプログラムが書けるのなら普及すると思います.
本当にそうであればよかったですよね. init()メソッドしかないクラスなんて存在しなかったでしょうし, しかもそれが1メソッドで数千行も続くこともなかったでしょうし.
Re: (スコア:0)
>javaのライブラリがそのまま呼べた
バグの内包とかを考えると、これはメリットなのかデメリットなのか・・・。
Re: (スコア:0)
Groovyにかけた時間を返して
-> Scalaに時間をかける気などない
に遷移するのが正解。
Javaで不可能なことがScala環境になれば出来るということも無い
使いこなせるプログラマも少なく、 (スコア:0)
一山いくらで使い潰せていくらでも代わりが効くスキルのほうがいいというのは経営者の論理だろ。
雇われる立場では他人と差別化できるスキルがなきゃ使い潰されるだけだぞ
ライブラリ (スコア:0)
実際に仕事で言語を使う場合、
言語を使ってるというよりもライブラリを使ってるという側面が大きくて
どの程度ライブラリがそろってるかということは
言語自体の質よりも格段に重要だと思える。
開発言語オタクや専門家に持ち上げられる言語って、
たいていライブラリがあんまり充実してなくて、
サンプルがコマンドラインで動かす程度のものしか無いんだよね。
「で、これで何作るの?」とでも言うしかないレベル。
ウィンドウシステムからマルチメディアコントロールまで自力で作れる人には
問題ないんだろうけどね。
Re:ライブラリ (スコア:1)
Haskell は GUI ツールキットもあるし、OpenGL も呼べるしWeb アプリケーションフレームワークだってある。
もちろん選択肢は少ないけど、ぜんぜんないわけじゃないんだよね。
それに Scala は JavaVM で動いて Java の API 全部呼べるし、F# に至っては .NET Framework の一部。
F# や Scala ならライブラリの心配はないんじゃないかな。
全部を一つの言語で作る必要も無いわけで (スコア:1)
うちの会社はとある大規模並列処理にErlang、そのジョブを管理するマネージャにPython、Web周りや検索系、Hadoop、HBaseにJavaを使ったプロジェクトをやっています。Erlangで全部賄おうというつもりは毛頭無く、システムの売りのコアになる特定処理に絞って投入しています。仮に既存のライブラリが少なくてもそれがカバーする範囲と自前で用意できる実装が目的とピタリとマッチすればすごく強力です。
そして全ての言語でゲンミツにロジックを共有したい場合はCで書くという・・・
Re: (スコア:0)
ScalaのPlayFrameworkはなかなか便利、Railsくらい便利かって言われるとわからないが。
お腹一杯 (スコア:0)
> 関数型言語で大規模システムの設計を行えるエンジニアはまだ少ないのではないだろうか
いやいや、ひいひい言いながら「オブジェクト指向+デザパタ」の実務経験を積んできたんだがな~。orz
関数型云々じゃなくて (スコア:0)
並列処理に強いプログラミング言語だからじゃないの?
Re:デメリットは? (スコア:1)
優秀な人間にしか使いこなせない。
手続型言語での記述は、人間が作業手順を落としこむ時の記載方法に近く、普通に日常的な思考の持ち主でも記述できる。
関数型言語での記述は、人間が普通に行っている思考とかけ離れているので、新しい思考方法を身につけるまでハードルが高い。単純な物なら何とかなるけど、複雑な条件分岐を含むような物を関数型言語に落とすのは常人には難しい。