約 3,962,277 件
https://w.atwiki.jp/fns1556/pages/28.html
Allied Telesis 1.Static ENAT (1つのIPに対してアドレス、ポート変換) WAN側インターフェースeth0のアドレスにLAN側のネットワーク192.168.1.0/24を変換する。 enable ip nat add ip nat ip=192.168.1.0 mask=255.255.255.0 gblint=eth0 2. Dynamic ENAT (複数のIPに対してアドレス、ポート変換) 例)172.16.240.40~172.16.240.49の範囲でNAT(アドレス、ポート変換)を行う。 この時、NAT対象の送信元は192.168.1.0/24(vlan11-0)とする。 enable ip nat add ip nat ip=192.168.1.0 mask=255.255.255.0 gblip=172.16.240.40 gblmask=255.255.255.248 上記でNATされたIPアドレスはこのルーターに存在していないIPであり、対向のルーターからARP Requestによる MACアドレス情報取得の際にNAT対象のIP範囲に対してもARP ReplyでMACアドレスを返答する設定が必要となる。 従って、Proxy ARPの設定を以下のように行う。 set ip int=vlan11-0 pro=on (デフォルトではONとなるため、基本不要) add ip rou=172.16.240.40 mask=255.255.255.248 int=vlan11-0 next=0.0.0.0 pref=0 参照:IP/レンジNAT YAMAHA 1. NAPT 例1)任意の内部アドレスをlan3のインターフェースIP(172.16.0.254)にNAPT変換(IP、ポート) nat descriptor type 1 masquerade nat descriptor address outer 1 primary nat descriptor address inner 1 auto (デフォルトのため、なくてもOK) ip lan1 address 192.168.1.254/24 ip lan1 secondary address 192.168.2.254/24 ip lan3 address 172.16.0.254/16 ip lan3 nat descriptor 1 例2)lan1のセカンダリネットワーク(192.168.2.0/24)のみをlan3のインターフェース以外のあるIP(172.16.0.100)にNAT変換 nat descriptor type 1 masquerade nat descriptor address outer 1 172.16.0.100 nat descriptor address inner 1 192.168.2.0-192.168.2.255 ip lan1 address 192.168.1.254/24 ip lan1 secondary address 192.168.2.254/24 ip lan3 address 172.16.0.254/16 ip lan3 nat descriptor 1 参考:NAT descriptor command Juniper 1. Src-NAT (送信元アドレス&ポート変換) WAN側インターフェースがethernet0/0、LAN側インターフェースがbgroup0の場合。 set interface "ethernet0/0" zone "Untrust" set interface ethernet0/0 route set interface ethernet0/0 ip 172.16.1.254/24 set interface "bgroup0" zone "Trust" set interface bgroup0 nat set interface bgroup0 ip 192.168.254.254/24 2. Dst-NAT (宛先アドレス変換) サーバー公開時の設定等(1つのGlobal IPでPrivate IPにポートフォワーディングする) set interface ethernet0/0 vip interface-ip 21 "FTP" 192.168.254.1 set policy id 2 from "Untrust" to "Trust" "Any" "VIP(ethernet0/0)" "FTP" permit 3. DIPによるRange NAT 例)WAN側のインターフェースeth0/0.2(172.16.240.253/24)にLAN側のTrustゾーンが送信元となる通信(全てのIP)に対してNATを行う。 set interface ethernet0/0.2 ip 172.16.240.253/24 set interface ethernet0/0.2 route (Trustゾーンの場合のみデフォルトがnatであるため必要) set interface ethernet0/0.2 dip 4 172.16.240.32 172.16.240.39 set policy id 1 from "Trust" to "Untrust" "Any" "Any" "ANY" nat src dip-id 4 permit log exit NATレンジの確認 [[SSG]]- get dip Dip Id Dip Low Dip High Interface Attribute Usage 4 172.16.240.32 172.16.240.39 ethernet0/0.2 port-xlate n/a Port-xlated dip stickness off DIP pool utilization alarm disabled, raise threshold 0%, clear threshold 0% Windows XP 1. NAT (Windows XPをルーターとして使用) 以下手順 1.Routing and Remote Accessサービス停止(これしないとNATの設定が反映されない) C \Users\user net stop remoteaccess NAT初期設定の確認 C \Users\user netsh routing ip nat dump # ---------------------------------- # NAT 構成 # ---------------------------------- pushd routing ip nat uninstall popd 2.NATの有効化 C \Users\user netsh routing ip nat install C \Users\user netsh routing ip nat dump 以下のようにinstallが追加される。 C \Users\user netsh routing ip nat dump # ---------------------------------- # NAT 構成 # ---------------------------------- pushd routing ip nat uninstall install set global tcptimeoutmins=1440 udptimeoutmins=1 loglevel=ERROR popd 3.インターフェースの確認(ローカル エリア接続とか) C \Users\user netsh interface ip dump # ---------------------------------- # インターフェイス IP 構成 # ---------------------------------- pushd interface ip # "WiMAX" のインターフェイス IP 構成 set address name="WiMAX" source=dhcp set dns name="WiMAX" source=dhcp register=PRIMARY set wins name="WiMAX" source=dhcp # "eth0" のインターフェイス IP 構成 set address name="eth0" source=static addr=192.168.255.1 mask=255.255.255.192 set address name="eth0" gateway=192.168.255.62 gwmetric=0 set dns name="eth0" source=static addr=none register=PRIMARY set wins name="eth0" source=static addr=none popd # インターフェイス IP 構成の最後 これにより、WAN側がWiMAX、LAN側がeth0で有ることが分かる。 4.NATの設定(WAN側がWiMAX、LAN側がeth0となる) C \Users\user netsh routing ip nat add interface name="WiMAX" mode=full C \Users\user netsh routing ip nat add interface name="eth0" mode=private 設定確認 C \Users\user netsh routing ip nat dump # ---------------------------------- # NAT 構成 # ---------------------------------- pushd routing ip nat uninstall install set global tcptimeoutmins=1440 udptimeoutmins=1 loglevel=ERROR # #インターフェイス WiMAX の NAT 構成 # add interface name="WiMAX" mode=FULL # #インターフェイス eth0 の NAT 構成 # add interface name="eth0" mode=PRIVATE popd 5.Routing and RemoteAccessサービスの自動開始 C \Users\user sc config RemoteAccess start= auto 6.再起動 C \Users\user shutdown -t 0 -r
https://w.atwiki.jp/tmiya/pages/51.html
8.5 タプル (Tuples) 関数から1つ以上の結果を返す必要がたまに生じます。たとえば、与えられた2つの整数引数の整数商と余りを返す関数 divmod を考えましょう。もちろん、divmod の2つの結果を保持するクラスを次のようにも定義できます。 case class TwoInts(first Int, second Int) def divmod(x Int, y Int) TwoInts = new TwoInts(x / y, x % y) しかし、結果型のペア一つ一つに対し、新しいクラスを定義しなくてはならないのでは、あまりに面倒です。Scala ではその代わりに、次のように定義されたジェネリッククラス Tuple2 を使えます。 package scala case class Tuple2[A, B](_1 A, _2 B) Tuple2 を用いて divmod メソッドは次のように書けます。 def divmod(x Int, y Int) = new Tuple2[Int, Int](x / y, x % y) コンストラクタへの型パラメータは、値引数から推論可能な場合、通常省略できます。異なる要素数ごとにタプルクラスが存在します (現在の Scala 実装では、要素数をある適正値に制限しています) 。 タプルの要素にどうやってアクセスするのでしょうか? タプルはケースクラスなので、2つの可能性があります。次の例のように、タプルのフィールドにコンストラクタパラメータ名 _i を用いてアクセスできます。 val xy = divmod(x, y) println("quotient " + xy._1 + ", rest " + xy._2) あるいは次の例のように、タプルに対するパターンマッチを用います。 divmod(x, y) match { case Tuple2(n, d) = println("quotient " + n + ", rest " + d) } 型パラメータはパターンでは決して使われないことに注意して下さい。「case Tuple2[Int, Int](n, d)」と書くのは文法違反です。(訳注 たとえば、「case x Tuple2[Int,Int] = ・・・」と書くのは OK です) タプルは非常に便利なので、Scala では特別な構文が用意されています。n 要素 x1,...,xn のタプルは、(x1,...,xn) と書けます。これは Tuplen(x1,...,xn) と等価です。(...) 構文は、型やパターンについても同じように働きます。タプル構文を使って、divmod の例は次のように書けます。 def divmod(x Int, y Int) (Int, Int) = (x / y, x % y) divmod(x, y) match { case (n, d) = println("quotient " + n + ", rest " + d) } 前ページ 8 章 目次 次ページ 名前 コメント
https://w.atwiki.jp/tmiya/pages/88.html
17.9 ワーカー Scala における 計算サーバー の実装例を見てみましょう。サーバーは future メソッドを実装し、与えられた式をその呼び出し者と並列に評価します。 17.3節の実装とは異なり、サーバーはスレッドの事前定義された数字だけを持って future を計算します。サーバーの一つのあり得る実装では、別々のプロセッサ上で各スレッドを走らせることができ、シングルプロセッサ上で複数のスレッドを切り替える際のコンテキストスイッチングに伴うオーバーヘッドを回避できます。 import scala.concurrent._, scala.concurrent.ops._ class ComputeServer(n Int) { private abstract class Job { type T def task T def ret(x T) } private val openJobs = new Channel[Job]() private def processor(i Int) { while (true) { val job = openJobs.read job.ret(job.task) } } def future[A](p = A) () = A = { val reply = new SyncVar[A]() openJobs.write{ new Job { type T = A def task = p def ret(x A) = reply.set(x) } } () = reply.get } spawn(replicate(0, n) { processor }) } 計算すべき式(つまり、future を呼び出すときの引数)は openJobs チャネルに書かれます。 ジョブ (job) は次を備えた オブジェクトです。 job の計算結果を表す抽象型 T 計算すべき式を表す、パラメータのない、型 T の taskメソッド いちど計算された結果をとる ret メソッド 計算サーバーはその初期化中に n 個の processor プロセスを生成します。各プロセスは未処理の jobを繰り返し取り出し、job の task メソッドを評価して job の ret メソッドに結果を渡します。多相的な future メソッドは、reply という名前のガードを使って ret メソッドを実装している新しい job を生成し、その job を未処理 job の集合に入れます。そして、対応する reply ガードが呼ばれるまでウェイトします。 この例は抽象型の使い方を示しています。抽象型 T は、job の結果型を記録し、異なる job に対しては異なる型をとることもできます。抽象型がなければ、ユーザは型キャストと動的な型テストへの信頼なしに、静的に型安全な方法で同じクラスを作ることはできないでしょう。次に、式 41 + 1 を評価する計算サーバーを使うコードを示します。 object Test with Executable { val server = new ComputeServer(1) val f = server.future(41 + 1) println(f()) } 前ページ 17 章 目次 次ページ 名前 コメント
https://w.atwiki.jp/sampleisbest/pages/364.html
開発環境 Apache Flex SDK 4.12.1 FlashDevelop 4.6.1 実行環境 Microsoft Windows 8.1 (64bit) プロジェクトの種類 ActionScript 3/AS3 Project プロジェクト名 Context3DExample
https://w.atwiki.jp/tmiya/pages/58.html
9.4 リストクラスの定義Ⅱ 高階メソッド ここまでに見た例が示すことは、リストに対する関数はしばしば似た構造をしているということです。リストに対する計算パターンをいくつか見ることができます。たとえば、 ある方法で全ての要素を変換する 条件を満たす全ての要素を取り出す。 ある演算子を用いて全ての要素を結合する 関数型プログラミング言語では高階関数を使うことで、パターンを実装する汎用的な関数を書けます。よく使われる高階関数について議論しますが、それらはクラス List のメソッドとして実装されています。 リストのマッピング リストの各要素を変換して結果のリストを得ることは、よくある操作です。たとえば、リストの各要素を与えられた数だけ倍するのは、 def scaleList(xs List[Double], factor Double) List[Double] = xs match { case Nil = xs case x xs1 = x * factor scaleList(xs1, factor) } このパターンは、クラス List の map メソッドとして一般化できます。 abstract class List[A] { ... def map[B](f A = B) List[B] = this match { case Nil = this case x xs = f(x) xs.map(f) } map を用いると、scaleList は次のように簡潔になります。 def scaleList(xs List[Double], factor Double) = xs map (x = x * factor) ほかの例として、行のリストとして表現されている行列の、指定された列を返す問題、ただし各行もまたリストである、を考えましょう。これは次の関数 column で与えられます。 def column[A](xs List[List[A]], index Int) List[A] = xs map (row = row(index)) map と近い関係にあるのは foreach メソッドで、リストの全要素に関数を適用しますが、結果のリストを組み立てません。この関数はですから、副作用のためだけのものです。foreach は次のように定義されています。 def foreach(f A = Unit) { this match { case Nil = () case x xs = f(x); xs.foreach(f) } } たとえば、この関数はリストの要素すべてを表示するのに使えます。 xs foreach (x = println(x)) 演習 9.4.1 リストの要素すべてを2乗して、結果のリストを返す関数について考察しなさい。次の2つの等価な定義を完成させなさい。 def squareList(xs List[Int]) List[Int] = xs match { case List() = ?? case y ys = ?? } def squareList(xs List[Int]) List[Int] = xs map ?? リストのフィルタリング 他のよくある操作は、リストの、与えられた条件を満たすすべての要素を取り出す操作です。たとえば整数リスト中の正の要素からなるリストを返すには、 def posElems(xs List[Int]) List[Int] = xs match { case Nil = xs case x xs1 = if (x 0) x posElems(xs1) else posElems(xs1) } このパターンは、クラス List の filter メソッドへ一般化できます。 def filter(p A = Boolean) List[A] = this match { case Nil = this case x xs = if (p(x)) x xs.filter(p) else xs.filter(p) } filter を使うと、posElems は次のように簡潔に書けます。 def posElems(xs List[Int]) List[Int] = xs filter (x = x 0) フィルタに関係した操作として、リストのすべての要素が、ある条件を満たすかをテストするものがあります。対を成すものとして、リストに、ある条件を満たす要素があるか否か、という問題にも興味があるかもしれません。これらの操作はクラス List の forall と exists という高階関数として具体化されます。 def forall(p A = Boolean) Boolean = isEmpty || (p(head) (tail forall p)) def exists(p A = Boolean) Boolean = !isEmpty (p(head) || (tail exists p)) forall の使い方を示すために、ある数が素数であるか否かという問題を考えましょう。数 n が素数であるとは、1と自分自身でのみ割り切れるということを思い出して下さい。最も直接的にこの定義を翻訳すると、2以上 n 未満のすべての数で割った余りが非ゼロであることをテストすることです。数のリストは、次のようにオブジェクト List で定義されている List.range 関数で生成できます。 package scala object List { ... def range(from Int, end Int) List[Int] = if (from = end) Nil else from range(from + 1, end) たとえば List.range(2,n) は2以上 n 未満の全整数からなるリストを生成します。関数 isPrime は次のように簡単に定義できます。 def isPrime(n Int) = List.range(2, n) forall (x = n % x != 0) 素数性の数学的定義が直接 Scala コードに翻訳されています。 演習 filter を使って forall と exists を定義しなさい。 リストの畳み込み 他のよくある操作は、リストの要素をある演算子で結合することです。たとえば sum(List(x1, ..., xn )) = 0 + x1 + ... + xn product(List(x1, ..., xn )) = 1 * x1 * ... * xn もちろん、どちらの関数も再帰的スキームで実装できます。 def sum(xs List[Int]) Int = xs match { case Nil = 0 case y ys = y + sum(ys) } def product(xs List[Int]) Int = xs match { case Nil = 1 case y ys = y * product(ys) } しかし、このプログラムスキームの一般化、具体的にはクラス List の reduceLeft メソッドを利用しても実装できます。このメソッドは与えられた二項演算子を、与えられたリストの隣りあう要素の間に挿入します。たとえば List(x1, ..., xn ).reduceLeft(op) = (...(x1 op x2 ) op ... ) op xn reduceLeft を使って、sum と product の共通パターンを明らかにできます。 def sum(xs List[Int]) = (0 xs) reduceLeft {(x, y) = x + y} def product(xs List[Int]) = (1 xs) reduceLeft {(x, y) = x * y} 次が reduceLeft の実装です。 def reduceLeft(op (A, A) = A) A = this match { case Nil = error("Nil.reduceLeft") case x xs = (xs foldLeft x)(op) } def foldLeft[B](z B)(op (B, A) = B) B = this match { case Nil = z case x xs = (xs foldLeft op(z, x))(op) } reduceLeft メソッドは、一般的で役に立つ別のメソッド foldLeft を使って定義されていることがわかります。後者は、追加のパラメータとして 積算器 z をとり、foldLeft が空リストに適用された時は、その値が返ります。つまり、 (List(x1, ..., xn ) foldLeft z)(op) = (...(z op x1 ) op ... ) op xn メソッド sum と product は foldLeft を使って、次のようにも定義できます。 def sum(xs List[Int]) = (xs foldLeft 0) {(x, y) = x + y} def product(xs List[Int]) = (xs foldLeft 1) {(x, y) = x * y} 右畳み込み foldLeft と reduceLeft を適用すると、左に傾いた木(left-leaning tree)ができます。双対的な foldRight と reduceRight では、右に傾いた木ができます。 List(x1, ..., xn ).reduceRight(op) = x1 op ( ... (xn−1 op xn )...) (List(x1, ..., xn ) foldRight acc)(op) = x1 op ( ... (xn op acc)...) それらは次のように定義されます。 def reduceRight(op (A, A) = A) A = this match { case Nil = error("Nil.reduceRight") case x Nil = x case x xs = op(x, xs.reduceRight(op)) } def foldRight[B](z B)(op (A, B) = B) B = this match { case Nil = z case x xs = op(x, (xs foldRight z)(op)) } クラス List では、foldLeft と foldRight の省略形記号も定義しています。 def / [B](z B)(f (B, A) = B) B = foldLeft(z)(f) def \[B](z B)(f (A, B) = B) B = foldRight(z)(f) このメソッド名(記号)は、順スラッシュあるいは逆スラッシュによって、畳み込み操作の木を左/右に傾いた木の絵で表しています。それぞれの はリスト引数を指し示し、スラッシュは積算器 (あるいはゼロ) 引数 z を指し示します。つまり (z / List(x1, ..., xn ))(op) = (...(z op x1 ) op ... ) op xn (List(x1, ..., xn ) \ z)(op) = x1 op ( ... (xn op acc)...) 結合則および交換則をみたす演算子(op)に対しては、/ と \ は等価です (ただし、効率には違いがありますが)。 演習 9.4.2 リストを要素とするリストを引数とする関数 flatten を書く問題を考察しなさい。flatten の結果は、すべての要素リストを一つのリストへと連結したものです。次は \ を用いた、このメソッドの実装です。 def flatten[A](xs List[List[A]]) List[A] = (xs \ (Nil List[A])) {(x, xs) = x xs} flatten の本体を次のように置き換えた場合を考察しなさい。 ((Nil List[A]) / xs) ((xs, x) = xs x) flatten の2つのバージョンでの漸近的計算量の違いはどうなりますか? 実際には、flatten は他の有用な関数と共に Scala ライブラリの List オブジェクトで定義されています。ユーザープログラムからは List.flatten でアクセスできます。flatten はクラス List のメソッドでないことに注意してください --- それでは意味がありません。なぜならそれは一般のリストにではなく、リストのリストにしか適用できないからです。 リストの逆転 再考 9.2 節で、メソッド reverse の実装と、その実行時間がリストの長さの二次式になることを見ました。ここで、線形なコストをもつ reverse の新しい実装を考えましょう。アイデアは、次のようなプログラムスキームに基づく foldLeft 操作を用いることです。 class List[+A] { ... def reverse List[A] = (z? / this)(op?) あとは z? と op? 部分を埋めるだけです。例から推測してみましょう。 Nil = Nil.reverse // 仕様より = (z / Nil)(op) // reverse のテンプレートより = (Nil foldLeft z)(op) // / の定義より = z // foldLeft の定義より したがって z? は Nil でなくてはなりません。二つ目のオペランドを推測するために、長さが1のリストを考えます。 List(x) = List(x).reverse // 仕様より = (Nil / List(x))(op) // reverse のテンプレートと z = Nil より = (List(x) foldLeft Nil)(op) // / の定義より = op(Nil, x) // foldLeft の定義より したがって op(Nil, x) は List(x) に等しく、それは x Nil と等しい。これから op は で、オペランドを交換したものだと分かります。以上から、次のような、線形な計算量をもつ reverse の実装を得ます。 def reverse List[A] = ((Nil List[A]) / this) {(xs, x) = x xs} (注釈 Nil の型アノテーションは、型推論させるために必要です) 演習 9.4.3 書かれていない式を埋めて、次の基本的なリスト操作定義を畳み込み操作として完成しなさい。 def mapFun[A, B](xs List[A], f A = B) List[B] = (xs \ List[B]()){ ?? } def lengthFun[A](xs List[A]) int = (0 / xs){ ?? } ネストしたマップ 命令型言語において通常、ループのネストで書かれる多くの計算を、高階リスト操作関数を使って書くことができます。 例として次のような問題を考えましょう。与えられた正整数 n に対し、正整数 i と j のすべての組 (ただし 1 = j i n で、i+j が素数)を求めなさい。たとえば n = 7 であれば対は、 i 2 3 4 4 5 6 6 j 1 2 1 3 2 1 5 i + j 3 5 5 7 7 7 11 問題を解く自然な方法は2つのステップからなります。最初のステップでは、1 =j i n を満たす整数の対 (i,j) の列を作ります。第二のステップでは、すべての対 (i,j) の列から、i+j が素数であるものをフィルタします。 最初のステップをより詳細に見ましょう。対の列を生成する自然な方法は3つのサブステップからなります。最初に、1 以上 n未満の整数を i のために作ります。 次に、1 以上 n 未満の各 i に対して、(i,1) から (i,i-1) までの対のリストを作ります。これは range と map の組み合わせによって可能です。 List.range(1, i) map (x = (i, x)) 最後に、すべてのサブリストを foldright と を使って連結します。すべてを組み合わせると次の式が得られます。 List.range(1, n) .map(i = List.range(1, i).map(x = (i, x))) .foldRight(List[(Int, Int)]()) {(xs, ys) = xs ys} .filter(pair = isPrime(pair._1 + pair._2)) マップの平坦化 マッピングと、マップで得られたサブリストの連結という組み合わせは、非常によく使うので、クラス List には特別なメソッドがあります。 abstract class List[+A] { ... def flatMap[B](f A = List[B]) List[B] = this match { case Nil = Nil case x xs = f(x) (xs flatMap f) } } flatMap を使うと「和が素数となる対」の式は、次のようにさらに簡潔に書けます。 List.range(1, n) .flatMap(i = List.range(1, i).map(x = (i, x))) .filter(pair = isPrime(pair._1 + pair._2)) 前ページ 9 章 目次 次ページ 名前 コメント
https://w.atwiki.jp/asterisk99/pages/570.html
original (2019/05/14 付) Google 翻訳 (2019/05/19 付) # API examples #APIの例 This wiki provides simple examples on how to use the tesseract-ocr API (v3.02.02-4.0.0) in C++. このWikiは、C ++でtesseract-ocr API(v3.02.02-4.0.0)を使用する方法に関する簡単な例を提供します。 It is expected that tesseract-ocr is correctly installed including all dependecies. tesseract-ocrがすべての依存関係を含めて正しくインストールされていることが期待されます。 It is expected the user is familiar with C++, compiling and linking program on their platform, though basic compilation examples are included for beginners with Linux. 基本的なコンパイル例はLinuxの初心者向けですが(#compiling-c-api-programs-linux)、ユーザーは自分のプラットフォームでC ++、プログラムのコンパイルおよびリンクに精通していることが期待されます。 More details about tesseract-ocr API can be found at baseapi.h. tesseract-ocr APIについての詳細はbaseapi.hにあります。 # Basic example #基本的な例 Code コード `c++ | `c ++ #include tesseract/baseapi.h #include tesseract / baseapi.h #include leptonica/allheaders.h #include leptonica / allheaders.h int main() int main() { { char *outText; char * outText; tesseract TessBaseAPI *api = new tesseract TessBaseAPI(); tesseract TessBaseAPI * api = new tesseract TessBaseAPI(); // Initialize tesseract-ocr with English, without specifying tessdata path // tessdataパスを指定せずに、tesseract-ocrを英語で初期化します if (api- Init(NULL, "eng")) { if(api- Init(NULL、 "eng")){ fprintf(stderr, "Could not initialize tesseract.\n"); fprintf(stderr、 "tesseractを初期化できませんでした。\ n"); exit(1); 出口(1); } } // Open input image with leptonica library // leptonicaライブラリで入力画像を開く Pix *image = pixRead("/usr/src/tesseract/testing/phototest.tif"); Pix * image = pixRead( "/ usr / src / tesseract / testing / phototest.tif"); api- SetImage(image); api- SetImage(image); // Get OCR result // OCR結果を取得する outText = api- GetUTF8Text(); outText = api- GetUTF8Text(); printf("OCR output \n%s", outText); printf( "OCR出力 \ n%s"、outText); // Destroy used object and release memory //使用済みオブジェクトを破棄してメモリを解放する api- End(); api- End(); delete [] outText; delete [] outText; pixDestroy( image); pixDestroy(&image); return 0; 0を返します。 } } ` | ` The program must be linked to the tesseract-ocr and leptonica libraries. プログラムはtesseract-ocrおよびleptonicaライブラリーにリンクされていなければなりません。 If you want to restrict recognition to a sub-rectangle of the image - call SetRectangle(left, top, width, height) after SetImage. Each SetRectangle clears the recogntion results so multiple rectangles can be recognized with the same image. E.g. 認識を画像のサブ矩形に制限したい場合は、SetImageの後に_SetRectangle(left、top、width、height)_を呼び出します。各SetRectangleは認識結果を消去するので、同じ画像で複数の長方形を認識することができます。例えば。 `c++ | `c ++ api- SetRectangle(30, 86, 590, 100); api- SetRectangle(30、86、590、100); ` | ` # GetComponentImages example #GetComponentImagesの例 `c++ | `c ++ Pix *image = pixRead("/usr/src/tesseract/testing/phototest.tif"); Pix * image = pixRead( "/ usr / src / tesseract / testing / phototest.tif"); tesseract TessBaseAPI *api = new tesseract TessBaseAPI(); tesseract TessBaseAPI * api = new tesseract TessBaseAPI(); api- Init(NULL, "eng"); api- Init(NULL、 "eng"); api- SetImage(image); api- SetImage(image); Boxa* boxes = api- GetComponentImages(tesseract RIL_TEXTLINE, true, NULL, NULL); Boxa * boxes = api- GetComponentImages(tesseract RIL_TEXTLINE、true、NULL、NULL); printf("Found %d textline image components.\n", boxes- n); printf( "%dテキスト行の画像コンポーネントが見つかりました。\ n"、boxes- n); for (int i = 0; i boxes- n; i++) { for(int i = 0; i n; i ++){ BOX* box = boxaGetBox(boxes, i, L_CLONE); BOX * box = boxaGetBox(boxes、i、L_CLONE); api- SetRectangle(box- x, box- y, box- w, box- h); api- SetRectangle(ボックス - x、ボックス - y、ボックス - w、ボックス - h); char* ocrResult = api- GetUTF8Text(); char * ocrResult = api- GetUTF8Text(); int conf = api- MeanTextConf(); int conf = api- MeanTextConf(); fprintf(stdout, "Box[%d] x=%d, y=%d, w=%d, h=%d, confidence %d, text %s", fprintf(stdout、 "ボックス[%d] x =%d、y =%d、w =%d、h =%d、信頼度 %d、テキスト %s"、、 i, box- x, box- y, box- w, box- h, conf, ocrResult); i、box- x、box- y、box- w、box- h、conf、ocrResult); } } ` | ` # Result iterator example #結果イテレータの例 It is possible to get confidence value and BoundingBox per word from a ResultIterator ResultIteratorから単語ごとの信頼値とBoundingBoxを取得することが可能です。 `c++ | `c ++ Pix *image = pixRead("/usr/src/tesseract/testing/phototest.tif"); Pix * image = pixRead( "/ usr / src / tesseract / testing / phototest.tif"); tesseract TessBaseAPI *api = new tesseract TessBaseAPI(); tesseract TessBaseAPI * api = new tesseract TessBaseAPI(); api- Init(NULL, "eng"); api- Init(NULL、 "eng"); api- SetImage(image); api- SetImage(image); api- Recognize(0); api- 認識(0); tesseract ResultIterator* ri = api- GetIterator(); tesseract ResultIterator * ri = api- GetIterator(); tesseract PageIteratorLevel level = tesseract RIL_WORD; tesseract PageIteratorLevel level = tesseract RIL_WORD; if (ri != 0) { if(ri!= 0){ do { 行う { const char* word = ri- GetUTF8Text(level); const char * word = ri- GetUTF8Text(level); float conf = ri- Confidence(level); float conf = ri- 信頼度(レベル)。 int x1, y1, x2, y2; int x1、y1、x2、y2。 ri- BoundingBox(level, x1, y1, x2, y2); ri- BoundingBox(レベル、&x 1、&y 1、&x 2、&y 2); printf("word %s ; \tconf %.2f; BoundingBox %d,%d,%d,%d;\n", printf( "単語 %s ; \ tconf %.2f;境界ボックス %d、%d、%d、%d; \ n"、 word, conf, x1, y1, x2, y2); ワード、conf、x1、y1、x2、y2)。 delete[] word; []単語を削除します。 } while (ri- Next(level)); while(ri- Next(level)); } } ` | ` It is also possible to use other iterator levels (block, line, word, etc.), see PageiteratorLevel. 他のイテレータレベル(ブロック、行、単語など)を使用することもできます。PageiteratorLevelを参照してください。 #L219) # Orientation and script detection (OSD) example #オリエンテーションと文字検出(OSD)の例 `c++ | `c ++ const char* inputfile = "/usr/src/tesseract/testing/eurotext.tif"; const char * inputfile = "/usr/src/tesseract/testing/eurotext.tif"; tesseract Orientation orientation; tesseract オリエンテーション tesseract WritingDirection direction; tesseract WritingDirectionの方向。 tesseract TextlineOrder order; tesseract TextlineOrderの順序 float deskew_angle; float deskew_angle; PIX *image = pixRead(inputfile); PIX * image = pixRead(入力ファイル); tesseract TessBaseAPI *api = new tesseract TessBaseAPI(); tesseract TessBaseAPI * api = new tesseract TessBaseAPI(); api- Init("/usr/src/tesseract/", "eng"); api- Init( "/ usr / src / tesseract /"、 "eng"); api- SetPageSegMode(tesseract PSM_AUTO_OSD); SetPageSegMode(tesseract PSM_AUTO_OSD); api- SetImage(image); api- SetImage(image); api- Recognize(0); api- 認識(0); tesseract PageIterator* it = api- AnalyseLayout(); tesseract PageIterator * it = api- AnalyseLayout(); it- Orientation( orientation, direction, order, deskew_angle); it- Orientation(&orientation、&direction、&order、&deskew_angle); printf("Orientation %d;\nWritingDirection %d\nTextlineOrder %d\n" \ printf( "印刷の向き %d; \ n書き込み方向 %d \ nテキスト行の順序 %d \ n" \ "Deskew angle %.4f\n", "傾き角 %.4f \ n"、 orientation, direction, order, deskew_angle); 方向、方向、順序、deskew_angle); ` | ` Explanation for result codes are in publictypes.h 結果コードの説明は[publictypes.h]にあります(https //github.com/tesseract-ocr/tesseract/blob/master/src/ccstruct/publictypes.h#L120) # Example of iterator over the classifier choices for a single symbol #単一のシンボルに対する分類子の選択に対する反復子の例 `c++ | `c ++ Pix *image = pixRead("/usr/src/tesseract/testing/phototest.tif"); Pix * image = pixRead( "/ usr / src / tesseract / testing / phototest.tif"); tesseract TessBaseAPI *api = new tesseract TessBaseAPI(); tesseract TessBaseAPI * api = new tesseract TessBaseAPI(); api- Init(NULL, "eng"); api- Init(NULL、 "eng"); api- SetImage(image); api- SetImage(image); api- SetVariable("save_blob_choices", "T"); api- SetVariable( "save_blob_choices"、 "T"); api- SetRectangle(37, 228, 548, 31); api- SetRectangle(37、228、548、31); api- Recognize(NULL); 認識(NULL); tesseract ResultIterator* ri = api- GetIterator(); tesseract ResultIterator * ri = api- GetIterator(); tesseract PageIteratorLevel level = tesseract RIL_SYMBOL; tesseract PageIteratorLevel level = tesseract RIL_SYMBOL; if(ri != 0) { if(ri!= 0){ do { 行う { const char* symbol = ri- GetUTF8Text(level); const char * symbol = ri- GetUTF8Text(level); float conf = ri- Confidence(level); float conf = ri- 信頼度(レベル)。 if(symbol != 0) { if(symbol!= 0){ printf("symbol %s, conf %f", symbol, conf); printf( "シンボル%s、conf %f"、シンボル、conf); bool indent = false; bool indent = false; tesseract ChoiceIterator ci(*ri); tesseract ChoiceIterator ci(* ri); do { 行う { if (indent) printf("\t\t "); printf( "\ t \ t");の場合(インデント) printf("\t- "); printf( "\ t-"); const char* choice = ci.GetUTF8Text(); const char * choice = ci.GetUTF8Text(); printf("%s conf %f\n", choice, ci.Confidence()); printf( "%s conf %f \ n"、選択、ci.Confidence()); indent = true; indent = true; } while(ci.Next()); while(ci.Next()); } } printf("---------------------------------------------\n"); printf( "--------------------------------------------- \ n "); delete[] symbol; []記号を削除します。 } while((ri- Next(level))); while((ri- Next(level))); } } ` | ` # Compiling C++ API programs on Linux #LinuxでC ++ APIプログラムをコンパイルする Including and linking to Tesseract s API is done in a standard Linux way. To compile a basic program against the API, you can use a command like this TesseractのAPIの組み込みとリンクは、標準のLinuxの方法で行われます。 APIに対して基本プログラムをコンパイルするには、次のようなコマンドを使用できます。 ` | ` g++ -o myprogram myprogram.cpp -llept -ltesseract g ++ -o myprogram myprogram.cpp -llept-ltesseract ` | ` If Tesseract is installed in an unusual place, you can specify the include and lib directories explicitly with g++ s -I and -L flags, like this Tesseractが異常な場所にインストールされている場合は、次のようにg ++の-Iおよび-Lフラグを使用してincludeおよびlibディレクトリを明示的に指定できます。 ` | ` g++ -o myprogram myprogram.cpp -I/home/nick/local/include/tesseract -L/home/nick/local/lib -llept -ltesseract g ++ -o myprogram myprogram.cpp -I / home / nick / local / include / tesseract -L / home / nick /ローカル/ lib -llept -ltesseract ` | ` # C-API in python #PythonのC-API Tesseract-ocr from version 3.02.02 provide C-API. This enable to use tesseract-ocr shared library in python (and other languages that can use C libraries) バージョン3.02.02からのTesseract-ocrはC-APIを提供します。これはpythonでtesseract-ocr共有ライブラリを使う(そしてC言語を使うことができる他の言語)を可能にします。ライブラリ) ```python python import os 輸入os import ctypes ctypeをインポート lang = "eng" lang = "eng" filename = "/usr/src/tesseract-ocr/phototest.tif" filename = "/usr/src/tesseract-ocr/phototest.tif" libname = "/usr/local/lib64/libtesseract.so.3" libname = "/usr/local/lib64/libtesseract.so.3" TESSDATA_PREFIX = os.environ.get( TESSDATA_PREFIX ) TESSDATA_PREFIX = os.environ.get( TESSDATA_PREFIX ) if not TESSDATA_PREFIX TESSDATA_PREFIXでない場合 TESSDATA_PREFIX = "../" TESSDATA_PREFIX = "../" tesseract = ctypes.cdll.LoadLibrary(libname) tesseract = ctypes.cdll.LoadLibrary(libname) tesseract.TessVersion.restype = ctypes.c_char_p tesseract.TessVersion.restype = ctypes.c_char_p tesseract_version = tesseract.TessVersion() tesseract_version = tesseract.TessVersion() api = tesseract.TessBaseAPICreate() api = tesseract.TessBaseAPICreate() rc = tesseract.TessBaseAPIInit3(api, TESSDATA_PREFIX, lang) rc = tesseract.TessBaseAPIInit3(api、TESSDATA_PREFIX、lang) if (rc) if(rc) tesseract.TessBaseAPIDelete(api) tesseract.TessBaseAPIDelete(api) print("Could not initialize tesseract.\n") print( "tesseractを初期化できませんでした。\ n") exit(3) 出口(3) text_out = tesseract.TessBaseAPIProcessPages(api, filename, None, 0) text_out = tesseract.TessBaseAPIProcessPages(api、filename、None、0) result_text = ctypes.string_at(text_out) result_text = ctypes.string_at(text_out) print Tesseract-ocr version , tesseract_version 「Tesseract-ocrバージョン」、tesseract_versionを印刷します。 print result_text result_textを印刷する ` | ` Example of passing python file object to C-API can be found at pastebin. PythonファイルオブジェクトをC-APIに渡す例はpastebinにあります。 Example of extracting orientation from Tesseract 4.0 Tesseract 4.0から方向を抽出する例 ```python python # /usr/bin/env python3 #/ usr / bin / env python3 # coding utf-8 #コーディング utf-8 PATH_TO_LIBTESS = /path/to/development/libtesseract.so PATH_TO_LIBTESS = /path/to/development/libtesseract.so import cffi # requires "pip install cffi" import cffi#には "pip install cffi"が必要です。 ffi = cffi.FFI() ffi = cffi.FFI() ffi.cdef(""" ffi.cdef( "" " struct Pix; Pixを構築します。 typedef struct Pix PIX; type PIX PIX PIXを構築します。 PIX pixRead ( const char filename ); PIX pixRead(const char filename); char * getLeptonicaVersion ( ); char * getLeptonicaVersion(); typedef struct TessBaseAPI TessBaseAPI; typedef struct TessBaseAPI TessBaseAPI; typedef int BOOL; typedef int BOOL; const char* TessVersion(); const char * TessVersion(); TessBaseAPI* TessBaseAPICreate(); TessBaseAPI * TessBaseAPICreate(); int TessBaseAPIInit3(TessBaseAPI handle, const char datapath, const char* language); int TessBaseAPIInit3(TessBaseAPI ハンドル、const char データパス、const char *言語); void TessBaseAPISetImage2(TessBaseAPI handle, struct Pix pix); void TessBaseAPISetImage2(TessBaseAPI ハンドル、Pix pix構造体); BOOL TessBaseAPIDetectOrientationScript(TessBaseAPI* handle, char** best_script_name, BOOL TessBaseAPIDetectOrientationScript(TessBaseAPI *ハンドル、char ** best_script_name、 int best_orientation_deg, float script_confidence, int best_orientation_deg、float script_confidence、 float* orientation_confidence); float * orientation_confidence); """) "" ") libtess = ffi.dlopen(PATH_TO_LIBTESS) libtess = ffi.dlopen(PATH_TO_LIBTESS) from ctypes.util import find_library ctypes.util import find_libraryから liblept = ffi.dlopen(find_library( lept )) liblept = ffi.dlopen(find_library( lept )) ffi.string(libtess.TessVersion()) ffi.string(libtess.TessVersion()) ffi.string(liblept.getLeptonicaVersion()) ffi.string(liblept.getLeptonicaVersion()) api = libtess.TessBaseAPICreate() api = libtess.TessBaseAPICreate() libtess.TessBaseAPIInit3(api, ffi.NULL, ffi.NULL) libtess.TessBaseAPIInit3(api、ffi.NULL、ffi.NULL) pix = liblept.pixRead( mono.png .encode()) pix = liblept.pixRead( mono.png .encode()) libtess.TessBaseAPISetImage2(api, pix) libtess.TessBaseAPISetImage2(api、pix) script_name = ffi.new( char ** ) script_name = ffi.new( char ** ) orient_deg = ffi.new( int * ) orient_deg = ffi.new( int * ) script_conf = ffi.new( float * ) script_conf = ffi.new( float * ) orient_conf = ffi.new( float * ) orient_conf = ffi.new( float * ) libtess.TessBaseAPIDetectOrientationScript(api, script_name, orient_deg, script_conf, orient_conf) libtess.TessBaseAPIDetectOrientationScript(api、script_name、orient_deg、script_conf、orient_conf) print(ffi.string(script_name).decode( utf-8 )) print(ffi.string(script_name).decode( utf-8 )) print(orient_deg[0]) print(orient_deg [0]) print(script_conf[0]) print(script_conf [0]) print(orient_conf[0]) print(orient_conf [0]) ` | ` # Example using the C-API in a C program #CプログラムでC-APIを使用する例 The C-API can of course also be used by regular C programs, as in this very basic example. この非常に基本的な例のように、C-APIは通常のCプログラムでももちろん使用できます。 `c | `c #include #include #include #include #include #include void die(const char *errstr) { void die(const char * errstr){ fputs(errstr, stderr); exit(1); } } int main(int argc, char *argv[]) { int main(int argc、char * argv []){ TessBaseAPI *handle; PIX *img; char *text; if((img = pixRead("img.png")) == NULL) handle = TessBaseAPICreate(); if(TessBaseAPIInit3(handle, NULL, "eng") != 0) TessBaseAPISetImage2(handle, img); if(TessBaseAPIRecognize(handle, NULL) != 0) if((text = TessBaseAPIGetUTF8Text(handle)) == NULL) fputs(text, stdout); TessDeleteText(text); TessBaseAPIEnd(handle); TessBaseAPIDelete(handle); pixDestroy( img); return 0; } } ` | ` On Linux you can compile it as you would build a program using the C++ API. Linuxでは[C ++ APIを使ってプログラムをビルドするのと同じようにコンパイルする]ことができます(#compiling-c-api-programs-linux)。 # Example creating searchable pdf from image in C++ #C ++で画像から検索可能なPDFを作成する例 `c++ | `c ++ #include leptonica/allheaders.h #include leptonica / allheaders.h #include tesseract/baseapi.h #include tesseract / baseapi.h #include tesseract/renderer.h #include tesseract / renderer.h int main() int main() { { const char* input_image = "/usr/src/tesseract-oc/testing/phototest.tif"; const char * input_image = "/usr/src/tesseract-oc/testing/phototest.tif"; const char* output_base = "my_first_tesseract_pdf"; const char * output_base = "my_first_tesseract_pdf"; const char* datapath = "/Projects/OCR/tesseract/tessdata"; const char * datapath = "/プロジェクト/ OCR / tesseract / tessdata"; int timeout_ms = 5000; int timeout_ms = 5000; const char* retry_config = nullptr; const char * retry_config = nullptr; bool textonly = false; bool textonly = false; int jpg_quality = 92; int jpg_quality = 92; tesseract TessBaseAPI *api = new tesseract TessBaseAPI(); tesseract TessBaseAPI * api = new tesseract TessBaseAPI(); if (api- Init(datapath, "eng")) { if(api- Init(datapath、 "eng")){ fprintf(stderr, "Could not initialize tesseract.\n"); fprintf(stderr、 "tesseractを初期化できませんでした。\ n"); exit(1); 出口(1); } } tesseract TessPDFRenderer *renderer = new tesseract TessPDFRenderer( tesseract TessPDFRenderer * renderer = new tesseract TessPDFRenderer( output_base, api- GetDatapath(), textonly, jpg_quality); output_base、api- GetDatapath()、textonly、jpg_quality); bool succeed = api- ProcessPages(input_image, retry_config, timeout_ms, renderer); bool succeed = api- ProcessPages(input_image、retry_config、timeout_ms、renderer); if (!succeed) { if(!成功){ fprintf(stderr, "Error during processing.\n"); fprintf(stderr、 "処理中にエラーが発生しました。\ n"); return EXIT_FAILURE; EXIT_FAILUREを返します。 } } api- End(); api- End(); return EXIT_SUCCESS; EXIT_SUCCESSを返します。 } } ` | ` # Example of monitoring OCR progress in C++ #C ++でOCRの進捗を監視する例 `c++ | `c ++ #include tesseract/baseapi.h #include tesseract / baseapi.h #include tesseract/ocrclass.h #include tesseract / ocrclass.h #include leptonica/allheaders.h #include leptonica / allheaders.h #include #include スレッド void monitorProgress(ETEXT_DESC *monitor, int page); void monitorProgress(ETEXT_DESC * monitor、int page); void ocrProcess(tesseract TessBaseAPI api, ETEXT_DESC monitor); void ocrProcess(tesseract TessBaseAPI api、ETEXT_DESC monitor); void monitorProgress(ETEXT_DESC *monitor, int page) { void monitorProgress(ETEXT_DESC *モニタ、intページ){ while (1) { while(1){ printf( "\r%3d%%", monitor[page].progress); printf( "\ r%3d %%"、モニター[ページ] .progress); fflush (stdout); fflush(標準出力)。 if (monitor[page].progress==100) if(monitor [page] .progress == 100) break; ブレーク; } } } } void ocrProcess(tesseract TessBaseAPI api, ETEXT_DESC monitor) { void ocrProcess(tesseract TessBaseAPI api、ETEXT_DESC monitor){ api- Recognize(monitor); 認識 - 監視(監視) } } int main() { int main(){ tesseract TessBaseAPI *api = new tesseract TessBaseAPI(); tesseract TessBaseAPI * api = new tesseract TessBaseAPI(); ETEXT_DESC *monitor = new ETEXT_DESC(); ETEXT_DESC * monitor = new ETEXT_DESC(); if (api- Init("/tesseract/tessdata_best", "eng")) { if(api- Init( "/ tesseract / tessdata_best"、 "eng")){ fprintf(stderr, "Could not initialize tesseract.\n"); fprintf(stderr、 "tesseractを初期化できませんでした。\ n"); return 1; 1を返します。 } } api- SetPageSegMode(tesseract PSM_AUTO); SetPageSegMode(tesseract PSM_AUTO); Pix *image = pixRead("/tesseract-ocr/test/testing/phototest.tif"); Pix * image = pixRead( "/ tesseract-ocr / test / testing / phototest.tif"); if (!image) { if(!image){ fprintf(stderr, "Leptonica can t process input file!\n"); fprintf(stderr、 "Leptonicaは入力ファイルを処理できません!\ n"); return 2; 2を返します。 } } api- SetImage(image); api- SetImage(image); int page = 0; int page = 0; std thread t1(ocrProcess, api, monitor); std thread t1(ocrProcess、api、monitor); std thread t2(monitorProgress, monitor, page); std thread t2(monitorProgress、monitor、page); t1.join(); t1.join(); t2.join(); t2.join(); pixDestroy( image); pixDestroy(&image); char *outText = api- GetUTF8Text(); char * outText = api- GetUTF8Text(); printf("\n%s", outText); printf( "\ n%s"、outText); if (outText) if(outText) delete [] outText; delete [] outText; api- End(); api- End(); return 0; 0を返します。 } } ` | ` More complex example (e.g. cancelling OCR process) can be found in source code of TesseractGui, gimagereader or android textfairy app. より複雑な例(OCRプロセスのキャンセルなど)は、TesseractGuiのソースコードにあります。[gimagereader](https // fossies) .org / linux / gimagereader / qt / src / Recognizer.cc)またはandroid textfairy app。
https://w.atwiki.jp/tmiya/pages/56.html
9.2 リストクラスの定義Ⅰ 一階メソッド リストは Scala では組み込み型ではありません。抽象クラス List として定義され、2つのサブクラス と Nil があります。以降では、クラス List のツアーに出かけます。 package scala abstract class List[+A] { List は抽象クラスであり、空の List コンストラクタを呼び出して (たとえば new List )、要素を定義することはできません。クラスには型パラメータ a があります。このパラメータについて共変、つまり S T であるような型 S と T について、List[S] List[T] です。クラスはパッケージ scala にあります。このパッケージは Scala の最も重要で標準的なクラスを含んでいます。List は多くのメソッドを定義しており、以下でそれを説明します。 リストの分解 最初に、3つの基本的なメソッド isEmpty, head, tail があります。パターンマッチングによるそれらの実装は簡単です。 def isEmpty Boolean = this match { case Nil = true case x xs = false } def head A = this match { case Nil = error("Nil.head") case x xs = x } def tail List[A] = this match { case Nil = error("Nil.tail") case x xs = xs } 次の関数はリストの長さを計算します。 def length Int = this match { case Nil = 0 case x xs = 1 + xs.length } 演習 9.2.1 length の末尾再帰版を設計しなさい。 次の2つの関数は head と tail を補完するものです。 def last A def init List[A] xs.last はリスト xs の最後の要素を返し、一方で xs.init は最後以外の xs の全要素を返します。両関数ともリスト全体をたどる必要があるので、類似の head や tail より効率的ではありません。次は last の実装です。 def last A = this match { case Nil = error("Nil.last") case x Nil = x case x xs = xs.last } init の実装も似ています。 次の3つの関数は、リストの先頭部、末尾部、あるいはその両方を返します。 def take(n Int) List[A] = if (n == 0 || isEmpty) Nil else head tail.take(n-1) def drop(n Int) List[A] = if (n == 0 || isEmpty) this else tail.drop(n-1) def split(n Int) (List[A], List[A]) = (take(n), drop(n)) (xs take n) は、リスト xs の最初の n 要素、あるいは長さが n 未満の場合はリスト全体を返します。(xs drop n) は、最初の n 要素を除いた xs の全要素を返します。最後に (xs split n) は、xs take n と xs drop n からなるリストのペアを返します。 次の関数はリストの、与えられたインデックス要素を返します。つまり配列の添字と似ています。インデックスは 0 から始まります。 def apply(n Int) A = drop(n).head apply メソッドは Scala では特別な意味を持ちます。apply メソッドを持つオブジェクトはあたかも関数のように引数へ適用されます。たとえば、リスト xs の第 3 要素を選び出すには xs.apply(3) とも xs(3) とも書けます --- 後の式は前の式に展開されます。 take と drop を使って、元のリストの連続した要素からなるサブリストを取り出せます。リスト xs のサブリスト xsm,...,xsn-1 を取り出すには、 xs.drop(m).take(n - m) リストの ZIP 次の関数は2つのリストを組み合わせて、ペアからなる一つのリストを作ります。2つのリスト xs = List(x1, ..., xn ) , and ys = List(y1, ..., yn ) , に対して、xs zip ys はリスト List(*1) を作ります。もし2つのリストの長さが違う場合は、長い方が切り捨てられます。次は zip の定義です。多相的メソッドであることに注意してください。 def zip[B](that List[B]) List[(A,B)] = if (this.isEmpty || that.isEmpty) Nil else (this.head, that.head) (this.tail zip that.tail) リストの CONS すべての中置演算子と同じように、 もオブジェクトのメソッドとして実装されています。この場合、そのオブジェクトは拡張されるリストです。Scala では、文字 で終わる演算子は特別に扱われるため、それが可能です。そのような演算子は、右オペランドのメソッドとして扱われます。たとえば x y = y. (x) 一方 x + y = x.+(y) しかし、どちらの場合も二項演算のオペランドは左から右に評価されることに注意して下さい。もし D と E が副作用の可能性のある式なら、D E は オペランド評価において、左から右への順序を維持するために、{val x = D; E. (x)} と変換されます。 で終わる演算子と他の演算子とのもう一つの違いは、結合性に関するものです。 で終わる演算子は右結合で、他の演算子は左結合です。たとえば、 x y z = x (y z) 一方 x + y + z = (x + y) + z クラス List のメソッドとしての の定義は、次のようです。 def [B A](x B) List[B] = new scala. (x, this) は、x の型 B がリストの要素型 A のスーパータイプであるような、型 B のすべての要素 x と、List[A] 型のリストに対して定義されていることに注意して下さい。この場合、結果は要素型 B のリストになります。このことは のシグネチャにおいて、下限境界 A を持つ型パラメータ B、として表現されています。 リストの連結 と似た操作はリストの連結で、 と書きます。(xs ys) の結果は xs の全要素に ys の全要素が続いたリストです。コロンで終わるため、 は右結合であり右オペランドのメソッドとみなされます。したがって、 xs ys zs = xs (ys zs) = zs. (ys). (xs) 以下は メソッドの実装です。 def [B A](prefix List[B]) List[B] = prefix match { case Nil = this case p ps = this. (ps). (p) } リストの逆転 ほかにも有用な操作として、リストの逆転があります。List にはそのためのメソッド reverse があります。実装を与えてみましょう。 def reverse[A](xs List[A]) List[A] = xs match { case Nil = Nil case x xs = reverse(xs) List(x) } この実装には単純であるという利点がありますが、あまり効率的とは言えません。実際のところ、リストの各要素に対して1回の連結が実行されます。List の連結は、最初のオペランドの長さに比例する時間がかかります。したがって reverse(xs) の計算量は n + (n − 1) + ... + 1 = n(n + 1)/2 ただし n は xs の長さです。reverse をもっと効率的に実装できますか?線形な計算量しか持たない異なる実装をあとで見ます。 前ページ 9 章 目次 次ページ s/split/splitAt/g -- murase_syuka (2008-10-08 01 15 57) 名前 コメント
https://w.atwiki.jp/tmiya/pages/38.html
5.2 カリー化 (Curring) 和を求める関数の最後の設計はすでにかなり簡潔です。しかし更に可能です。a と b がすべての関数でパラメータまたは引数として現れる一方で、興味深い組み合わせを成していないようです。それらを除去できるでしょうか。 sum を書き直し、境界 a と b をパラメータにしないようにしましょう。 def sum(f Int = Int) (Int, Int) = Int = { def sumF(a Int, b Int) Int = if (a b) 0 else f(a) + sumF(a + 1, b) sumF } この設計では、sum は他の関数、すなわち特別な和を求める関数 sumF を返す関数です。後者の関数がすべての仕事をします。境界 a と b をパラメータとしてとり、sum 関数のパラメータ f をその間のすべての整数に適用し、結果を足し合わせます。 新設計の sum を使って、次のように定義できます。 def sumInts = sum(x = x) def sumSquares = sum(x = x * x) def sumPowersOfTwo = sum(powerOfTwo) Or, equivalently, with value definitions あるいは同等に、値定義を使って val sumInts = sum(x = x) val sumSquares = sum(x = x * x) val sumPowersOfTwo = sum(powerOfTwo) sumInts, sumSquares, sumPowersOfTwo は、他の関数と同じように適用できます。たとえば scala sumSquares(1, 10) + sumPowersOfTwo(10, 20) unnamed0 Int = 267632001 関数を返す関数はどのように適用されるのでしょうか?例として式 sum(x = x * x)(1, 10) , の関数 sum は2乗する関数 (x = x * x) に適用されます。そして結果の関数は二番目の引数リスト (1, 10) に適用されます。 関数適用が左結合のため、この記法が可能です。すなわち、もし args1 と args2 が引数リストなら、 f(args 1)(args2) は (f(args1))(args2) と等価です。 この例では sum(x = x * x)(1, 10) は、式 (sum(x = x * x))(1, 10) と等価です。 関数を返す関数のスタイルはたいへん有用なので、Scala にはそのための特別な構文があります。たとえば次の sum 定義は前のものと等価ですが短くなっています。 def sum(f Int = Int)(a Int, b Int) Int = if (a b) 0 else f(a) + sum(f)(a + 1, b) 一般に、カリー化された関数定義 def f (args1) ... (argsn) = E ただし n 1、は次のように展開されます。 def f (args1) ... (argsn−1) = { def g (argsn) = E ; g } ただし g は未使用の識別子です。あるいはもっと短く無名関数を使って def f (args1) ... (argsn−1) = ( argsn) = E . このステップを n 回繰り返すと次を得ます。 def f (args1) ... (argsn) = E これは次と等価です。 def f = (args1) = ... = (argsn) = E . あるいは同様に値定義を用いて val f = (args) = ... = (args) = E . この関数定義と適用のスタイルは、創始者である20世紀の論理学者 Haskell B. Curry に因んで カリー化 と呼ばれています。しかしそのアイデアは Moses Schoenfinkel や Gottlob Frege にまで遡ります。 関数を返す関数の型は、パラメータリストに似た形で表されます。例として sum の最後の設計を見ると、sum の型は (Int = Int) = (Int, Int) = Int です。関数型は右結合なため、これが可能です。すなわち T1 = T2 = T3 は T1 = (T2 = T3) と等価 演習 5.2.1 関数 sum は線形再帰を使ってます。?? の部分を埋めて末尾再帰に書けますか? def sum(f Int = Double)(a Int, b Int) Double = { def iter(a, result) = { if (??) ?? else iter(??, ??) } iter(??, ??) } 演習 5.2.2 与えられた範囲の点の、関数値の積を求める関数 product を書きなさい。 演習 5.2.3 factorial を product を用いて書きなさい。 演習 5.2.4 sum と product の両方を一般化する、より汎用的な関数を書けますか? 前ページ 5 章 目次 次ページ 翻訳ありがとうございます。翻訳とは直接関係ないのですが、def sumInts = sum(x = x) _ を定義すると、「_ must follow method; cannot follow (Int, Int) = Int」とエラーが出ます。なぜなのでしょうか? -- Gen (2008-08-24 15 33 28) すいません。↑の投稿をしたものですが、def sumInts(x Int, y Int) = sum(x = x)(x, y)とすることで、実行可能になりました。お騒がせしました。 -- Gen (2008-08-24 15 42 44) 名前 コメント
https://w.atwiki.jp/tmiya/pages/68.html
11.2 命令型制御構造 (Imperative Control Structures) Scala には C や Java で知られる while や do-while のループ構文があります。また else-節のない片側の if や、関数を途中で中止する return 文もあります。これらを使えば、従来の命令型スタイルのプログラミングも可能です。たとえば次の関数は、与えられたパラメータ x の n 乗を計算しますが、while と片側 if を使って実装されています。 def power(x Double, n Int) Double = { var r = 1.0 var i = n var j = 0 while (j 32) { r = r * r if (i 0) r *= x i = i 1 j += 1 } r } これらの命令的な制御構文は、ユーザの便宜を図って言語に入れてあります。それらを無くすこともできました。なぜなら同じ構文を単に関数として実装できるからです。たとえば while ループを関数的に実装してみましょう。whileLoop は2つのパラメータ、Boolean 型の条件と Unit 型のコマンド、をとる関数のはずです。条件とコマンドは名前渡しである必要があります。そうすれば各ループ毎に繰り返し評価されます。以上から、次の whileLoop 定義を得ます。 def whileLoop(condition = Boolean)(command = Unit) { if (condition) { command; whileLoop(condition)(command) } else () } whileLoop は末尾再帰的であり、一定のスタック領域で動作することに注意しましょう。 演習 11.2.1 repeatLoop 関数を書きなさい。次のように適用されるものとします。 repeatLoop { command } ( condition ) また次のようなループ構文は可能ですか? repeatLoop { command } until ( condition ) C や Java で知られるいくつかの制御構文は Scala にはありません。ループ中にジャンプする break や continue はありません。また Java の意味での for ループもありません。それらは 10.4 節で議論した、より一般的な for ループ構文で置き換えられています。 前ページ 11 章 目次 次ページ 名前 コメント
https://w.atwiki.jp/tmiya/pages/74.html
13.2 イテレータの構築 (Constructing Iterators) 具体的なイテレータは、クラス Iterator の2つの抽象メソッド next と hasNext の実装を提供する必要があります。もっとも単純なイテレータは、常に空の列を返す Iterator.empty です。 object Iterator { object empty extends Iterator[Nothing] { def hasNext = false def next = error("next on empty iterator") } もっと面白みのあるイテレータは、配列のすべての要素を列挙するものです。このイテレータはオブジェクト Iterator で定義されている fromArray メソッドで構築されます。 def fromArray[A](xs Array[A]) = new Iterator[A] { private var i = 0 def hasNext Boolean = i xs.length def next A = if (i xs.length) { val x = xs(i); i += 1; x } else error("next on empty iterator") } ほかのイテレータとして、範囲内の整数を列挙するものがあります。Iterator.range 関数は、与えられた範囲の整数値をたどるイテレータを返します。 object Iterator { def range(start Int, end Int) = new Iterator[Int] { private var current = start def hasNext = current end def next = { val r = current if (current end) current += 1 else error("end of iterator") r } } } ここまで見てきたイテレータはいずれ終わりますが、永遠に続くイテレータも定義できます。たとえば、次のイテレータは初期値からずっと続く整数を返します(*1)。 def from(start Int) = new Iterator[Int] { private var last = start 1 def hasNext = true def next = { last += 1; last } } (*1) int 型が有限の表現であるため、2^31で数は元に戻ります。 前ページ 13 章 目次 次ページ 名前 コメント