約 3,227,251 件
https://w.atwiki.jp/kiake77/pages/1.html
@wikiへようこそ ウィキはみんなで気軽にホームページ編集できるツールです。 このページは自由に編集することができます。 メールで送られてきたパスワードを用いてログインすることで、各種変更(サイト名、トップページ、メンバー管理、サイドページ、デザイン、ページ管理、等)することができます まずはこちらをご覧ください。 @wikiの基本操作 用途別のオススメ機能紹介 @wikiの設定/管理 おすすめ機能 気になるニュースをチェック 関連するブログ一覧を表示 その他にもいろいろな機能満載!! @wikiプラグイン @wiki便利ツール @wiki構文 バグ・不具合を見つけたら? お手数ですが、こちらからご連絡宜しくお願いいたします。 ⇒http //atwiki.jp/guide/contact.html 分からないことは? @wiki ご利用ガイド よくある質問 @wikiへお問い合わせ 等をご活用ください
https://w.atwiki.jp/ndsdev/
@wikiへようこそ ウィキはみんなで気軽にホームページ編集できるツールです。 このページは自由に編集することができます。 メールで送られてきたパスワードを用いてログインすることで、各種変更(サイト名、トップページ、メンバー管理、サイドページ、デザイン、ページ管理、等)することができます まずはこちらをご覧ください。 @wikiの基本操作 用途別のオススメ機能紹介 @wikiの設定/管理 おすすめ機能 気になるニュースをチェック 関連するブログ一覧を表示 その他にもいろいろな機能満載!! @wikiプラグイン @wiki便利ツール @wiki構文 @wikiプラグイン一覧 バグ・不具合を見つけたら? 要望がある場合は? お手数ですが、メールでお問い合わせください。 分からないことは? @wiki ご利用ガイド よくある質問 @wiki更新情報 @wikiへお問い合わせ 等をご活用ください その他お勧めサービスについて フォーラム型の無料掲示板は@bbをご利用ください 2ch型の無料掲示板は@chsをご利用ください お絵かき掲示板は@paintをご利用ください その他の無料掲示板は@bbsをご利用ください 無料ブログ作成は@WORDをご利用ください CGIゲームが設置できる無料ホームページ作成は@PAGESをご利用ください
https://w.atwiki.jp/tmiya/pages/141.html
Scala アクター 簡易チュートリアル (Scala Actors A Short Tutorial) By phaller Created 2007-05-24, 08 26 はじめに (Introduction) マルチコアプロセッサの到来で並行プログラミングは不可欠になりました。並行性に関する Scala の主要な構文はアクターです。アクターは基本的に、メッセージ交換で通信する並行プロセスです。アクターは、メッセージ送信に関連するメソッドを起動する、アクティブなオブジェクトの形態と見ることもできます。 Scala アクターライブラリは、同期、非同期メッセージ送信の両方を提供します(前者は、複数の非同期メッセージ交換によって実装されます)。さらに、アクターは、リクエストを非同期に処理するフューチャ(*1)を使って通信しますが、その応答を待つことを可能にする表現(フューチャ)を返します。 このチュートリアルの主な目的は、すぐにコンパイルできて Scala 2.4 以降で実行できる、いくつかの完全なサンプルプログラムをウォークスルーすることです。 (*1)訳注:フューチャについては Scala By Example 17.3参照 最初の例 (First Example) 最初の例は、一連のメッセージを交換して終了する 2 つのアクターから成ります。最初のアクターは "ping" メッセージを 2 番目のアクターに送り、するとそれは "pong" メッセージを返送します。( 各受信 "ping"メッセージ に 1 つの "pong" メッセージ)。 はじめにアクターによって送受信されるメッセージを定義します。この場合、シングルトンオブジェクトが使えます(より先進的なプログラムでは、メッセージをパラメータ化します)。パターンマッチィングを使いたいので、各メッセージは case object (ケースオブジェクト)です case object Ping case object Pong case object Stop ping アクターは、pong アクターに Ping メッセージを送ることで交換処理を開始します。Pong メッセージは pong アクターからの応答です。ping アクターは、特定の数の Ping メッセージを送り終えると、pong アクターに Stop メッセージを送ります。 Scala アクターライブラリのすべてのクラス、オブジェクトとトレイトは、scala.actors パッケージにあります。このパッケージから Actor クラスをインポートし、拡張して独自のカスタムアクターを定義するのに使います。また、それは多くの役に立つアクター操作を含むので、Actor オブジェクトのすべてのメンバーをインポートします import scala.actors.Actor import scala.actors.Actor._ アクターは、Actor クラスのサブクラスをインスタンス化して生成できる、普通のオブジェクトです。Actor をサブクラス化し、その抽象 act メソッドを実装することで、ping アクターの振る舞いを定義します class Ping(count int, pong Actor) extends Actor { def act() { var pingsLeft = count - 1 pong ! Ping while (true) { receive { case Pong = if (pingsLeft % 1000 == 0) Console.println("Ping pong") if (pingsLeft 0) { pong ! Ping pingsLeft -= 1 } else { Console.println("Ping stop") pong ! Stop exit() } } } } } 送るべき Ping メッセージの数と pong アクターは、コンストラクタの引数として渡されます。無限ループ中の receive メソッドの呼び出しは、Pong メッセージがアクターに送られるまで、アクターをサスペンドします。この場合、メッセージはアクターのメールボックスから取り除かれ、対応する、矢印の右側のアクションが実行されます。 pingsLeft がゼロより大きい場合は、! 送信演算子を使って Ping メッセージを pong アクターへ送り、pingsLeft カウンタを減じます。pingsLeft カウンタがゼロになったら、pong アクターへ Stop メッセージを送り、exit()を呼び出して現在のアクター実行を終了させます。 pong アクター用のクラスも同じように定義できます class Pong extends Actor { def act() { var pongCount = 0 while (true) { receive { case Ping = if (pongCount % 1000 == 0) Console.println("Pong ping "+pongCount) sender ! Pong pongCount = pongCount + 1 case Stop = Console.println("Pong stop") exit() } } } } ここで、注目すべき点が 1 つあります。Ping メッセージを受信して、Pong メッセージを sender アクターに送りますが、それは我々のクラスのどこにも定義されていません! 実は、それは Actor クラスのメソッドです。sender を使えば、現在のアクターが最後に受け取ったメッセージを送ったアクターを参照できます。これにより、メッセージの引数として明示的に送信者を渡さなくても済みます。 あとはアクタークラスを定義すれば、それらを使う Scala アプリケーションの生成準備完了です。 object pingpong extends Application { val pong = new Pong val ping = new Ping(100000, pong) ping.start pong.start } Java スレッドと同じように、アクターは start メソッドの呼び出しで始めます。 動かしましょう! (Let s run it!) 完全な例は、doc/scala-devel/scala/examples/actors/pingpong.scala 下の Scala ディストリビューションに含まれています。 次は、これをコンパイル、実行する方法です $ scalac pingpong.scala $ scala -cp . examples.actors.pingpong Pong ping 0 Ping pong Pong ping 1000 Ping pong Pong ping 2000 ... Ping stop Pong stop スレッド レスに! (Make it Thread-less!) アクターはスレッドプール上で実行されます。最初は、4 つのワーカースレッドがあります。もしすべてのワーカースレッドがブロックされて、まだ処理すべきタスクがあれば、スレッドプールは増大します。理想的には、スレッドプールの大きさは計算機の処理系コアの数に一致します。 アクターが、receive のような(あるいは同等の wait)スレッドをブロックする操作を呼び出すと、現在のアクター(self)を実行しているワーカースレッドはブロックされます。これは基本的に、アクターがブロックされるスレッドであることを意味します。たいていの JVM は標準的なハードウェア上では数千スレッド以上は処理できないので、使いたいアクター数への依存は避けたいことでしょう。 スレッド-ブロッキング操作は、新しいメッセージを待つ react (イベントベースの receive の仲間)を使って避けることができます。しかし、支払うべき(通常は少しの)代償があります react は決して戻ってきません。現実には、メッセージへの応答の終わりに、アクターの計算の残りを含む何らかの関数を呼び出す必要があるということです。while ループ内で react を使ってもうまく機能しないことに注意してください! しかし、ループは一般的ですから、このための特別な、loop 関数形のライブラリサポートがあります。次のように使えます。 loop { react { case A = ... case B = ... } } react の呼び出しをネストできることに注意してください。それにより、次のようにシーケンスの複数のメッセージを受信できます。 react { case A = ... case B = react { // if we get a B we also want a C case C = ... } } ping と pong アクターをスレッドレスにするには、たんに while(true)を loop で、receive を react で置き換えれば十分です。例えば、次は pong アクターの修正版 act メソッドです def act() { var pongCount = 0 loop { react { case Ping = if (pongCount % 1000 == 0) Console.println("Pong ping "+pongCount) sender ! Pong pongCount = pongCount + 1 case Stop = Console.println("Pong stop") exit() } } } 2 つめの例 (Second Example) 2 つめ例として、作り出された値のシーケンスを読み出す producers の抽象化を書くつもりです。それは標準的なイテレータインターフェースを提供します。 特定の producers は、抽象 produceValues メソッドを実装することで、定義します。個々の値は、produce メソッドを使って作り出します。クラス producer は両方のメソッドを継承します。例えば、行きがけ順(pre-order)のツリーに含まれる値を作り出す producer は次のように定義できます class PreOrder(n Tree) extends Producer[int] { def produceValues = traverse(n) def traverse(n Tree) { if (n != null) { produce(n.elem) traverse(n.left) traverse(n.right) } } Producer は、2 つのアクター producer アクターと coordinator アクターを用いて実装されています。次は producer アクターの実装方法を示します。 abstract class Producer[T] { protected def produceValues unit protected def produce(x T) { coordinator ! Some(x) receive { case Next = } } private val producer Actor = actor { receive { case Next = produceValues coordinator ! None } } ... } producer アクターの定義方法に注目してください。今回は、わざわざ Actor の特別のサブクラスを生成して、その act メソッドを実装しようとはしませんでした。その代わり、たんに actor 関数を使ってインラインでアクターの振る舞いを定義します。多分、これはずっと簡潔です! さらに、actor を使って定義したアクターは自動的に始まるので、start メソッドを起動する必要がありません! それで、producer はどのように動作するのでしょうか? Next メッセージを受け取ると、(抽象) produceVaules メソッドを実行し、それは今度は、produce メソッドを呼び出します。この結果、値のシーケンスが Some メッセージにラップされて coordinator へ送られます。シーケンスのお終いは None メッセージです。Some と None は Scala の標準 Option クラスの 2 つのケース(訳注 ケースクラス/ケースオブジェクト)です。 coordinatorはクライアントからの要求と producer から来る値を同期させます。次のように実装できます private val coordinator Actor = actor { loop { react { case Next = producer ! Next reply { receive { case x Option[_] = x } } case Stop = exit( stop) } } } Next メッセージ用のハンドラ中で、受信 Option 値をある要求側 actor へ返すために、reply を使っていることに注意してください。このことは、次のセクションで説明するつもりです。話を元に戻して... イテレータインターフェース (The Iterator Interface) 我々は producers を標準的なイテレータとして使えることを望みます。そのために、驚くなかれ、イテレータ返す iterator メソッドを実装します。その hasNext と next メソッドは、仕事を遂行するために coordinator アクターにメッセージを送ります。見てみましょう def iterator = new Iterator[T] { private var current Any = Undefined private def lookAhead = { if (current == Undefined) current = coordinator !? Next current } def hasNext boolean = lookAhead match { case Some(x) = true case None = { coordinator ! Stop; false } } def next T = lookAhead match { case Some(x) = current = Undefined; x.asInstanceOf[T] } } 非公開の lookAhead メソッドを使ってイテレータロジックを実装します。next 値がまだ未探索の場合は、current 変数は単なるプレースホルダーオブジェクトである値 Undefined を持ちます。 private val Undefined = new Object ちょっと興味を引くことが lookAhead メソッドの中にあります。current 値が Undefined のとき、これは next 値を手に入れなければならないことを意味します。そのために、同期メッセージ送信演算子 !? を使います。これは coordinatorに Next メッセージを送信しますが、しかし、通常の(非同期)メッセージ送信のように戻る代わりに、coordinator からの応答を待ちます。応答は !? の戻り値です。!? を使って送られたメッセージは、reply を使って応答されます。 sender に単純にメッセージを送っても機能しないことに注意してください! それは、!? がメールボックスの代わりに 非公開の reply チャネルからのメッセージ受信を待つからです。これは "true" 応答を、たまたまメールボックスにある古いメッセージに起因する "fake(偽物)" から区別するために必要です。 producers の例は doc/scala-devel/scala/examples/actors/producers.scala 下の Scala ディストリビューションに同じく含まれています。
https://w.atwiki.jp/tmiya/pages/127.html
Scala ひと巡り ジェネリッククラス (Generic Classes) 原ページ Java 5 (aka.JDK 1.5 [58])と同じように、Scala は、型がパラメータ化されたクラスを組み込でサポートしています。そのようなジェネリッククラスは、コレクションクラスの開発に特に役立ちます。 次はこのことを示す例です class Stack[T] { var elems List[T] = Nil def push(x T) { elems = x elems } def top T = elems.head def pop() { elems = elems.tail } } クラス Stack は、任意の要素型 T の命令型(ミュータブル 更新可能な)スタックをモデル化します。型パラメータの使用により、正しい要素(つまり型が T のもの)だけがスタック上に push されるようにできます。同様に、型パラメータを用いてメソッド top が、与えられた型の要素だけを出力することを表現できます。 次は使用方法を示すいくつかの例です object GenericsTest extends Application { val stack = new Stack[Int] stack.push(1) stack.push( a ) println(stack.top) stack.pop() println(stack.top) } 次は、このプログラムの出力です。 97 1 ジェネリック型のサブ型付けは、非変であることに注意してください。これは、もし型 Stack[Char] の文字スタックがあっても、それを型 Stack[Int] の整数スタックとしては使えないことを意味します。それでは、本当の整数を文字スタックに入れることがでてしまうので、不健全でしょう。結論を言えば、ただ S = T の場合に限り、Stack[T] は Stack[S] のサブ型になります。これは非常に制約が厳しいので、Scala は、ジェネリック型のサブ型付けの振る舞いをコントロールする、型パラメータのアノテーション機構 [17]を提供しています。 Scala ひと巡り 暗黙のパラメータ (Implicit Parameters) 原ページ 暗黙のパラメータをもつメソッドは、通常のメソッドとまったく同じように引数に適用されます。この場合、implicit ラベルは効果を持ちません。しかし、もしメソッドにその暗黙のパラメータに対する引数が書かれていないなら、そのような引数は自動的に供給されます。 暗黙のパラメータに渡すに適した実際の引数は、2 つのカテゴリに分けられます。 1 つめは、メソッド呼び出しの時点でアクセスできる、前置子のつかない、implicit 定義あるいは暗黙のパラメータを表す、すべての識別子 x が適しています。 2 つめは、implicit と印された暗黙のパラメータの型のコンパニオンモジュールのすべてのメンバーも適しています。 次の例は、monoid の add と unit 操作を使ってリストの要素の合計を計算する、メソッド sum を定義しています。暗黙の値がトップレベルではいけないことに注意してください。それらはテンプレートのメンバーでなければなりません。 abstract class SemiGroup[A] { def add(x A, y A) A } abstract class Monoid[A] extends SemiGroup[A] { def unit A } object ImplicitTest extends Application { implicit object StringMonoid extends Monoid[String] { def add(x String, y String) String = x concat y def unit String = "" } implicit object IntMonoid extends Monoid[Int] { def add(x Int, y Int) Int = x + y def unit Int = 0 } def sum[A](xs List[A])(implicit m Monoid[A]) A = if (xs.isEmpty) m.unit else m.add(xs.head, sum(xs.tail)) println(sum(List(1, 2, 3))) println(sum(List("a", "b", "c"))) } 次は Scala プログラムの出力です 6 abc Scala ひと巡り 内部クラス (Inner Classes) 原ページ Scala では、クラスは他のクラスをメンバーとして持てます。Java ライクな言語では、そのような内部クラスは取り囲むクラスのメンバーですが、Scala では反対に、そのような内部クラスは外側のオブジェクトへ束縛されます。違いを明らかにするために、グラフデータ型の実装概要を示します class Graph { class Node { var connectedNodes List[Node] = Nil def connectTo(node Node) { if (connectedNodes.find(node.equals).isEmpty) { connectedNodes = node connectedNodes } } } var nodes List[Node] = Nil def newNode Node = { val res = new Node nodes = res nodes res } } このプログラムで、グラフはノードのリストによって表されます。ノードは内部クラス Node のオブジェクトです。各ノードは 隣のリストを持っており、それはリスト connectedNodes 中に記憶されます。これでいくつかのノードをもち、ノードを付加的に(incrementally)連結できるグラフをセットアップできます。 object GraphTest extends Application { val g = new Graph val n1 = g.newNode val n2 = g.newNode val n3 = g.newNode n1.connectTo(n2) n3.connectTo(n1) } 次に、定義されるエンティティの型が何であるかを明示する型を用いて、例を補強します object GraphTest extends Application { val g Graph = new Graph val n1 g.Node = g.newNode val n2 g.Node = g.newNode val n3 g.Node = g.newNode n1.connectTo(n2) n3.connectTo(n1) } このコードは、ノードの型が、その外側のインスタンス(この例ではオブジェクト g )で前置されることを明らかにしています。今 2 つのグラフがあるとして、Scala の型システムは、一方のグラフ内で定義されたノードと他方のグラフのノードを混ぜることを許しません。なぜなら、他のグラフのノードは異なる型をもつからです。 次は不正なプログラムです object IllegalGraphTest extends Application { val g Graph = new Graph val n1 g.Node = g.newNode val n2 g.Node = g.newNode n1.connectTo(n2) // 正しい val h Graph = new Graph val n3 h.Node = h.newNode n1.connectTo(n3) // 不正! } Javaでは、上記サンプルプログラムの最後の行は正しいことに注意してください。Java は両方のグラフのノードに同じ型 Graph.Node を割り当てます。すなわち、Node はクラス Graph で前置されます(*1)。 Scalaでは、そのような型も表現でき、Graph#Node と書きます。もし異なるグラフのノードを連結できるようにしたければ、最初のグラフ実装の定義を次のように変える必要があります。 class Graph { class Node { var connectedNodes List[Graph#Node] = Nil def connectTo(node Graph#Node) { if (connectedNodes.find(node.equals).isEmpty) { connectedNodes = node connectedNodes } } } var nodes List[Node] = Nil def newNode Node = { val res = new Node nodes = res nodes res } } このプログラムが、2 つの異なるグラフへのノードの張りつけを許さないことに注意してください。もしこの制限もなくしたければ、変数 nodes の型とメソッド newNode の戻り値型を Graph#Node に変える必要があります。 (*1)訳注: Scalaではクラス Graph ではなくオブジェクト g が前置されていて、 g.Node と h.Node はパスが異なるので異なる型を表すということ。 Scala ひと巡り ミックスインクラス合成 (Mixin Class Composition) 原ページ 単一継承のみをサポートする言語と対照して、Scala には、クラス再利用のためのより汎用的な概念があります。Scala では、クラスの新しいメンバー定義(すなわち、スーパークラス継承の差分)を再利用できます。これはミックスインクラス合成として表現されます。イテレータに関する次の抽象化を考えてみます。 abstract class AbsIterator { type T def hasNext Boolean def next T } 次に、メソッド foreach を用いて AbsIterator を展開するミックスインクラスについて考えます。ここで foreach は、イテレータが返す各要素に与えられた関数を適用します。ミックスインとして使用できるクラスを定義するのに、キーワード trait を使います。 trait RichIterator extends AbsIterator { def foreach(f T = Unit) { while (hasNext) f(next) } } 次は、与えられた文字列の文字を次々に返す、具象イテレータクラスです class StringIterator(s String) extends AbsIterator { type T = Char private var i = 0 def hasNext = i s.length() def next = { val ch = s charAt i; i += 1; ch } } StringIterator と RichIterator の機能を 1 つのクラスへ統合したいとします。これは単一継承とインタフェースだけではできません。両クラスともコードを伴うメンバー実装を含むからです。Scala では、ミックスインクラス合成を使ってできます。プログラマはクラス定義の差分 --- すなわち、継承さていれないすべての新しい定義 --- を再利用できます。この機構により、次のテストプログラムのようにして、RichIterator と StringIterator を統合できます。次は、与えられた文字列のすべての文字のカラムを印字します。 object StringIteratorTest { def main(args Array[String]) { class Iter extends StringIterator(args(0)) with RichIterator val iter = new Iter iter foreach println } } 関数 main 中の Iter クラスは、親の StringIterator と RichIterator をキーワード with を使ってミックスイン合成し、構築されています。最初の親は Iter のスーパークラスと呼ばれるのに対し、2 つめ(と、もしあればその他すべて)の親は、ミックスインと呼ばれます。 Scala ひと巡り 関数のネスト (Nested Functions) 原ページ Scala では、関数定義をネストできます。次のオブジェクトは、整数のリストから閾値未満の値を抽出する、filter 関数を提供します object FilterTest extends Application { def filter(xs List[Int], threshold Int) = { def process(ys List[Int]) List[Int] = if (ys.isEmpty) ys else if (ys.head threshold) ys.head process(ys.tail) else process(ys.tail) process(xs) } println(filter(List(1, 9, 2, 8, 3, 7, 4), 5)) } ネストされた関数 process が、filter のパラメータ値である外側のスコープ中で定義された変数 threshold を参照することに注意してください。 次はこのプログラムの出力です List(1,2,3,4) Scala ひと巡り 無名関数の構文 (Anonymous Function Syntax) 原ページ Scala は無名関数の定義について、比較的簡単な構文を提供します。次の式は、整数の後続関数を生成します (x Int) = x + 1 これは次の、無名クラス定義の略記表現です new Function1[Int, Int] { def apply(x Int) Int = x + 1 } 複数のパラメータをもつ関数も定義できます。 (x Int, y Int) = "(" + x + ", " + y + ")" あるいは、パラメータなしの関数 () = { System.getProperty("user.dir") } 関数の型を書くためのたいへん簡単な方法もあります。次は、上で定義した 3 つの関数の型です Int = Int (Int, Int) = String () = String この構文は、次の型の略記表現です Function1[Int, Int] Function2[Int, Int, String] Function0[String] Scala ひと巡り カリー化 (Currying) 原ページ メソッドは複数のパラメータリストを定義できます。メソッドは、パラメータリストの数より少ない形で呼び出される時には、その引数としてパラメータリストを失った関数をもたらします。 次は 1 つの例です object CurryTest extends Application { def filter(xs List[Int], p Int = Boolean) List[Int] = if (xs.isEmpty) xs else if (p(xs.head)) xs.head filter(xs.tail, p) else filter(xs.tail, p) def modN(n Int)(x Int) = ((x % n) == 0) val nums = List(1, 2, 3, 4, 5, 6, 7, 8) println(filter(nums, modN(2))) println(filter(nums, modN(3))) } 2 つの filter 呼び出しにおいて、メソッド modN が部分適用されることに注意してください; すなわち、その最初の引数だけが実際に適用されます。項 modN(2) は、型 Int = Boolean の関数をもたらし、それはこのように、関数 filter の 2 番目の引数に対する可能な候補となります。 次は、上記プログラムの出力です List(2,4,6,8) List(3,6) Scala ひと巡り 型依存クロージャの自動構築 (Automatic Type-Dependent Closure Construction) 原ページ uction) Scala では、メソッドのパラメータにパラメータなしの関数名を与えることができます。そのようなメソッドが呼ばれる時、パラメータなしの関数名に対する実際のパラメータは評価されず、代わりにパラメータなしの関数が渡されます。これは対応するパラメータの計算をカプセル化します(いわゆる、名前呼出し評価)。 次のコードはこのメカニズムを示します object TargetTest1 extends Application { def whileLoop(cond = Boolean)(body = Unit) Unit = if (cond) { body whileLoop(cond)(body) } var i = 10 whileLoop (i 0) { println(i) i -= 1 } } 関数 whileLoop は、2 つのパラメータ cond と body をとります。関数の適用時、実際のパラメータは評価されません。しかしその代わりに、whileLoop の本体中で形式上のパラメータが使われる毎に、暗黙のうちに生成されるパラメータなしの関数が評価されます。このように、このメソッド whileLoop は、再帰的な実装方式の Java ライクな while-loop を実装します。 中置/後置演算子 [27] とこのメカニズムを結びつけて、(洗練された構文を用いた)より複雑な文を作れます。 次は loop-unless 文の実装です object TargetTest2 extends Application { def loop(body = Unit) LoopUnlessCond = new LoopUnlessCond(body) protected class LoopUnlessCond(body = Unit) { def unless(cond = Boolean) { body if (!cond) unless(cond) } } var i = 10 loop { println("i = " + i) i -= 1 } unless (i == 0) } loop 関数はただループの本体を受けつけるだけであり、そして(この本体オブジェクトをカプセル化する)クラス LoopUnlessCond のインスタンスを返します。本体がまだ評価されないことに注意してください。クラス LoopUnlessCond はメソッド unless を持っており、それを中置演算子として使用できます。このように、新たなループ loop { stats } unless ( cond ) の、極めて自然な構文を作れます 次は、TargetTest2 を実行したときの出力です i = 10 i = 9 i = 8 i = 7 i = 6 i = 5 i = 4 i = 3 i = 2 i = 1 Scala ひと巡り オペレータ (Operators) 原ページ Scala では、ただ 1 つのパラメータをとるどのようなメソッドも中置演算子として使えます。 次は、3 つのメソッド and、or と negate を定義する classMyBool の定義です。 class MyBool(x Boolean) { def and(that MyBool) MyBool = if (x) that else this def or(that MyBool) MyBool = if (x) this else that def negate MyBool = new MyBool(!x) } ここで、and と or を中置演算子として使えます。 def not(x MyBool) = x negate; // ここではセミコロンが必要 def xor(x MyBool, y MyBool) = (x or y) and not(x and y) このコードの最初の行のように、パラメータなしのメソッドを後置演算子としても使用えます。2 番目の行は、新しい not 関数と同様に、and および or メソッドを使って xor 関数を定義します。この例で、中置演算子を使って xor 定義がいっそう理解しやすくなっています。 次は、より伝統的なオブジェクト指向プログラミング言語構文における、対応するコードです def not(x MyBool) = x.negate; // semicolon required here def xor(x MyBool, y MyBool) = x.or(y).and(x.and(y).negate) Scala ひと巡り 高階関数 (Higher-Order Functions) 原ページ Scala では、高階関数を定義できます。それらは、パラメータに他の関数をとるか、あるいは、その結果が関数であるような、関数です。 次は、他の関数 f と値 v をとり、関数 f を v に適用する、関数 apply です。 def apply(f Int = String, v Int) = f(v) もしコンテキスト上で必要なら、メソッドが関数へ自動的に特化(coerced 強制)されることに注意してください。 次は 1 つの例です class Decorator(left String, right String) { def layout[A](x A) = left + x.toString() + right } object FunTest extends Application { def apply(f Int = String, v Int) = f(v) val decorator = new Decorator("[", "]") println(apply(decorator.layout, 7)) } 実行すると次の出力となります。 [7] この例で、メソッド decorator.layout は、メソッド apply が必要とするときに、型 Int = String の値へ自動的に特化されます。メソッド decorator.layout が多相的メソッドであり(すなわち、いくつかのシグニチャ型にわたっての抽象化)、Scala コンパイラは最初にそのメソッド型を適切にインスタンス化しなければならないことに注意してください。 Scala ひと巡り パッケージ (Packages) 原ページ パッケージはメンバークラス、オブジェクトとパッケージの集合を定義する特別なオブジェクトです。他のオブジェクトと異なり、パッケージは定義では導入できません。 パッケージング package p { ds } は、ds 中のすべての定義をその限定修飾名が p であるパッケージに、メンバーとして注入します。パッケージのメンバーはトップレベル定義と呼ばれます。もし ds 中の定義が private と印されていれば、そのパッケージ中の他のメンバーに対してのみ可視となります。 protected 修飾子をパッケージ識別子 p で限定できます(たとえば protected[p])。そのような修飾子を印されたメンバーは、パッケージ p 内のすべてのコードから同様にアクセス可能です。 p からの選択 p.m は、p からのインポートと同様、オブジェクトに関して機能します。しかし、他のオブジェクトと異なり、パッケージは値としては使用できません。モジュールあるいはクラス名と、同じ完全修飾名のパッケージは不正です。 パッケージング外でのトップレベル定義は、特別な空パッケージに注入されるとみなされます。このパッケージは、名前を付けることはできず、したがってインポートできません。しかし、空パッケージのメンバーは互いに限定修飾なしで可視です。 パッケージ節ではじまるコンパイル単位 package p ; stats は、ただ 1 つのパッケージング package p { stats } からなるコンパイル単位と同じです。 同じ Scala ソースファイル中で、複数のパッケージを宣言できます。 package p1 { object test extends Application { println("p1.test") } } package p2 { object test extends Application { println("p2.test") } } インポート節 インポート節は、import p.I の形をしています。ここで、インポート式 I は、限定修飾なしでアクセスできる、p のインポート可能なメンバー名の集合を決定します。たとえば 節 限定修飾なしで利用可能 import p._ p の全てのメンバー (Javaにおける import p.* と類似) import p.x p のメンバー x import p.{x = a} p のメンバー x を a にリネーム import p.{x, y} p のメンバー x と y import p1.p2.z p2 のメンバー z 。p2 自身は p1 のメンバー また、節 import p1._ , p2._ は、import p1._; import p2._ の略記表現です。 次は、すべてのコンパイル単位中に暗黙のうちに、この順番でインポートされます。 パッケージ java.lang、 パッケージ Scala と オブジェクト scala.Predef この順番において、後でインポートしたメンバーは、前にインポートしたメンバーを隠します。 Scala ひと巡り パターンマッチング (Pattern Matching) 原ページ Scala には、汎用的なパターンマッチング機構が組み込まれています。ファーストマッチ方式で、あらゆる種類のデータ上でマッチングさせることができます。 次は、整数値に対するマッチ方法を示す、小さな例です object MatchTest1 extends Application { def matchTest(x Int) String = x match { case 1 = "one" case 2 = "two" case _ = "many" } println(matchTest(3)) } ケース文のブロックは、整数を文字列にマップする関数を定義します。match キーワードは、オブジェクトに関数を適用する(上記のパターンマッチング関数のような)便利な方法を提供します。 次は、異なる型のパターンの値とマッチする、2 つめの例です object MatchTest2 extends Application { def matchTest(x Any) Any = x match { case 1 = "one" case "two" = 2 case y Int = "scala.Int" } println(matchTest("two")) } もし x が整数値 1 を参照するなら、最初のケースがマッチします。もし x が文字列 "two" と等しければ、2 つめのケースがマッチします。3 つめのケースは型付きパターンから成ります; それは任意の整数にマッチし、セレクター値 x を整数型の変数 y に束縛します。 Scala のパターンマッチング文は、ケースクラス [10]を介して表現される代数型上のマッチングにおいて、最も役に立ちます。 Scala ではまた、抽出子オブジェクト [59]中の unapply メソッドを使って、ケースクラスとは独立にパターンを定義できます。 Scala ひと巡り 多相的メソッド (Polymorphic Methods) 原ページ Scala 中のメソッドは、値と型の両方でパラメータ化できます。クラスレベルのように、値パラメータは丸括弧の対で囲み、他方、型パラメータは対の角括弧内で宣言します。 次は 1 つの例です object PolyTest extends Application { def dup[T](x T, n Int) List[T] = if (n == 0) Nil else x dup(x, n - 1) println(dup[Int](3, 4)) println(dup("three", 3)) } オブジェクト PolyTest 中のメソッド dup は、型 T と値パラメータ x T、n Int でパラメータ化されています。メソッド dup が呼び出されると、プログラマは必要とされるパラメータを提供しますが(上記プログラム中の 5 行目参照)、上記プログラムの 6 行目のように、プログラマは実際の型パラメータを明示的に与える必要はありません。Scala の型システムは、そのような型を推論できます。それは、与えられた値パラメータの型と、メソッドが呼ばれるコンテキストを調べることで、なされます。 トレイト Application は短いテストプログラムを書くために設計したのですが、JVM の出力コード最適化能力を動揺させるようなプログラムを書くことは避けるべきでしょう。この代わりに def main() を使ってください。 Scala ひと巡り 正規表現パターン (Regular Expression Patterns) 原ページ 右無視シーケンスパターン 右無視パターンは、Seq[A]のサブ型あるいは、(たとえば下記のような)反復する形式上のパラメータをもつケースクラスなどのデータ分解に役立つフィーチャーです。 Elem(prefix String, label String, attrs MetaData, scp NamespaceBinding, children Node*) これらの場合、Scala は、任意長のシーケンスを表すワイルドカード-星印 _ * を最右端にもつパターンを許しています。 次は、シーケンスの前部とマッチし、残りを変数 restへ束縛する、パターンマッチの例です。 object RegExpTest1 extends Application { def containsScala(x String) Boolean = { val z Seq[Char] = x z match { case Seq( s , c , a , l , a , rest @ _*) = println("rest is "+rest) true case Seq(_*) = false } } } 次に述べる理由により、前 Scala バージョンと違い、もう任意の正規表現は使用できません。 Scala から当面の間除かれた一般的な Regexp パターン 正当性の問題が見つかり、このフィーチャーは当面の間 Scala 言語から除かれています。もしユーザーコミュニティーからのリクエストがあれば、私たちはこれを改善した形で復活させるかもしれません。 私達の考えでは、正規表現パターンは私たちが見積もったほどには XML 処理に役立ちませんでした。現実の XML 処理アプリケーションでは、XPath ははるかに良い選択肢に思われます。変換処理あるいは正規表現パターンが、あまり使われずしかも取り除くことが難しい難解なパターンに対していくつかのバグをもつということを見つけたとき、言語を単純化する時が来たと私達は判断しました。 前 はじめ 次
https://w.atwiki.jp/directx/pages/34.html
ビルボードまでは固定機能パイプラインでした。 スキンメッシュアニメーションからはシェーダープログラムになっています。 DirectX10からはシェーダープログラミングしかできないようになっています。 というワケでシェーダープログラミングにも入門しておきましょう。 いきなりシェーダープログラミングはハードルが高いのでDirectX9から学ぶのが最適です。 では何が違うのでしょう?シェーダー未使用とシェーダー使用の2つのプログラムを用意しました。 どちらも黄色の四角形を表示するプログラムですがシェーダー使用の方は頂点シェーダーによって 赤色に変わっています。 シェーダー未使用 NoShader.cpp #include d3dx9.h #define WINDOW_WIDTH 640 //ウインドウの幅 #define WINDOW_HEIGHT 480 //ウインドウの高さ #define SAFE_RELEASE(x) if(x){x- Release();} LPDIRECT3D9 g_pD3D = NULL;//Direct3D9 LPDIRECT3DDEVICE9 g_pd3dDevice = NULL;//レンダリングデバイス //------------------------------------------------------------- // 頂点フォーマット //------------------------------------------------------------- #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE) struct CUSTOMVERTEX{ FLOAT x, y, z; // スクリーン座標での位置 DWORD color; }; LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL;//頂点バッファ HWND hwnd; HRESULT Init() { // 頂点と色情報 CUSTOMVERTEX vertices[] = { // x, y, z, {-0.5f, +0.5f, 0, 0xffffff00,}, {+0.5f, +0.5f, 0, 0xffffff00,}, {-0.5f, -0.5f, 0, 0xffffff00,}, {+0.5f, -0.5f, 0, 0xffffff00,}, }; // 頂点バッファを生成する if( FAILED( g_pd3dDevice- CreateVertexBuffer( 4*sizeof(CUSTOMVERTEX), // 頂点バッファのサイズ 0, D3DFVF_CUSTOMVERTEX, // 使用法、頂点フォーマット D3DPOOL_DEFAULT, // メモリクラス g_pVB, NULL ))) // 頂点バッファリソース 予約済 return E_FAIL; // 頂点バッファに情報を格納する VOID* pVertices; if(FAILED( g_pVB- Lock(0, sizeof(vertices), (void**) pVertices, 0))) return E_FAIL; memcpy( pVertices, vertices, sizeof(vertices) ); g_pVB- Unlock(); return true; } void FrameUpDate() { D3DXMATRIXA16 mat,matView,matProj; // ビュー行列の設定 D3DXVECTOR3 vEye = D3DXVECTOR3( 0.0f, 0.0f, 1.0f ); D3DXVECTOR3 vAt = D3DXVECTOR3( 0.0f, 0.0f, 0.0f ); D3DXVECTOR3 vUp = D3DXVECTOR3( 0.0f, 1.0f, 0.0f ); D3DXMatrixLookAtRH( matView, vEye, vAt, vUp ); g_pd3dDevice- SetTransform( D3DTS_VIEW, matView ); // 射影行列の生成 D3DXMatrixPerspectiveFovRH( matProj, D3DXToRadian(60.0f), 1.4f, 0.1f, 1000.0f ); D3DXMatrixMultiply( mat, matView, matProj ); g_pd3dDevice- SetTransform( D3DTS_PROJECTION, matProj ); } void ScreenDraw() { // 画面をクリアする g_pd3dDevice- Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0x000000ff, 1.0f, 0L ); //シーンの開始 if(SUCCEEDED(g_pd3dDevice- BeginScene())) { //ストリームソースのセット g_pd3dDevice- SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) ); //FVFのセット g_pd3dDevice- SetFVF( D3DFVF_CUSTOMVERTEX ); g_pd3dDevice- DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 ); //シーンの終了 g_pd3dDevice- EndScene(); } //バックバッファを表画面に反映させる g_pd3dDevice- Present( NULL, NULL, NULL, NULL ); } void GetFPS() { FrameUpDate(); ScreenDraw(); Sleep(16); } DWORD WINAPI MainLoop(LPVOID vdParam) { while(TRUE){ GetFPS(); } return 0; } HRESULT InitD3D( HWND hWnd ) { if(NULL==(g_pD3D=Direct3DCreate9(D3D_SDK_VERSION))){return E_FAIL;} D3DPRESENT_PARAMETERS d3dpp; ZeroMemory( d3dpp, sizeof(d3dpp) ); d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; d3dpp.BackBufferCount = 1; d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE; d3dpp.MultiSampleQuality = 0; d3dpp.EnableAutoDepthStencil = TRUE; d3dpp.AutoDepthStencilFormat = D3DFMT_D16; d3dpp.hDeviceWindow = hWnd; d3dpp.Flags = 0; d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE ; if(FAILED(g_pD3D- CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,D3DCREATE_HARDWARE_VERTEXPROCESSING, d3dpp, g_pd3dDevice))){ if(FAILED(g_pD3D- CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING, d3dpp, g_pd3dDevice))){ return(E_FAIL); } } g_pd3dDevice- SetRenderState( D3DRS_LIGHTING, false ); Init(); return S_OK; } LRESULT CALLBACK MsgProc(HWND hwnd , UINT msg , WPARAM wp , LPARAM lp) { switch (msg) { case WM_DESTROY PostQuitMessage(0); return 0; } return DefWindowProc(hwnd , msg , wp , lp); } int WINAPI WinMain(HINSTANCE hInstance , HINSTANCE hPrevInstance ,PSTR lpCmdLine , int nCmdShow ) { MSG msg; DWORD dwID; WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, L Window1 , NULL }; RegisterClassEx( wc ); RECT rect; SetRect( rect,0,0,WINDOW_WIDTH,WINDOW_HEIGHT); AdjustWindowRect( rect, WS_OVERLAPPEDWINDOW, FALSE); SetRect( rect,0,0,rect.right-rect.left,rect.bottom-rect.top); hwnd = CreateWindow( L Window1 , L NoShader , WS_OVERLAPPEDWINDOW ~WS_THICKFRAME ~WS_MAXIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT, rect.right, rect.bottom, NULL, NULL, wc.hInstance, NULL ); if (hwnd == NULL) return 0; timeBeginPeriod(1); if(SUCCEEDED(InitD3D(hwnd))){ ShowWindow(hwnd,SW_SHOWDEFAULT); UpdateWindow(hwnd); CreateThread(NULL , 0 , MainLoop , (LPVOID)hwnd , 0 , dwID); while (GetMessage( msg , NULL , 0 , 0 )) { TranslateMessage( msg); DispatchMessage( msg); } } UnregisterClass(L Window1 ,wc.hInstance); timeEndPeriod(1); SAFE_RELEASE(g_pVB); SAFE_RELEASE(g_pd3dDevice); SAFE_RELEASE(g_pD3D); return 0; } 以下はシェーダー使用 VertexShader.vsh vs_1_1 // バージョン命令 dcl_position v0 // 座標頂点宣言 m4x4 oPos, v0, c0 // 座標変換をする mov oD0, c4 // 定数色を読み込む Shader.cpp #include d3dx9.h #define WINDOW_WIDTH 640 //ウインドウの幅 #define WINDOW_HEIGHT 480 //ウインドウの高さ #define SAFE_RELEASE(x) if(x){x- Release();} LPDIRECT3D9 g_pD3D = NULL;//Direct3D9 LPDIRECT3DDEVICE9 g_pd3dDevice = NULL;//レンダリングデバイス //------------------------------------------------------------- // 頂点フォーマット //------------------------------------------------------------- #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE) struct CUSTOMVERTEX{ FLOAT x, y, z; // スクリーン座標での位置 DWORD color; }; LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL;//頂点バッファ // ★ 頂点シェーダ LPDIRECT3DVERTEXSHADER9 m_pVertexShader=NULL; // ★ 頂点シェーダ LPDIRECT3DVERTEXDECLARATION9 m_pVertexDeclaration; // ★ 頂点宣言 HWND hwnd; HRESULT Init() { HRESULT hr; LPD3DXBUFFER pCode; // --------------------------------------------------------- // ★ 頂点シェーダの作成 // --------------------------------------------------------- // 頂点宣言オブジェクトの生成 D3DVERTEXELEMENT9 decl[] = { { 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, D3DDECL_END() }; if( FAILED( hr = g_pd3dDevice- CreateVertexDeclaration( decl, m_pVertexDeclaration ) ) ) { return hr; } // シェーダを読み込む if( FAILED( hr = D3DXAssembleShaderFromFileA( VertexShader.vsh , NULL, NULL, 0, pCode, NULL ))) { return hr; } // 頂点シェーダの生成 hr = g_pd3dDevice- CreateVertexShader( (DWORD*)pCode- GetBufferPointer(), m_pVertexShader ); pCode- Release(); // 頂点と色情報 CUSTOMVERTEX vertices[] = { // x, y, z, {-0.5f, +0.5f, 0, 0xffffff00,}, {+0.5f, +0.5f, 0, 0xffffff00,}, {-0.5f, -0.5f, 0, 0xffffff00,}, {+0.5f, -0.5f, 0, 0xffffff00,}, }; // 頂点バッファを生成する if( FAILED( g_pd3dDevice- CreateVertexBuffer( 4*sizeof(CUSTOMVERTEX), // 頂点バッファのサイズ 0, D3DFVF_CUSTOMVERTEX, // 使用法、頂点フォーマット D3DPOOL_DEFAULT, // メモリクラス g_pVB, NULL ))) // 頂点バッファリソース 予約済 return E_FAIL; // 頂点バッファに情報を格納する VOID* pVertices; if(FAILED( g_pVB- Lock(0, sizeof(vertices), (void**) pVertices, 0))) return E_FAIL; memcpy( pVertices, vertices, sizeof(vertices) ); g_pVB- Unlock(); return true; } void FrameUpDate() { D3DXMATRIXA16 mat,matView,matProj; // ビュー行列の設定 D3DXVECTOR3 vEye = D3DXVECTOR3( 0.0f, 0.0f, 1.0f ); D3DXVECTOR3 vAt = D3DXVECTOR3( 0.0f, 0.0f, 0.0f ); D3DXVECTOR3 vUp = D3DXVECTOR3( 0.0f, 1.0f, 0.0f ); D3DXMatrixLookAtRH( matView, vEye, vAt, vUp ); // 射影行列の生成 D3DXMatrixPerspectiveFovRH( matProj, D3DXToRadian(60.0f), 1.4f, 0.1f, 1000.0f ); D3DXMatrixMultiply( mat, matView, matProj ); // ★ 座標変換の定数レジスタの設定 D3DXMatrixMultiply( mat, matView, matProj ); D3DXMatrixTranspose( mat, mat );// 転置行列の作成 g_pd3dDevice- SetVertexShaderConstantF(0, (float*) mat, 4); // ★ 頂点色の定数レジスタの設定 float color[] = {1.0f, 0.0f, 0.0f, 1.0f};// 赤色 g_pd3dDevice- SetVertexShaderConstantF(4, (float*) color, 1); } void ScreenDraw() { // 画面をクリアする g_pd3dDevice- Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0x000000ff, 1.0f, 0L ); //シーンの開始 if(SUCCEEDED(g_pd3dDevice- BeginScene())) { // ★頂点シェーダの設定 g_pd3dDevice- SetVertexDeclaration(m_pVertexDeclaration); g_pd3dDevice- SetVertexShader( m_pVertexShader ); //ストリームソースのセット g_pd3dDevice- SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) ); //FVFのセット g_pd3dDevice- SetFVF( D3DFVF_CUSTOMVERTEX ); g_pd3dDevice- DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 ); //シーンの終了 g_pd3dDevice- EndScene(); } //バックバッファを表画面に反映させる g_pd3dDevice- Present( NULL, NULL, NULL, NULL ); } void GetFPS() { FrameUpDate(); ScreenDraw(); Sleep(16); } DWORD WINAPI MainLoop(LPVOID vdParam) { while(TRUE){ GetFPS(); } return 0; } HRESULT InitD3D( HWND hWnd ) { if(NULL==(g_pD3D=Direct3DCreate9(D3D_SDK_VERSION))){return E_FAIL;} D3DPRESENT_PARAMETERS d3dpp; ZeroMemory( d3dpp, sizeof(d3dpp) ); d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; d3dpp.BackBufferCount = 1; d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE; d3dpp.MultiSampleQuality = 0; d3dpp.EnableAutoDepthStencil = TRUE; d3dpp.AutoDepthStencilFormat = D3DFMT_D16; d3dpp.hDeviceWindow = hWnd; d3dpp.Flags = 0; d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE ; if(FAILED(g_pD3D- CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,D3DCREATE_HARDWARE_VERTEXPROCESSING, d3dpp, g_pd3dDevice))){ if(FAILED(g_pD3D- CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING, d3dpp, g_pd3dDevice))){ return(E_FAIL); } } g_pd3dDevice- SetRenderState( D3DRS_LIGHTING, false ); Init(); return S_OK; } LRESULT CALLBACK MsgProc(HWND hwnd , UINT msg , WPARAM wp , LPARAM lp) { switch (msg) { case WM_DESTROY PostQuitMessage(0); return 0; } return DefWindowProc(hwnd , msg , wp , lp); } int WINAPI WinMain(HINSTANCE hInstance , HINSTANCE hPrevInstance ,PSTR lpCmdLine , int nCmdShow ) { MSG msg; DWORD dwID; WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, L Window1 , NULL }; RegisterClassEx( wc ); RECT rect; SetRect( rect,0,0,WINDOW_WIDTH,WINDOW_HEIGHT); AdjustWindowRect( rect, WS_OVERLAPPEDWINDOW, FALSE); SetRect( rect,0,0,rect.right-rect.left,rect.bottom-rect.top); hwnd = CreateWindow( L Window1 , L Shader , WS_OVERLAPPEDWINDOW ~WS_THICKFRAME ~WS_MAXIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT, rect.right, rect.bottom, NULL, NULL, wc.hInstance, NULL ); if (hwnd == NULL) return 0; timeBeginPeriod(1); if(SUCCEEDED(InitD3D(hwnd))){ ShowWindow(hwnd,SW_SHOWDEFAULT); UpdateWindow(hwnd); CreateThread(NULL , 0 , MainLoop , (LPVOID)hwnd , 0 , dwID); while (GetMessage( msg , NULL , 0 , 0 )) { TranslateMessage( msg); DispatchMessage( msg); } } UnregisterClass(L Window1 ,wc.hInstance); timeEndPeriod(1); // ★ 頂点シェーダの開放 SAFE_RELEASE( m_pVertexShader ); SAFE_RELEASE( m_pVertexDeclaration ); SAFE_RELEASE(g_pVB); SAFE_RELEASE(g_pd3dDevice); SAFE_RELEASE(g_pD3D); return 0; }
https://w.atwiki.jp/neetsdkasu/pages/36.html
バージョン管理に関するメモ バージョン管理の種類 ※集中型管理 CVS Subvertion (svn) ※分散型管理 Git Mercurial (hg) Bazaar (bzr) ※他にも色々あるらしい 用語 リポジトリ コミット ブランチ Git Subversion (SVN) バージョン管理 .
https://w.atwiki.jp/ndsdev/pages/8.html
@wikiにはいくつかの便利なプラグインがあります。 アーカイブ コメント ニュース 動画(Youtube) 編集履歴 関連ブログ これ以外のプラグインについては@wikiガイドをご覧ください = http //atwiki.jp/guide/
https://w.atwiki.jp/nadebook/pages/230.html
オープンソースカンファレンス2007 Kansai 日時 2007年7月20日(金)・21日(土) 10 00~17 00 場所 京都コンピュータ学院 京都駅前校 参加者 クジラ飛行机さん EZNAVI.netさん mrさん 楽市駱駝さん 粗茶 その他 会場の様子 本日はたくさんのユーザーさんが来てくれました! 楽市駱駝さん、EZnaviさん、mrさん、しらたまさん、ありがとうごさいました! 来場者は少なかったですが、中身の濃い議論ができました。 なでしこは、たくさん利用されている事例を紹介しなければ、なかなか理解してもらえません。 なんとかユーザーの活用状況を集める方法がないものでしょうかね!? とにかく、クジラさん他、お手伝いくださった皆様おつかれさまでした。 いろんな年代、いろんな業種のメンバーが集まると、お互いに良い刺激となって、「なでしこ」を盛り上げるために何かやらなきゃ!って思いますね。 参考 オープンソースカンファレンス2007 Kansai 楽市駱駝さんレポート 一番早く家に着いたであろう?、楽市駱駝こと哲也です。 今日と昨日、お疲れさまでした。今日出ていた話をまた、整理したいと思います~解決方法は別としてでいてた話は MS Office連携を OpenOfficeにも対応させる 関西弁など方言対応にする(笑) アンケート集計など、実務分野の強化として、集計系命令を作る マニュアルの完成へ(発行するとかPDFにするとか…) 法人化に向けて? 誰か何かをやって、IPAの未踏を取れないか??笑 話に上っていた、ソフトを作って欲しい人と、作りたい人との仲介掲示板のようなもの。完全に個人間で交渉して貰うか、代金の受け渡しなどに、法人として関与するか?などなど プログラミング自体から少し離れて、実務系のソフトをたくさん公開して(exeで用意する←DLするだけで実行できるように)、ある程度知ってから、「なでしこ」に戻ってきてもらう(キャッチフレーズは「ダイエット」?) 起動したときに、前回終了したときの実行モードをデフォルトにする 知名度をUPして、広告収入を増やす←次回の展示会で、セミナーやる?? ぐらいです。覚えてるだけ書きました。またあれば増やしてください。 みなさん(EZNAVIさんや、しらたまさん、粗茶さん)は専門分野をお持ちですから僕もなにか、専門分野を作らないとダメですねぇ…営業にしますか笑
https://w.atwiki.jp/tomokazu0525/pages/116.html
最終更新日時2012-08-24ここを編集 ■目次 XPATHとはXPATHによるノードや文字列の指定方法 XPATHを簡単に知る方法 (どれか1つで良い)firefoxのアドオンを使うXpath Checker firebug xpather(更新されておらず、現バージョンのFFでは使用不可) Internet Explorer google chrome 簡易スクレイピングブラウザとJavaScript デバッグツール で $x によるスクレイピング$xに各ブラウザ JavaScript デバッグツールの対応している状況 google chromeでのやり方 XPATHを使える言語、ソフト、アドオン実践例あるテキストを含むコメントノードを取得するXPath - 0x廃棄階層 - 統治局 ページフッタこのページの1階層上のページ このページの1階層下のページ このページに含まれるタグ このページへのアクセス数 ■本文 XPATHとは XPathとは - 意味/解説/説明/定義 : IT用語辞典 XPath - Mozilla Developer Network リンクをたどっていくと、かなり詳しく解説あり。 関連リンク:(英語での解説) XPath René Nyffenegger s collection of things on the web XPATHによるノードや文字列の指定方法 ブラウザのアドオンその他の方法で、おおざっぱなXPATHは取得できる。しかし知識があれば、さらに細かい指定ができる。 XPath使いのための日本語チートシート Adobe Spry XPath 逆引きリファレンス 目次抜粋 XPath基本 パスを指定する 比較 内容が等しいものを取り出す 内容が等しくないものを取り出す 値の大小で内容を取り出す 属性値が等しいものを取り出す 範囲指定 特定の出現位置にある内容を取り出す 特定の出現位置より大きいか小さいものを取得する 特定の出現範囲内のものを取り出す いずれかの出現順番の場合に内容を取り出す 出現順番が偶数番目のデータを表示する 出現順番が奇数番目のデータを表示する 出現順番が3の倍数のデータを表示する 出現順番が最後のものを取り出す 関連リンク @IT:XMLマスターへの道 第12回 XPathによるノードの指定法を理解する 2003/12/23 XSLTスタイルシート書き方講座(2):XPathの書き方の基本 サンプルで覚えるXSLTプログラミング XPATHを簡単に知る方法 (どれか1つで良い) firefoxのアドオンを使う Xpath Checker Greasemonkey開発になくてはならないほど便利なアドオンXPath Checker - 大人になったら肺呼吸 XPath Checker Add-ons for Firefox firebug Firebug で Xpath を調べる:Ubuntu Emacs etc. メモ:So-netブログ 関連リンク: 勉強用メモ - トップページ/windows/ブラウザ/firefox/アドオン/firebug xpather(更新されておらず、現バージョンのFFでは使用不可) 勉強用メモ - firefox/アドオン/XPATHER Internet Explorer selenium - Equivalent of Firebug s "Copy Xpath" in Internet Explorer? - Stack Overflow 英語だが、IEとfirefox(FF)用のブックマークレットが置いてある。 google chrome google chromeを使ってxpathを取得するための解説の動画。英語だが、英語わからなくても雰囲気でわかる。 Quick Tip Getting The XPath In Google Chrome - YouTube 関連リンク: Chromeだけで任意のノードのXPathを簡単に取得 たぶん革命 - nrm //lab.kss.inc - Petittech 簡易スクレイピング ブラウザとJavaScript デバッグツール で $x によるスクレイピング ブラウザだけとデバッグツールだけで簡単なスクレイピングできる。 $xというものがあり、ここにxpathを当てはめれば、そのページに含まれる該当要素を抜き出せる。 $x - FirebugWiki XPath関数 - prog*sig $xに各ブラウザ JavaScript デバッグツールの対応している状況 関連リンク: classics. JavaScript デバッグツール で $x で XPath セレクタ使えるのがいつの間にかメジャーになっていた google chromeでのやり方 chromeの場合は、F12で立ち上げた開発者ツールのconsoleに入力。 なお上記サイトの知識と、chromeの右クリックから得られるxpathを、そのまま使ってもシンタックスエラーが出ることがある。例えば、xpath内に""でくくられた文字列が出てくるとシンタックスエラー。x関数内を示す""か、xpathの""のいずれかの""を に変更が必要。 例)右クリックで得られたxpathが //*[@id="content"]/a のとき NGパターン : $x("//*[@id="content"]/a") OKパターン1 : $x( //*[@id="content"]/a ) OKパターン2 : $x("//*[@id= content ]/a") また、文字列だけを抜き出すなら、得られたxpathに /text()の付加が必要。 OKパターン3 : $x( //*[@id="content"]/a/text() ) OKパターン4 : $x("//*[@id= content ]/a/text()") XPATHを使える言語、ソフト、アドオン 勉強用メモ - javascript/XPATH 実践例 あるテキストを含むコメントノードを取得するXPath - 0x廃棄階層 - 統治局 ここを編集 ページフッタ このページの1階層上のページ このページの1階層下のページ このページに含まれるタグ xpath このページへのアクセス数 今日: - 昨日: - これまで合計: -
https://w.atwiki.jp/kiake77/pages/8.html
@wikiにはいくつかの便利なプラグインがあります。 アーカイブ コメント ニュース 動画(Youtube) 編集履歴 関連ブログ これ以外のプラグインについては@wikiガイドをご覧ください = http //atwiki.jp/guide/