約 4,481,790 件
https://w.atwiki.jp/tmiya/pages/57.html
9.3 例 マージソート (Merge sort) この章で前に示した挿入ソートは、書くのは簡単ですがあまり効率的ではありません。その平均的な計算量は入力リストの長さの2乗に比例します。さて、挿入ソートより効率的にリスト要素をソートするプログラムをデザインしましょう。そのためのよいアルゴリズムは マージソート です。次のように動きます。 はじめに、もしリストが0個あるいは1個の要素を持つなら、それはすでにソートされているので、そのままリストを返します。長いリストは2つのサブリストに分割され、それぞれが元のリストの半分の要素を含むようにします。各サブリストはソート関数への再帰呼び出しでソートされ、得られる2つのソート済みリストは、マージ操作にて結合されます。 マージソートを汎用的な実装とするために、ソートされるリストの要素型だけではなく、要素の比較に使う関数も指定できるようにすべきです。それら2つの要素をパラメータとして渡すことで、可能な限り汎用性のある関数が得られます。以上から次の実装を得ます。 def msort[A](less (A, A) = Boolean)(xs List[A]) List[A] = { def merge(xs1 List[A], xs2 List[A]) List[A] = if (xs1.isEmpty) xs2 else if (xs2.isEmpty) xs1 else if (less(xs1.head, xs2.head)) xs1.head merge(xs1.tail, xs2) else xs2.head merge(xs1, xs2.tail) val n = xs.length/2 if (n == 0) xs else merge(msort(less)(xs take n), msort(less)(xs drop n)) } msort の計算量は O(N log (N))、ただし N は入力リストの長さです。理由を見てみます。リストを二つに分割し、ソートされた2つのリストをマージするには、それぞれに引数のリストの長さに比例した時間を要します。msort の再帰呼び出しの度に入力の要素数は半分になり、リスト長が1に達するまでに O(log (N)) 回の再帰呼び出しが行われます。しかし長い方のリストについては、各呼び出しで更に2回の呼び出しが生じます。すべてを足し合わせると、O(log(N)) 回の呼び出しレベルのそれぞれに対して、元のリストの全要素が1回の分割操作と1回のマージ操作に関わります。すなわち各呼び出しレベルは、全部で O(N) に比例するコストがかかります。O(log(N)) の呼び出しレベルがあるため、全体で O(N log(N)) のコストとなります。このコストはリストの要素の初期分布には依存せず、最悪ケースのコストは平均ケースと同じです。このためマージソートは、リストのソートとして魅力的なアルゴリズムです。 次は msort を使う例です。 msort((x Int, y Int) = x y)(List(5, 7, 1, 3)) msort の定義はカリー化されていて、特定の比較関数を使って簡単に特化できます。たとえば val intSort = msort((x Int, y Int) = x y) val reverseSort = msort((x Int, y Int) = x y) 前ページ 9 章 目次 次ページ 名前 コメント
https://w.atwiki.jp/tmiya/pages/73.html
13.1 イテレータメソッド (Iterator Method) イテレータは、next と hasNext のほかにも豊富なメソッドをサポートしており、それを次で説明します。それらメソッドの多くは、リスト機能の対応するものに似ています。 Append メソッド append は、新しいイテレータを構築します。構築されるイテレータは、元のイテレータの最後まで到達すると、与えられたイテレータで継続します。 def append[B A](that Iterator[B]) Iterator[B] = new Iterator[B] { def hasNext = Iterator.this.hasNext || that.hasNext def next = if (Iterator.this.hasNext) Iterator.this.next else that.next } append 定義にある Iterator.this.next という項と Iterator.this.hasNext という項は、それを取り囲む Iterator クラスで定義されている、対応するメソッドを呼び出します。もし、this に対するプレフィックス Iterator がなければ、hasNext と next は、append の結果(オブジェクト)に定義されているメソッド自身を再帰的に呼び出してしまいます。これは我々の望むことではありません。 Map、FlatMap、Foreach メソッド map は、元のイテレータのすべての要素を、与えられた関数 f で変換して返すイテレータを構築します。 def map[B](f A = B) Iterator[B] = new Iterator[B] { def hasNext = Iterator.this.hasNext def next = f(Iterator.this.next) } メソッド flatMap はメソッド map と似ていますが、変換する関数 f がイテレータを返す点が違います。flatmap の結果は、f を順に呼んでいって返されてくるイテレータ達を結合したものです。 def flatMap[B](f A = Iterator[B]) Iterator[B] = new Iterator[B] { private var cur Iterator[B] = Iterator.empty def hasNext Boolean = if (cur.hasNext) true else if (Iterator.this.hasNext) { cur = f(Iterator.this.next); hasNext } else false def next B = if (cur.hasNext) cur.next else if (Iterator.this.hasNext) { cur = f(Iterator.this.next); next } else error("next on empty iterator") } map に深く関係するのが foreach メソッドです。与えられた関数をイテレータのすべての要素に適用しますが、結果のリストを構築しません。 def foreach(f A = Unit) Unit = while (hasNext) { f(next) } Filter メソッド filter は、元のイテレータのすべての要素のうち、基準 p を満たすものを返すイテレータを構築します。 def filter(p A = Boolean) = new BufferedIterator[a] { private val source = Iterator.this.buffered private def skip { while (source.hasNext !p(source.head)) { source.next } } def hasNext Boolean = { skip; source.hasNext } def next A = { skip; source.next } def head A = { skip; source.head } } filter はイテレータの「バッファされた」サブクラスのインスタンスを返します。BufferedIterator オブジェクトは、そのほかに head メソッドを持っています。このメソッドは、head (訳注 next の誤り?) が返すはずの要素を返しますが、next のように、要素をそれ以降に進めることはありません。そのため、head が返す要素は、次の head または next の呼び出しで再び返されます。BufferedIterator トレイトの定義は次のとおりです。 trait BufferedIterator[+A] extends Iterator[A] { def head A } map、flatmap、filter、foreach がイテレータに存在するので、for 内包表記 と for ループ がイテレータに対しても使えます。たとえば、1 から 100 までの数の平方を表示する適用は、次のように等価に表現できます。 for (i Iterator.range(1, 100)) println(i * i) Zip メソッド zip は、他のイテレータをとって、2つのイテレータから返される要素のペアからなるイテレータを返します。 def zip[B](that Iterator[B]) = new Iterator[(A, B)] { def hasNext = Iterator.this.hasNext that.hasNext def next = {Iterator.this.next, that.next} } } 前ページ 13 章 目次 次ページ 名前 コメント
https://w.atwiki.jp/tmiya/pages/33.html
4.4 例 ニュートン法による平方根計算 ここまでに紹介した構文を、もう少し興味深いプログラムを組み立てて、示しましょう。課題は x の平方根を計算する関数 def sqrt(x Double) Double = ... を書くことです。 平方根を計算する一般的な方法は、近似を繰り返すニュートン法です。まず初期推定値 y (たとえば y=1) から始めます。次いで現在の推定値 y を、y と x/y の平均値を取って繰り返し改良します。次の例では √2 を近似する、推定値 y、商 x/y、その平均が3列に示されています。 1 2/1 = 2 1.5 1.5 2/1.5 = 1.3333 1.4167 1.4167 2/1.4167 = 1.4118 1.4142 1.4142 ... ... y x / y ( y + x / y )/2 Scala では、このアルゴリズムを小さな関数群によって実装でき、各関数がアルゴリズムの各要素を表すようにできます。 はじめに、推定値から結果を得ることを繰り返す関数を定義します。 def sqrtIter(guess Double, x Double) Double = if (isGoodEnough(guess, x)) guess else sqrtIter(improve(guess, x), x) sqrtIter は自分自身を再帰的に呼び出します。命令型プログラムのループは常に、関数型プログラムでは再帰でモデル化できます。 sqrtIter の定義には、パラメータ部に続いて戻り値型があることに注意して下さい。このような戻り値型は再帰関数では必須です。非再帰関数では戻り値型はオプションであり、もしそれがなければ、型チェッカーが関数の右辺から計算します。しかし非再帰関数であっても、よりよい文書化のために戻り値型を書いておくことは、しばしばよい考えです。 二つ目のステップとして、sqrtIter から呼ばれる2つの関数を定義します。推定値を改良する関数 improve と、終了テスト isGoodEnough です。定義は次ようになります。 def improve(guess Double, x Double) = (guess + x / guess) / 2 def isGoodEnough(guess Double, x Double) = abs(square(guess) - x) 0.001 最後に、sqrt 関数自身を sqrtIter の適用として定義します。 def sqrt(x Double) = sqrtIter(1.0, x) 演習 4.4.1 isGoodEnough の判定は小さな数に対してはあまり正確ではなく、大きな数に対しては終了しないかもしれません (何故でしょう?)。これらの問題のない別の isGoodEnough を設計しなさい。 演習 4.4.2 式 sqrt(4) の実行をトレースしなさい。 前ページ 4 章 目次 次ページ 名前 コメント
https://w.atwiki.jp/tmiya/pages/67.html
11.1 状態を持つオブジェクト (Stateful Object) 我々は世界をオブジェクトの集合としてとらえ、オブジェクトの中には時間と共に変化する状態を持つものもあります。通常、状態は計算の過程で変化しうる変数の集合と結びついています。プログラミング言語の特定の構文に触れずに、状態を抽象化して言うと、「もしオブジェクトの振る舞いがその履歴に影響されるなら、オブジェクトは 状態を持つ ( ステートフル である)。」となります。 たとえば、銀行口座オブジェクトは状態を持ちます。なぜなら「100スイスフラン引き出せるか?」は口座の存続期間、異なる答を持ちうるからです。 Scala ではすべてのミュータブルな状態は、結局のところ、変数から作られます。変数定義は値定義と同じように書きますが、val の代わりに var で始まります。たとえば、次の2つの定義は2つの変数、x と count を導入し初期化します。 var x String = "abc" var count = 111 値定義と同様に変数定義は、名前と値を結びつけます。しかし変数定義の場合、この結びつきは後から代入によって変更できます。そのような代入は C や Java と同じように書きます。たとえば x = "hello" count = count + 1 Scala では定義する変数はすべて、定義の時点で初期化しければなりません。たとえば文、 var x Int; は変数定義とみなされません。なぜなら初期値が無いからです(*2)。適切な初期値を知らない、あるいは気にしない場合は、代わりにワイルドカードを使えます。たとえば、 val x T = _ は、x を何かデフォルト値 (参照型には null を、論理型には false を、数値型には適切な 0 を) で初期化します。 実世界のオブジェクトは、Scala では変数をメンバに持つオブジェクトとして表現されます。たとえば銀行口座を表現するクラスです。 class BankAccount { private var balance = 0 def deposit(amount Int) { if (amount 0) balance += amount } def withdraw(amount Int) Int = if (0 amount amount = balance) { balance -= amount balance } else error("insufficient funds") } このクラスは、口座の現在の残高を入れておく変数 balance を定義しています。メソッド deposit と withdraw は、代入によってこの変数の値を変更します。クラス BankAccount において、balance が private であることに注意して下さい。この結果、クラスの外からは直接アクセスできません。 銀行口座を作成するには、通常のオブジェクト生成の記法を使います。 val myAccount = new BankAccount 例 11.1.1 次は銀行口座を扱う scala セッションです。 scala l bankaccount.scala Loading bankaccount.scala... defined class BankAccount scala val account = new BankAccount account BankAccount = BankAccount$class@1797795 scala account deposit 50 unnamed0 Unit = () scala account withdraw 20 unnamed1 Int = 30 scala account withdraw 20 unnamed2 Int = 10 scala account withdraw 15 java.lang.Error insufficient funds at scala.Predef$error(Predef.scala 74) at BankAccount$class.withdraw( console 14) at init ( console 5) scala この例は、同じ操作 (withdraw 20) を口座に2回適用して、異なる結果が生じることを示します。したがって口座がステートフルなオブジェクトであることは明らかです。 同一性と変化 代入は2つの式が「同じ」かを判定する際に新しい問題をもたらします。もし代入が排除されている場合には、次のよう、 val x = E; val y = E ただし E は何か任意の式であるとする、と書いた場合、x と y は無理なく同じと考えられます。つまり次のように書いても等価です。 val x = E; val y = x (この性質は通常、 参照透過性 と呼ばれます) しかしもし代入を許したなら、上の2つの定義は異なります。次を考えて下さい。 val x = new BankAccount; val y = new BankAccount この問題、x と y は同一であるか、に答えるには、「同一」の意味をより明確にしなければなりません。この意味は 操作的等価性 としてとらえられ、くだけた言い方をするなら、次のようになります。 仮に x と y の2つの定義があるとします。x と y とが同じ値を定義しているか調べるには、次のようにします。 定義を実行し、引き続いて x と y とを含む任意の操作列 S を実行し、(もしあれば) 結果を調べる。 次いで、定義を実行し、S 中のすべての y の出現を x で置き換えた、S から得られた列 S を実行する。 もし S を実行した結果が異なれば、x と y は確かに異なる。 もしすべての可能な操作列の組 {S, S } に対して、同じ結果が得られるなら、x と y は同一である。 別の言い方をすれば、操作的等価性は2つの定義 x と y を、もしどんな実験でも x と y を区別できないなら、同じ値だとみなします。この文脈における実験とは、x あるいは y を用いる任意の2つのプログラムです。 この定義を用いて、 val x = new BankAccount; val y = new BankAccount が、値 x と y を等しく定義するか確かめましょう。定義を再度行い、次いでテスト列を。 val x = new BankAccount val y = new BankAccount x deposit 30 30 y withdraw 20 java.lang.RuntimeException insufficient funds さて、y のすべての出現を x に置き替えます。すると val x = new BankAccount val y = new BankAccount x deposit 30 30 x withdraw 20 10 最終結果が異なるので、x と y が異なることが証明されました。その一方で、もし val x = new BankAccount; val y = x と定義すると、どんな操作も x と y を区別できません。したがってこの場合、x と y は等しくなります。 代入と置き換えモデル これらの例が示すことは、以前の計算の置き換えモデルは、もう使えないということです。結局のところ、このモデルでは変数の名前を定義式で常に置き換え可能なのですから。たとえば val x = new BankAccount; val y = x の、y の定義中の x は new BankAccount で置き換え可能です。しかしその変更は異なるプログラムを導くことを見てきました。したがって置き換えモデルは、代入を加えると、妥当ではありません。 (*2) もしこのような文がクラス中に表れたなら、そうではなく変数宣言とみなされ、変数に対する抽象アクセスメソッドを導入しますが、これらのメソッドを状態とは結びつけません。 前ページ 11 章 目次 次ページ 名前 コメント
https://w.atwiki.jp/tmiya/pages/89.html
17.10 メールボックス メールボックスはプロセス同期と通信のための、高度で柔軟な構造物です。メッセージの送受信が可能です。ここで メッセージ とは任意のオブジェクトを指します。シグナルのタイムアウトに使う TIMEOUT という特別のメッセージがあります。 case object TIMEOUT メールボックスは次のシグネチャを実装します。 class MailBox { def send(msg Any) def receive[A](f PartialFunction[Any, A]) A def receiveWithin[A](msec Long)(f PartialFunction[Any, A]) A } メールボックスの状態はメッセージのマルチセットから成ります。メッセージは send メソッドで メールボックスへ追加されます。メッセージは receive メソッドで メールボックスから取り除かれ、メッセージプロセッサ f の引数に渡されます。 f はメッセージから何らかの結果型への部分関数です。通常、この関数はパターンマッチ式で実装されます。 receive メソッドは、そのメッセージプロセッサが定義されたメールボックスにメッセージが届くまで、ブロックされます。マッチしたメッセージはメールボックスから取り除かれ、ブロックされていたスレッドは再スタートしてメッセージプロセッサをそのメッセージに適用します。送られたメッセージとレシーバの双方とも時間順に並べられます。レシーバ r は、マッチしたメッセージ m へ適用されますが、それは、各コンポーネントを時間順に並べた個別の順序中で、m, r に先立つ {メッセージ,レシーバ}ペアが他にないときに限ります。 メールボックスの使い方の簡単な例として one-place バッファを考えてみましょう。 class OnePlaceBuffer { private val m = new MailBox // An internal mailbox private case class Empty, Full(x Int) // Types of messages we deal with m send Empty // Initialization def write(x Int) { m receive { case Empty = m send Full(x) } } def read Int = m receive { case Full(x) = m send Empty; x } } メールボックスクラスは、次のようにも実装できます。 class MailBox { private abstract class Receiver extends Signal { def isDefined(msg Any) Boolean var msg = null } テストメソッド isDefined を備えたレシーバ用の内部クラスを定義し、与えられたメッセージに対してレシーバが定義されているかどうかを示すようにします。レシーバは Signal クラスから、レシーバスレッドを起動するのに使われる nofify メソッドを継承します。レシーバスレッドが起動されると、適用すべきメッセージは Reciever の msg 変数に保存されます。 private val sent = new LinkedList[Any] private var lastSent = sent private val receivers = new LinkedList[Receiver] private var lastReceiver = receivers メールボックスクラスは2つの連結リストを保持していて、一つは、送信されたけれど取り出されていないメッセージ用で、もう一つは、ウェイトしているレシーバ用のものです。 def send(msg Any) = synchronized { var r = receivers, r1 = r.next while (r1 != null !r1.elem.isDefined(msg)) { r = r1; r1 = r1.next } if (r1 != null) { r.next = r1.next; r1.elem.msg = msg; r1.elem.notify } else { lastSent = insert(lastSent, msg) } } send メソッドは最初に、ウェイトしているレシーバがその送信されたメッセージに適用可能かどうかチェックします。もしそうなら、レシーバに通知されます。そうでなければ、メッセージは送信されたメッセージの連結リストに追加されます。 def receive[A](f PartialFunction[Any, A]) A = { val msg Any = synchronized { var s = sent, s1 = s.next while (s1 != null !f.isDefinedAt(s1.elem)) { s = s1; s1 = s1.next } if (s1 != null) { s.next = s1.next; s1.elem } else { val r = insert(lastReceiver, new Receiver { def isDefined(msg Any) = f.isDefinedAt(msg) }) lastReceiver = r r.elem.wait() r.elem.msg } } f(msg) } recieve メソッドは最初に、メッセージプロセッサ関数 f が、既に送信されたけれどもまだ取り出されていないメッセージに適用可能かどうかチェックします。もしそうなら、スレッドは続けてすぐに f をそのメッセージに適用します。そうでなければ、新しいレシーバが作られてレシーバリストへリンクされ、スレッドはそのレシーバ上の通知を待ちます。スレッドは再び起動されると、f をそのレシーバに保存されたメッセージに適用します。 連結リストの insert メソッドは次のように定義されています。 def insert(l LinkedList[A], x A) LinkedList[A] = { l.next = new LinkedList[A] l.next.elem = x l.next.next = l.next l } メールボックスクラスは、指定された最大時間だけブロックする receiveWithin メソッドも提供しています。メッセージを指定された時間(ミリ秒で与えられる)以内に受信しなければ、メッセージプロセッサ引数 f は TIMEOUT という特別のメッセージでアンブロックされます。 recieveWithin の実装は receive とほとんど同じです。 def receiveWithin[A](msec Long)(f PartialFunction[Any, A]) A = { val msg Any = synchronized { var s = sent, s1 = s.next while (s1 != null !f.isDefinedAt(s1.elem)) { s = s1; s1 = s1.next } if (s1 != null) { s.next = s1.next; s1.elem } else { val r = insert(lastReceiver, new Receiver { def isDefined(msg Any) = f.isDefinedAt(msg) }) lastReceiver = r r.elem.wait(msec) if (r.elem.msg == null) r.elem.msg = TIMEOUT r.elem.msg } } f(msg) } } // end MailBox 違いは、制限時間つきの wait コールと、その後の文だけです。 前ページ 17 章 目次 次ページ 名前 コメント
https://w.atwiki.jp/karino2/pages/36.html
WebTobinQ/Example 以下のサイトにコピペして使う。 http //webtobinq.appspot.com/ 経済統計CSVのデータを使います。 消費とgdpをplotしてみる df - read.csv("https //docs.google.com/spreadsheet/pub?key=0AnKwf3jHs-oIdGVESWc4OGs2cVJxYVFLaTFZNHhOLVE single=true gid=0 output=csv") plot(df[["Fiscal Year"]],df[["GDP(expenditure approach)"]],ylim=c(100000,600000)) lines(df[["Fiscal Year"]],df[["PrivateConsumption"]]) for文、etc. 1983年以降の失業率をplot。月次データから年次データに変換 df - read.csv("https //docs.google.com/spreadsheet/pub?key=0AnKwf3jHs-oIdHZvV0IzaFBNQkowR21wNU4wS2FKb3c single=true gid=0 output=csv") totalName - "男女計 Total" total - df[[totalName]] n - (length(total)/12) y - 1 n for(i in 1 n) { b - (12*(i-1))+1; e - (12*(i-1))+12; y[i] - mean(total[b e]) } plot(1983 (1983+n-1), y, main="失業率(季節調整済み)", type="l") (下のはたぶん古い) df - read.csv("https //docs.google.com/spreadsheet/pub?key=0AnKwf3jHs-oIdHZvV0IzaFBNQkowR21wNU4wS2FKb3c single=true gid=0 output=csv") totalName - "男女計 Total" total - df[[totalName]] n - (length(total)/12) y - 1 n for(i in 1 n) { b - (12*(n-i))+1; e - (12*(n-i))+12; y[i] - mean(total[b e]) } plot(1983 (1983+n-1), y, main="失業率(季節調整済み)", type="l") 25~34才の失業率(上とほとんど一緒) df - read.csv("https //docs.google.com/spreadsheet/pub?key=0AnKwf3jHs-oIdHZvV0IzaFBNQkowR21wNU4wS2FKb3c single=true gid=0 output=csv") totalName - "男女計 25~34" total - df[[totalName]] n - (length(total)/12) y - 1 n for(i in 1 n) { b - (12*(i-1))+1; e - (12*(i-1))+12; y[i] - mean(total[b e]) } plot(1983 (1983+n-1), y, main="失業率(季節調整済み)男女計 25~34", type="l") 失業率15才~24才、25才~34才と35才~44才を並べる。 df - read.csv("https //docs.google.com/spreadsheet/pub?key=0AnKwf3jHs-oIdHZvV0IzaFBNQkowR21wNU4wS2FKb3c single=true gid=0 output=csv") sumMonths - function(total) { n - (length(total)/12) y - 1 n for(i in 1 n) { b - (12*(i-1))+1; e - (12*(i-1))+12; y[i] - mean(total[b e]) } y } y1 - sumMonths(df[["男女計 35~44"]]) y2 - sumMonths(df[["男女計 25~34"]]) y3 - sumMonths(df[["男女計 15~24"]]) plot(1983 (1983+(length(y1)-1), y1, main="失業率(季節調整済み)", type="l") lines(1983 (1983+(length(y1)-1), y2, type="l") lines(1983 (1983+(length(y1)-1), y3, type="l") 失業率25才~34才から35才~44才を引く df - read.csv("https //docs.google.com/spreadsheet/pub?key=0AnKwf3jHs-oIdHZvV0IzaFBNQkowR21wNU4wS2FKb3c single=true gid=0 output=csv") sumMonths - function(total) { n - (length(total)/12) y - 1 n for(i in 1 n) { b - (12*(i-1))+1; e - (12*(i-1))+12; y[i] - mean(total[b e]) } y } y1 - sumMonths(df[["男女計 35~44"]]) y2 - sumMonths(df[["男女計 25~34"]]) plot(1983 (1983+(length(y1)-1), y2-y1, main="失業率(季節調整済み)25~34 - 35~44", type="l") 日本の人口全体 pop - read.csv("https //docs.google.com/spreadsheet/pub?key=0AnKwf3jHs-oIdExXNEhTX3NHWHc3a014eEdxWUs1bHc single=true gid=0 output=csv") plot(pop[["Year"]], pop[["総数"]], type="l") 日本の人口1980年以降 pop - read.csv("https //docs.google.com/spreadsheet/pub?key=0AnKwf3jHs-oIdExXNEhTX3NHWHc3a014eEdxWUs1bHc single=true gid=0 output=csv") year - pop[["Year"]] total - pop[["総数"]] plot(year[year 1979], total[year 1979], type="l") 老年人口と生産年齢人口をplot popu - read.csv("https //docs.google.com/spreadsheet/pub?key=0AnKwf3jHs-oIdExXNEhTX3NHWHc3a014eEdxWUs1bHc single=true gid=0 output=csv") plot(popu[["Year"]], popu[["15~64(生産年齢人口)"]]) lines(popu[["Year"]], popu[["65歳以上(老年人口)"]]) 人口、推計とつなげる pop - read.csv("https //docs.google.com/spreadsheet/pub?key=0AnKwf3jHs-oIdExXNEhTX3NHWHc3a014eEdxWUs1bHc single=true gid=0 output=csv") popFuture - read.csv("https //docs.google.com/spreadsheet/pub?key=0AnKwf3jHs-oIdDljQ20yQzd1SGpFTXYyR3VzRDlUTXc single=true gid=0 output=csv") year - pop[["Year"]] total - pop[["総数"]] futTotal - popFuture[["総数"]] futYear - popFuture[["Year"]] yearall - year yearall[length(year) ((length(year)+length(futYear)-1)] - futYear totalall - total totalall[length(total) ((length(total)+length(futTotal)-1)] - futTotal plot(yearall, totalall, type="l") 老齢人口と推計をつなげる(ほとんど上と意味的には同じ。でもc実装したのを思い出して変更) pop - read.csv("https //docs.google.com/spreadsheet/pub?key=0AnKwf3jHs-oIdExXNEhTX3NHWHc3a014eEdxWUs1bHc single=true gid=0 output=csv") popFuture - read.csv("https //docs.google.com/spreadsheet/pub?key=0AnKwf3jHs-oIdDljQ20yQzd1SGpFTXYyR3VzRDlUTXc single=true gid=0 output=csv") years - c(pop[["Year"]], popFuture[["Year"]]) olds - c(pop[["65歳以上(老年人口)"]], popFuture[["65歳以上(老年人口)"]]) plot(years, olds, type="l") 生産年齢人口/全人口 を推計とつなげる(上とほとんど同じ) pop - read.csv("https //docs.google.com/spreadsheet/pub?key=0AnKwf3jHs-oIdExXNEhTX3NHWHc3a014eEdxWUs1bHc single=true gid=0 output=csv") popFuture - read.csv("https //docs.google.com/spreadsheet/pub?key=0AnKwf3jHs-oIdDljQ20yQzd1SGpFTXYyR3VzRDlUTXc single=true gid=0 output=csv") years - c(pop[["Year"]], popFuture[["Year"]]) products - c(pop[["15~64(生産年齢人口)"]], popFuture[["15~64(生産年齢人口)"]]) all - c(pop[["総数"]], popFuture[["総数"]]) plot(years, products/all, type="l") GDPのうち資本減耗の占める割合 http //d.hatena.ne.jp/himaginary/20110823 ここでのグラフの再現。ただし1980年以降のみ(90年基準はどっからとってきたのだろう…) gdp - read.csv("https //docs.google.com/spreadsheet/pub?key=0AnKwf3jHs-oIdFI1WW1IVnRkbFhvdmxRc3FOMC12c1E single=true gid=0 output=csv") plot(gdp[["Year"]], gdp[["固定資本減耗"]]/gdp[["国内総生産(生産側)"]], ylim=c(0.10, 0.24)) 生産年齢一人あたりのGDP この手の物ってfor文無しで書けた気がするんだけど、思い出せず…(追記 sapplyだね。まだ実装してないや) df - read.csv("https //docs.google.com/spreadsheet/pub?key=0AnKwf3jHs-oIdGVESWc4OGs2cVJxYVFLaTFZNHhOLVE single=true gid=0 output=csv") production - read.csv("https //docs.google.com/spreadsheet/pub?key=0AnKwf3jHs-oIdExXNEhTX3NHWHc3a014eEdxWUs1bHc single=true gid=0 output=csv") subpro - production[["15~64(生産年齢人口)"]][production[["Year"]] 1980] subproYear - production[["Year"]][production[["Year"]] 1980] gdp - subproYear for(i in 1 length(subproYear)) { year - subproYear[i]; gdp[i] - df[["GDP(expenditure approach)"]][df[["Fiscal Year"]] == year] } plot(subproYear, 100*gdp/subpro) 自営業者の数 df - read.csv("https //docs.google.com/spreadsheet/pub?key=0Ancau1TRtE7ddGpzQV9hTUMya1FpMnZBMVJqWWpURUE single=true gid=1 output=csv") plot(df[["year"]], df[["Self- employed worker"]]) ほぉ、減ってるね。労働者数との比率はどうだろう? df - read.csv("https //docs.google.com/spreadsheet/pub?key=0Ancau1TRtE7ddGpzQV9hTUMya1FpMnZBMVJqWWpURUE single=true gid=1 output=csv") ratio - df[["Self- employed worker"]]/df[["Total"]] plot(df[["year"]], ratio) なぜか plot(df[["year"]], df[["Self- employed worker"]]/df[["Total"]]) はエラーになった。たぶんバグ。 前年との比の差分は? df - read.csv("https //docs.google.com/spreadsheet/pub?key=0Ancau1TRtE7ddGpzQV9hTUMya1FpMnZBMVJqWWpURUE single=true gid=1 output=csv") ratio - df[["Self- employed worker"]]/df[["Total"]] plot(1954 2010, ratio[2 length(ratio)]-ratio[1 (length(ratio)-1)]) 別に最近減るのが早くなった、という傾向は無いかな。 これはあれか。一次産業抜かないとこうなっちゃうって話だなぁ、たぶん。 従業員規模別非農林業雇用者数 eval allでは意味が分からないので一行ずつenterしてってください。 多少500人以上が増えているが、それでも28%くらいか。 最近は大手とか人減らして中小が増えてる、と思っていたけれど、そうでも無いなぁ。 df - read.csv("https //docs.google.com/spreadsheet/pub?key=0Ancau1TRtE7ddDRwNjh3Y0staHZ4X0R4MmhSYzk2ZHc single=true gid=1 output=csv") plot(df[["Year"]], df[["less than 30"]]) lines(df[["Year"]], df[["less than 100"]]) lines(df[["Year"]], df[["less than 500"]]) lines(df[["Year"]], df[["more than 500"]]) lines(df[["Year"]], df[["government employee"]]) lines(df[["Year"]], df[["Total"]]) コアコアCPI コピペ用に書いておく。 df - read.csv("https //docs.google.com/spreadsheet/pub?key=0AnKwf3jHs-oIdHhNczZ2WS0tZXNJZ3R4R0hPc3FOZ3c single=true gid=0 output=csv") plot(df[["Year"]], df[["All items, less food (less alcoholic beverages) and energy"]]) 所得300万未満の累積度数 df - read.csv("https //docs.google.com/spreadsheet/pub?key=0AnKwf3jHs-oIdDg4cm85RlMxZ1U4UjVzRHJyaXlmc1E single=true gid=1 output=csv") plot(df[["Year"]], df[["300"]],ylim=c(20, 40)) 社会保障費と名目GDPをプロット social - read.csv("https //docs.google.com/spreadsheet/pub?key=0Ancau1TRtE7ddFJWbmlud29XNW52aE05WTFxcmt0Vnc single=true gid=0 output=csv") nominal - read.csv("https //docs.google.com/spreadsheet/pub?key=0Ancau1TRtE7ddEdxdjJ6b2RidFc0TVNiZkJZeWtwY3c single=true gid=0 output=csv") social_len - length(social[["年度"]]) sub_social - social[17 social_len,] plot(nominal[["Fiscal Year"]], nominal[["GDP(expenditure approach)"]]*10, ylim=c(0, 5200000)) lines(sub_social[["年度"]], sub_social[["計"]]) 社会保障費の名目GDP比 最後のplot以外は上と同じ。 social - read.csv("https //docs.google.com/spreadsheet/pub?key=0Ancau1TRtE7ddFJWbmlud29XNW52aE05WTFxcmt0Vnc single=true gid=0 output=csv") nominal - read.csv("https //docs.google.com/spreadsheet/pub?key=0Ancau1TRtE7ddEdxdjJ6b2RidFc0TVNiZkJZeWtwY3c single=true gid=0 output=csv") social_len - length(social[["年度"]]) sub_social - social[17 social_len,] plot(nominal[["Fiscal Year"]], sub_social[["計"]]*100/(nominal[["GDP(expenditure approach)"]]*10), ylim=c(0, 100)) Rにコピペする場合 read.csvを以下のread.csv2に変える。 require(RCurl) read.csv2 - function(url){ textData - getURL(url, encoding = "UTF-8") read.csv(textConnection(textData)) } g_table - NULL Qurl - function(name) { if(is.null(g_table)) { g_table - read.csv2( https //docs.google.com/spreadsheet/pub?key=0AnKwf3jHs-oIdEE4YnJ3dERMclRqazV0ZjJuN0k0UWc single=true gid=0 output=csv ) } as.character(g_table[g_table[[ name ]]==name,][[ url ]]) }
https://w.atwiki.jp/tmiya/pages/37.html
5.1 無名関数 (Anonymous Functions) 関数をパラメータとすることで、多くの小さな関数が作られます。前の例では id, square, powerOfTwo をそれぞれ別個の関数として定義し、sum に引数として渡せました。 引数用の小さな関数のために名前付きの関数定義を使う代わりに、それらを無名関数として短く書けます。 無名関数 は関数に評価される式で、関数に名前を付けずに定義できます。例として、2乗する無名関数を考えます。 (x Int) = x * x 矢印 = の前の部分は関数のパラメータで、 = に続く部分が本体です。たとえば、2つの引数を掛け合わせる無名関数は次のようになります。 (x Int, y Int) = x * y 無名関数により名前付きの外部関数を使わずに、先ほどの最初の2つの、和を求める関数を書けます。 def sumInts(a Int, b Int) Int = sum((x Int) = x, a, b) def sumSquares(a Int, b Int) Int = sum((x Int) = x * x, a, b) しばしば、Scala コンパイラは無名関数の文脈からそのパラメータの型を推論でき、その場合はパラメータの型を省略できます。たとえば sumInts や sumSquares では、sum の型から最初のパラメータは Int = Int 型の関数に違いないと分かります。ですから、パラメータの型 Int は冗長であり省略できます。もし、型指定のない、ただ1つのパラメータしかない場合は、その周りの括弧も省略できます。 def sumInts(a Int, b Int) Int = sum(x = x, a, b) def sumSquares(a Int, b Int) Int = sum(x = x * x, a, b) 一般的に Scala の項 (x1 T1, ..., xn Tn) = E は、パラメータ x1, ..., xn を式 E (E は x1, ..., xn を参照しているでしょう) の結果に対応させる関数を定義します。無名関数は Scala に必須の構文ではありません。なぜなら常に名前付き関数で表現できるからです。実際、無名関数 (x1 T1, ..., xn Tn ) = E はブロック { def f (x1 T1, ..., xn Tn ) = E ; f _ } と等価です。ただし f はプログラムのどこか他で使われていない新規な名前です。無名関数は「糖衣構文」であるとも言います。 前ページ 5 章 目次 次ページ 本当にお疲れさまです (実に素晴らしい貢献ですね(^^)) 。「それら引数の関数の為」の「引数の関数」は「引数のための (小さな) 関数」もしくは「引数用の (小さな) 関数」の方が良いように感じました。 -- ryugate (2008-05-19 22 27 45) 「しばしば Scala コンパイラは省略可能な場合には仮引数型を無名関数の文脈から推論可能です。」は、直訳的ですが「しばしば、Scala コンパイラは無名関数の文脈からそのパラメータの型を推論でき、その場合はそれらは省略できます。」な感じはいかがでしょうか。 -- ryugate (2008-05-19 22 36 32) 名前 コメント
https://w.atwiki.jp/tmiya/pages/59.html
9.5 まとめ この章では、リストをプログラミングの基本的なデータ構造として紹介しました。リストはイミュータブル(変更不能)なので、関数型プログラミング言語では一般的なデータ型です。命令型言語における配列に匹敵する役割を持っています。しかし配列とリストではアクセス方法に大きな違いがあります。配列へのアクセスは常にインデックスによりますが、リストではインデックスは滅多に使いません。scala.List にはインデックスによるアクセスのための apply メソッドが定義されていましたが、この操作は配列の場合よりずっとコストがかかります (一定時間に対して線形)。通常、リストはインデックスの代わりに再帰的にアクセスされ、再帰のステップは、たいていの場合、リスト上のパターンマッチに基づきます。また、豊富な高階コンビネータ群により、リストに対する事前定義された計算パターンをインスタンス化できます。 前ページ 9 章 目次 次ページ 名前 コメント
https://w.atwiki.jp/tmiya/pages/91.html
17.8 同期チャネル 同期チャネルの実装例を見てみましょう。ここではメッセージの送信者はメッセージが受け取られるまでブロックします。同期チャネルは、転送するメッセージを保持するのにただ1つの変数を必要としますが、リーダーとライタープロセスをうまく連動させるために3つの信号を使います。 package scala.concurrent class SyncChannel[A] { private var data A = _ private var reading = false private var writing = false def write(x A) = synchronized { while (writing) wait() data = x writing = true if (reading) notifyAll() else while (!reading) wait() } def read A = synchronized { while (reading) wait() reading = true while (!writing) wait() val x = data writing = false reading = false notifyAll() x } } 前ページ 17 章 目次 次ページ 名前 コメント
https://w.atwiki.jp/tmiya/pages/49.html
8.3 下限境界 (Lower Bounds) 型パラメータの上限境界について見てきました。T U のような型パラメータ宣言では、型パラメータ T は型 U のサブタイプの範囲に制限されます。これと対照的なのが Scala における下限境界です。型パラメータ宣言 T S において、型パラメータ T は型 S の スーパータイプ の範囲に制限されます (上限境界と下限境界を組み合わせることもできます。T S U のように)。 下限境界を用いると、Stack の push メソッドを次のように一般化できます。 class Stack[+A] { def push[B A](x B) Stack[B] = new NonEmptyStack(x, this) 技術的には、これによって変位指定問題は解決します。なぜなら、型パラメータ A はいまや push メソッドの型パラメータではないからです。その代わり、メソッドの別の型パラメータの下限境界として現れ、その型パラメータは共変的な位置に分類されます。したがって Scala コンパイラは新しい push 定義を受け入れます。 実際、変位指定の技術的な問題を解決しただけではなく、push 定義を一般化しました。以前は、スタックの宣言された要素型に適合する型のみプッシュできました。今では、この型のサブタイプの要素もプッシュできますが、戻り値のスタックの型は適宜変化します。たとえば String のスタックに AnyRef をプッシュできますが、戻るスタックは String のスタックではなく AnyRef のスタックなのです! 要約すると、自分のデータ構造に変位指定アノテーションを付けることを躊躇すべきではありません。なぜならそれによって、リッチで自然なサブタイプ関係が得られるからです。コンパイラは健全性に関する潜在的な問題を見つけます。クラス Stack の push メソッドのようにコンパイラの推定が用心深すぎたとしても、問題となっているメソッドについて、有益な一般化をしばしば示唆します。 前ページ 8 章 目次 次ページ 名前 コメント