筑波大学計算機数学グループ春の館山合宿での講演「数学プログラムを Haskell で書くべき6の理由」の発表資料。実際の講演映像は https://www.youtube.com/watch?v=S4_7KVNA-Ww Read less
「val」で不変の値を定義する際に、「lazy」修飾子をつけると、値が遅延評価される(最初にアクセスされたときにのみ評価され、定義時には評価されない)ようになります。 「lazy」は「val」にのみ設定できます。「var」や「def」に設定することはできません。 値の評価は「最初にアクセスされたときに1回のみ」行なわれます。 複数回呼び出した場合、2回目以降は値の評価は行なわれず、初回の評価結果が返されます。 ここが「def」と違うところですね。「def」でも値は遅延評価になりますが、値の評価は参照時に毎回行なわれます。 // lazyをつけると、値の評価が初回アクセス時にのみ行われるようになる。 lazy val a = { println("eval a"); "a" } // var や def には適用できない。 // 以下はコンパイルエラー // lazy var b = { "
hello mum");a.close()},find_slide_number:function(e){var c=e.indexOf("#");if(c<0){return 0}var b=unescape(e.substr(c+1));var f=document.getElementById(b);if(!f){var d=/\((\d)+\)/;if(b.match(d)){var a=parseInt(b.substring(1,b.length-1));if(a>this.slides.length){a=1}if(--a<0){a=0}return a}d=/\[(\d)+\]/;if(b.match(d)){var a=parseInt(b.substring(1,b.length-1));if(a>this.slides.length){a=1}if(--a<0){a=
Hey everyone! This is the third post in my new node.js modules you should know about article series. The first post was about dnode - the freestyle rpc library for node, the second was about optimist - the lightweight options parser for node. This time I'll introduce you to one of my own modules called node-lazy - lazy lists module for node. Basically you create a new lazy object, and pump data in
はじめに断っておくが、全部Pros/Consのあるデザインチョイスなので、こうじゃなきゃいけないってことではない。ただ、 OCaml はこの選択をした、そいう事だ。 前回の「経験15年の OCaml ユーザーが Haskell を仕事で半年使ってみた」 http://d.hatena.ne.jp/camlspotter/20101212/1292165692 のような易しい文章ではないのでわからない人はとことん判らないだろう。まあ勘弁して欲しい。 あと、面倒だろうが、読む人は全部常体を敬体にして最後に「と思います」をつけて読んでくれ。ください、と思います。 Shadowing は便利であると思っている OCaml の let は非再帰なので以前定義された名前に別の値の束縛をオーバーライドできる。OCaml の人はこれが便利だと思っており皆普通に使っている。詳しくは http://d.hat
なにこれ Haskellは素敵な言語だと思うが、デフォルトが遅延評価であることに起因する欠点のせいで魅力を50%くらい損なっているように見える。具体的にはサンク構築/評価のオーバーヘッドとメモリリークで、特にメモリリークの実害は大きい。ならば必要な所以外で評価を遅延させないコーディングをすれば、うっかりメモリリークを作ってしまう確率を減らせるに違いないというのがこの記事の主旨。 既に発生してしまったメモリリークに対処するのは別の問題で、有効な方法も全然違うだろう。 原則 特にそうしない必要のない限り、サンクを作ったらすぐ壊す。つまり、 let x = f y と書く代わりに、 let !x = f y と書き、 return (f x) と書く代わりに return $! f x と書く。 評価の責任 基本的に、サンクを作った者がそれを壊す責任を負うことにする。つまり、関数引数は呼び出し側
よく、Haskellには副作用がないと言われるが、それは間違いだ。確かに、Haskell には状態の変化(あるいは再代入)という副作用はない。しかし、入出力という副作用はある。この記事では、Haskell の副作用に対して、命令型プログラマーにすっきりと理解できる説明を試みたいと思う。 間違った方向への第一歩 Haskell の副作用に関する典型的な説明は、こんな感じだ。 Haskell にはあらゆるレベルで副作用がない。そのため、遅延評価が可能になる。遅延評価では、コードが記述順に実行/評価されるとは限らないので、入出力と相性が悪い。そこで、IO モナドが導入されている。IO モナドのおかげで、入出力に関するコードは記述順に実行され、外界に作用できる。 この説明を聞いて理解しろという方が無理である。説明が苦しい最大の理由は、Haskell にはあらゆるレベルで副作用がないと、間違った一歩
遅延評価では再帰の効率はどうなるかという問題です。Real World Haskell で、末尾再帰は重要だと言った後に、遅延評価では末尾再帰なんて気にするなとちゃぶ台を返しています。ようやく haskell-cafeで答えを見つけたので、Luke Palmer さんの許可を得て訳を公開します。 Luke Palmer さんの説明 私が Haskell でプログラミングするときは、通常関数を末尾再帰にはしません。(Int や Bool など)正格な値へ畳み込む場合、末尾再帰を使うのはよいことです。しかし帰納的な遅延構造を作成する場合、関係する用語は(私の記憶が正しければ)「余再帰」(corecursion)であり(訳注:mapは再帰かつ余再帰だそうですが、専門的すぎるので普通の再帰でいいと思います)、末尾再帰とはまったく異なります。 リストに対し末尾再帰で map する関数を例として考えま
僕は今、プログラマーとしての幸福感に満たされている。遅延評価を習得できたと思えるからだ。 遅延評価 なぜ関数プログラミングは重要かには、遅延評価の利点を以下のように説明している。 停止条件はループの本体とは切離すことができ、強力なモジュール化が可能となる。 例として載っている「ニュートン-ラプソン法による平方根」は、若干難しいので、簡単な別例を示そう。Haskell には、第一引数の数だけ、第二引数を繰り返す関数 replicate がある。 > replicate 3 'a' → "aaa" これを普通に実装するとこうなる。 replicate 0 c = [] replicate n c = c : replicate (n-1) c Haskell 以外で実装する場合、きっとループを使うだろう。ただ、ここでは再帰かループかは問題ではない。 問題は、「結果を作る仕事」と「終了条件を判断
IT 戦記で Haskell のリストを JavaScript で書くというのをやっている。これは面白い。ただ、そのまま書くと無限リストが無限再起に陥ってしまうので、遅延評価を行わなくてはいけない。 関数式を使った遅延評価 JavaScript で遅延評価を行うにはどうすればいいか。その答えのひとつが関数式だ。リストの各セルを、先頭の値と後続のリストという構造ではなく、先頭の値と後続のリストを返す関数という構造にしてやれば、リストの最初のセルを評価した時点で残りのセルがすべて評価されるという事態を防げる。 具体的には、リスト構築の際、後続のリストそのものの代わりにリストを返す関数を渡し、後続のリストを得るときは関数呼び出しを伴うようにすればよい。なお、ここでは空リストを表現するのに nil という特殊な値を用いる。nil は先頭の値も後続のリストも nil 自身であるリストである。 var
リリース、障害情報などのサービスのお知らせ
最新の人気エントリーの配信
処理を実行中です
j次のブックマーク
k前のブックマーク
lあとで読む
eコメント一覧を開く
oページを開く