ページ

2012年7月31日火曜日

[ドリトル] センサー

センサー付きのタートルを作ってみよう。
  • 自身から伸びるアンテナ(ヒゲ?)を持つ
  • アンテナは周期的に自身の周りを回転する。
  • 何かがアンテナに触れるとタートルはその時のアンテナの方を向く。
周りにエサを配置してアンテナがそれに触れたらそちらに向かう感じで。

2012年7月30日月曜日

[ドリトル] 平方数を求める

前回、円周率を算出してみたので今度は平方数を求めてみよう。
当たり前だが、sqrt 使用禁止。
√2、√3は簡単。
√2 は隣辺長1の直角2等辺三角形の底辺が √2 になる。

SCALE = 100.
t1 = Turtle ! create.
t1 ! 45 leftturn (SCALE) forward 90 rightturn (SCALE) forward.
Label ! ((t1 ! xPosition?) / (SCALE)) create.

2012年7月29日日曜日

[ドリトル] 円周率を求める

ふと思いついたのでやってよう。
タートルを使って円周率を求めてみる。
forward と rightturn で円を描けば周長がわかるので、「周長=直径×PI」より半円を描いた時の座標から円周率がわかる。

SCALE = 1.
APEX = 360.

t1 = Turtle!create hide.
[t1 ! (SCALE) forward (360.0/APEX) leftturn ] ! (APEX/2) repeat.

TextField ! (SCALE*APEX) create.
TextField ! (t1 ! yPosition?) create nextline.
TextField ! ((SCALE*APEX) / (t1 ! yPosition?)) create nextline.

「円周率=3.1416725」。おお、それなりの値が。

2012年7月28日土曜日

[Blogger] Blogger の画像ファイルの扱いについて

このブログで今まで主に使っている画像ファイルは「ドリトル」実行結果なので非常にシンプルなのが多い。なので、減色しても全く問題ないので、16 Color ( 4 bit ) PNG にしてサイズを小さくしている。
アップロードするファイルは数 KB ほどの物が多い。

Blogger では、画像を記事に埋め込むと元のファイルとは別にインライン表示用の画像が生成される。
ところが、3 KB ほどのサイズの元画像がインライン表示用には 10 KB 程になってしまったりと元画像よりサイズが大きくなってしまうことがよく発生する。いったいどういうことなの?

というわけでBloggerでの画像ファイルの扱いについて調べてみた。

2012年7月27日金曜日

[Scala] Function 型の実装

前回、関数の型について調べたので、今回はその実装について見てみることにする。

Function系のトレイトは、引数が1つの Function1 トレイトと引数が2つ以上からなる Function2 ~ Function22 までのトレイトでは実装している関数が異なる。 共通しているのは関数を実行する apply と文字列化用の toString。

  def apply(v1: T1): R
  override def toString() = "<function1>"

上は Function1 トレイトの例。他も同様。apply は抽象メソッドで toString は実装付き。

Function1 ではこの他に関数合成に関する compose と andThen が実装付きで定義されている。
一方、Function2 ~ Function22 では、curried と tupled がそれぞれ実装付きで定義されている。 (curry は deprecated されて curried になっている)。

まずは、Function1 から見ていこう。


Function1 トレイトの compose と andThen はこのようになっている。

  /** Composes two instances of Function1 in a new Function1, with this function applied last.
   *
   *  @tparam   A   the type to which function `g` can be applied
   *  @param    g   a function A => T1
   *  @return       a new function `f` such that `f(x) == apply(g(x))`
   */
  def compose[A](g: A => T1): A => R = { x => apply(g(x)) }

  /** Composes two instances of Function1 in a new Function1, with this function applied first.
   *
   *  @tparam   A   the result type of function `g`
   *  @param    g   a function R => A
   *  @return       a new function `f` such that `f(x) == g(apply(x))`
   */
  def andThen[A](g: R => A): T1 => A = { x => g(apply(x)) }

compose は関数の合成を行うメソッド。自関数 f( T1 ) に対して、g( A )=>T1 (要は戻り値の型が自関数の引数と同じ関数)を受け取って、f( g( A ) ) の結果になる関数を作成する。

andThen も関数の合成を行うが適用順序が逆になる。引数が自関数の戻り値と同じ型になる関数gを受け取り、 g(f(A)) の結果になる関数を作成する。

やってみよう。

    val f : Int => Int = (x : Int) => x * 3;
    val g : Int => Int = (x : Int) => x % 3;
    
    // f(g(x)) -> (x % 3) * 3   g を実行した結果にfを実行
    val fg : Int => Int = f.compose(g);
    println("fg= " + fg(5));    
    
    // g(f(x)) -> (x * 3) % 3   fを実行してからgを実行。
    val gf : Int => Int = f.andThen(g);
    println("gf= " + gf(5));


fg= 6 gf= 0

予想通りの結果になった。



次はFunction2~Function22 トレイト で定義されている curried と tupled を見てみよう。

  /** Creates a curried version of this function.
   *
   *  @return   a function `f` such that `f(x1)(x2) == apply(x1, x2)`
   */
  def curried: T1 => T2 => R = {
    (x1: T1) => (x2: T2) => apply(x1, x2)
  }

  /** Creates a tupled version of this function: instead of 2 arguments,
   *  it accepts a single [[scala.Tuple2]] argument.
   *
   *  @return   a function `f` such that `f((x1, x2)) == f(Tuple2(x1, x2)) == apply(x1, x2)`
   */
  def tupled: Tuple2[T1, T2] => R = {
    case Tuple2(x1, x2) => apply(x1, x2)
  }

curried はカリー化された関数を返す。
カリー化 (currying) とは、計算機科学分野の技法の一つ。複数の引数をとる関数を、引数が「もとの関数の最初の引数」で戻り値が「もとの関数の残りの引数を取り結果を返す関数」であるような関数にすること(by Wikipedia)。
要は 1つの引数を受け取って、残りの引数を受け取って結果を返すような関数を返す操作のことらしい。 このあたりはいずれ別途調べてみることにする。

tuppled は引数をタプルにした関数を返す。引数が1つになるのでFunction1 型になる。

とりあえず使ってみる。

    val addFunc : (Int, Int) => Int = (x: Int, y: Int) => x + y;

    val curriedAdd : Int => (Int => Int) = addFunc.curried;
    println( curriedAdd(2)(3));
    
    val tupledAdd : Tuple2[Int, Int] => Int = addFunc.tupled;
    println( tupledAdd( (2,3) ));


5 5

こんな感じ。
「 val curriedAdd : Int => (Int => Int) 」は、普通は「val curriedAdd : Int => Int => Int 」と書けばいいのだが、何が起きているの理解しにくいのであえて括弧付きで書いてある。

タプル化したバージョンも「 tupledAdd( 2,3 ) 」と普通に 2 引数で書けば暗黙的にタプルが生成されて実行できるのだが何をしたのかわからなくなるので明示的にタプルを作って渡している。
このようにタプル化して 1 引数化することで、Function1 にしかない関数合成関数を使えるようになる。



2012年7月26日木曜日

[ドリトル] リサージュ図形を描く(三角関数禁止)

ドリトルのサンプルにリサージュ図形 を描くものがある。
これはこれで楽しいのだが、三角関数は子供に説明できないので三角関数を使わずに書いてみることにしよう。
forward 命令と leftturn 命令でタートルに円運動をさせてそこから X 座標と Y 座標を取得するようにする。

2012年7月25日水曜日

[Scala] 関数の型

たとえば、Int型 の引数をとってその倍を返す関数はこのような感じになる。

  val f : (Int) => Int =  (x : Int) => x*2;
  println(f(10))

つまり、「 (Int) => Int 」が変数 f の型になる。
関数を実行するときには、f(10) になるのだが、例によってapply が省略されているので、 省略せずに書くと、f.apply(10) になる。もちろん結果は同じ。

関数に型があるということは関数もオブジェクトなわけで、実際、引数の数に応じて Function1 ~ Function22 というクラスが用意されている。つまり、

    val f2 : Function1[Int,Int] =  (x : Int) => x*2;
    println(f2(10))

というように書くこともできる。むしろこちらが正式な書き方で「(Int) => Int」のほうがシンタックスシュガーにあたる。
「 Function1[Int,Int] 」は引数が1つで Int型、戻り値も int であることを表している。 Int型の引数を2つとって戻り値がDoubleの場合はこうなる。

var f: (Int, Int) => Double = (x: Int, y: Int) => (x + y) / 2.0;
var f2: Function2[Int,Int,Double] = (x: Int, y: Int) => (x + y) / 2.0;

Function22まではあるが、Function23 はない。そうなると引数を23個にしてみなくなるのが人間というものだろう。

    val f23 : (
        Int, Int, Int, Int, Int, Int, Int, Int, Int, Int,
        Int, Int, Int, Int, Int, Int, Int, Int, Int, Int,
        Int, Int, Int
        ) => Int = null;

type Function23 is not a member of package scala

Function23 が見つからないそうだ。 普通に引数が23個のメソッドも定義できないのだろうか?

  def f23(
         x1:Int,  x2:Int,  x3:Int,  x4:Int, x5:Int, 
         x6:Int,  x7:Int,  x8:Int,  x9:Int, x10:Int,
        x11:Int, x12:Int, x13:Int, x14:Int, x15:Int, 
        x16:Int, x17:Int, x18:Int, x19:Int, x20:Int,
        x21:Int, x22:Int, x23:Int
      ) : Int = 0;

定義できた。どうなってるのだろう。

    val f = f23 _;

missing arguments for method f23 in object FuncTest; follow this method with `_' if you want to treat it as a partially applied function

メソッドとして定義することはできるが、それをオブジェクトとして取り扱うことができないということのようだ。引数が 22 個までなら上のコードで問題ない。

ちなみにメソッドとして定義されているものを関数オブジェクトとして取り扱うときにはこのようにメソッド名の後ろに「 _ 」をつける。部分適用を使って関数として取り出しているような感じ



Function の実装を確認してみよう。

@annotation.implicitNotFound(msg = "No implicit view available from ${T1} => ${R}.")
trait Function1[@specialized(scala.Int, scala.Long, scala.Float, scala.Double) -T1, @specialized(scala.Unit, scala.Boolean, scala.Int, scala.Float, scala.Long, scala.Double) +R] extends AnyRef

見にくいのでアノテーションを取っ払うと、

trait Function1[-T1, +R] extends AnyRef

関数の引数に対応する型パラメータが反変、戻り値に対応する型パラメータは共変になっている。 他の FunctionXX も引数に相当する型パラメータが増えているだけで基本は同じ。

ところで、Function1 では引数は @specialized アノテーションで、Int、Long、Float、Double を特別扱いしているのに対して、Function2 で特別扱いしているのは、Int、Long、Double でFloatが抜けている。
戻り値は Unit、Boolean、Int、Long、Float、Double で同じ。
一方、Function3 以降では引数、戻り値ともに特別扱いなし。

@specialized アノテーション はコンパイルするとクラス数が増えるのでよく使うと思われるものに限定しているのだろう。

次回は、Function系クラスの実装を確認してみよう。



2012年7月24日火曜日

[ドリトル] キーボード操作でドリフト亀

ドリトルでキーボードイベントを拾ってみた。

button1 = Button ! "button" "UP" create.
button1:action = [self! "hoge" set].

GUIオブジェクトを作成する際に第 2 引数でキーと関連付けておけば、 キー押下時に当該オブジェクトの action 命令が呼び出される。うーん、シンプル。

label1 = Label ! "label" create.
button1 = Button ! "button" "UP" create hide.
button1:action = [label1! "hoge" set].

こんな感じにイベントを受け取るオブジェクトが hide されていてもちゃんと action は発生する。

2012年7月23日月曜日

サイトマップの登録

Google の ウェブマスターツール で「サイトマップの登録」という機能がある。
使い方が良く解らなかったのだが、 Googleにサイトマップを登録する(Bloggerブログ版) にわかりやすい解説があったのでやってみた。

2012年7月22日日曜日

[ドリトル] self

self(自分)の使い方を確認しておこう。

lblResult = Label ! "result" create.
lblResult2 = Label ! "result2" create nextline.

t1 = Turtle ! create.
t1Child = t1 ! create.
t1:value = 1.

t1Child:test1 = [ lblResult ! (value) set ].
t1Child:test2 = [ lblResult2 ! (self:value) set ].

t1Child!test1.
t1Child!test2.

結果はいずれも 「1」になる。self 指定も無指定も検索起点は 自オブジェクトで、自オブジェクトにプロパティ値が設定されていないので親のプロパティ値が取得される。
ちなみに、「 :value 」を指定すると起点がルートになるので、「 undef 」になる。

2012年7月21日土曜日

[Scala] 変位指定と isInstanceOf

前回の 変位指定 の続き。
変位指定付きの型のオブジェクトを isInstanceOf[ T ] で検査した場合の挙動を確認しておこう。

まずは共変から。

object VarianceSample {
  def main(args : Array[String]) {
    var covariantStr : Covariantable[String] = new Covariantable[String];
    var covariantAny : Covariantable[AnyRef] = new Covariantable[AnyRef];

    println(
       "Covariantable[String] is instance of Covariantable[AnyRef]: " 
        + covariantStr.isInstanceOf[Covariantable[AnyRef]]);

    println(
        "Covariantable[AnyRef] is instance of Covariantable[String]: " 
        + covariantAny.isInstanceOf[Covariantable[String]]);
  }
}

class Covariantable[+R] {
  def hoge(): R = null.asInstanceOf[R];
}


Covariantable[String] is instance of Covariantable[AnyRef]: true Covariantable[AnyRef] is instance of Covariantable[String]: true

あれ?
共変なので、[String] is instance of [AnyRef] は true でも反対は false と思ったのだが、 両方とも true になった。

2012年7月20日金曜日

[ドリトル] 図形の回転

少し思うところがあったので、図形を回転させる際の中心について確認しておこう。
まずはシンプルに ( 0, 0 ) に円を描いて回転させる。

t1 = Turtle ! create.
t1 ! 50 circle.
shape1 = t1 ! makefigure.

// mark initial position
shapeOrg = shape1 ! create (blue) paint.  

// rotate shape.
[ shape1 ! create.
  shape1 ! 60 rightturn.
] ! 6 repeat.
t1 ! penup movetocenter.

2012年7月19日木曜日

[Scala] 変位指定: 共変、反変、非変

Scala のコードを見ているとよくこんなコードに当たる。

trait Traversable[+A] extends TraversableLike[A, Traversable[A]] ...

この +A ってなんだろう。ジェネリクスの指定関係だということはわかるのだが。
調べてみたら、共変、反変、非変というジェネリクスの性質を指定するもののようだ。

2012年7月18日水曜日

[ドリトル] QIX

跳ね返り命令を使ってみよう。
昔あったQIXという陣取りゲームに出てくるあの南京玉すだれみたいなやつを書いてみることにする。
例によって基本方針。

  • 2匹のタートルをエリアの壁に反射させながら動かす。
  • 3匹目が両タートルの間に線を描画する。
  • 一本ごとに図形化し配列に格納する。古くなった線は消していく。

こんな感じでそれっぽくなるだろうか。

2012年7月17日火曜日

[ドリトル] 跳ね返り (四角形)

前の記事で 「反射する方向は、入射角と最初に引いた線の角度で決まって、その線上のどちら側に反射するかだけが実際に反射する面との相互作用で決まる」と書いた。
ところで、反射後の角度は、反射面の角度の2倍で効くので90度の場合は180度方向が変わるわけで、反射方向はドリトルが補正するから正しい角度に反射しそうな気がする。
そうなら、polygon命令で描いた矩形でも(forward×4も)正しく反射するはず。

t1 = Turtle ! create.

t1 ! penup -100 100 moveto pendown.
t1 ! 100 4 polygon.
shape1 = t1 ! makefigure.
t1:collision = t1:bounce. 

t1:go = [ | length | 
  [ ! 1 forward ] ! (length) repeat ].

t1 ! (red) linecolor.
t1 ! penup 0 200 moveto -120 direction pendown 300 go.
t1 ! penup 100 200 moveto -120 direction pendown 300 go.
t1 ! penup -100 -100 moveto 60 direction pendown 300 go.
t1 ! penup -200 -100 moveto 60 direction pendown 300 go.

4方向から当ててみたがやはり四角形はうまく反射するようだ。
内側から当ててみよう。

2012年7月16日月曜日

[ドリトル] 跳ね返り (円)

前の記事で跳ね返りをやったので、もう少し続けてみる。 今度は円。

t1 = Turtle ! create.

// ターゲット作成
t1 ! penup -100 100 moveto pendown.
t1 ! 100 circle.
t1 ! penup 0 direction movetocenter.
shape1 = t1 ! makefigure.
t1:collision = t1:bounce. 

// 一歩づつ進める。
t1:go = [ | length | 
  [ ! 1 forward ] ! (length) repeat.
].

// 初期位置を下にずらしながらターゲットに当てる。
// (100, -100) - ( 100, 100)
t1 ! 1 linewidth (red) linecolor.
[ | count | 
  y = 100 - (count * 10).
  t1 ! penup 150 (y) moveto 180 direction pendown.
  t1 ! 600 go.
] ! 20 repeat.

あれ、全部まっすぐ跳ね返ってきた。
円を少し回転させてみる。ついでにタートルのサイズも少し小さくしてみよう。

2012年7月15日日曜日

[ドリトル] 跳ね返り

Turtle には bounce (跳ね返る)命令があり、跳ね返り動作を簡単に記述することができる。 面白そうなので早速使ってみよう。

t1 = Turtle ! create.

// ターゲット作成
t1 ! penup -200 100 moveto pendown 45 rightturn.
t1 ! (100 * sqrt(2)) forward 90 rightturn (100 * sqrt(2)) forward.
t1 ! penup 0 direction movetocenter.
shape1 = t1 ! makefigure.

// Collision 動作を bounce動作に置き換える。
t1:collision = t1:bounce. 

// 一歩づつ進める。
t1:go = [ | length | 
  [ ! 1 forward ] ! (length) repeat.
].

// 初期位置を下にずらしながらターゲットに当てる。
t1 ! 1 linewidth (red) linecolor.
[ | count | 
  y = 100 - (count * 10).
  t1 ! penup 100 (y) moveto 180 direction pendown.
  t1 ! 600 go.
] ! 20 repeat.

[Scala] apply

val a1 : Array[Int] = new Array(5);
val a2 : Array[Int] = Array(5);

誰だってこのコードを見たら、「 Scala って new は省略できるんだ。」って思う(と思う)。

val a1 : Array[Int] = new Array(5);
val a2 : Array[Int] = Array(5);
println("a1 size = " + a1.length);
println("a2 size = " + a2.length);


a1 size = 5 a2 size = 1

で、「あれっ」となる。

val a1 : Array[Int] = new Array(5);
val a2 : Array[Int] = Array(5);
println("a1.toSeq = " + a1.toSeq);
println("a2.toSeq = " + a2.toSeq);


a1.toSeq = WrappedArray(0, 0, 0, 0, 0) a2.toSeq = WrappedArray(5)

できた Array の中身はこんな感じになっている。
(ArrayそのもののtoStringは「a1 = [I@7f188439」のようになってしまう。)

「 Array(5)」で省略されていたのは、apply という名のクラスメソッド。
省略せずに書くと、「Array.apply(5)」になる。


クラスに対する Apply


クラス名に「(」が続いた場合には、apply メソッドが呼び出される。
通常はオブジェクトの生成(ファクトリ)として使用されるがコンストラクタと違って、 そのクラスのオブジェクトを返す必要はない。実際、List.apply も

val l : List[Int] = List(1,2,3); 
println("List.apply  = " + l.getClass());


List.apply = class scala.collection.immutable.$colon$colon

と謎なクラスを返している。「val l : List[Int]」に代入できていることから List の派生クラスになるわけなのだが、実際には派生クラスを返す必要さえない。
なのでこういうこともできてしまう。

object ApplySample {
  def main(args : Array[String]) {
    val s : String = ApplySample(10);
    println(s)
  }
  def apply(a: Int) : String = "hello." + a;
}

hello.10

引数をとるようにしたが引数がない場合でも同様なことができる。
apply メソッドはそのクラスまたはその派生クラスのオブジェクトを返すのが慣例になっているそうなので、 あまり変なことはしないほうがいいとは思う。


オブジェクトに対するApply


オブジェクトに対しても同様で、オブジェクトに括弧を続けるとオブジェクトに定義されている apply が呼ばれる。

val a : Array[Int] = Array(100,200,300);
println(a(1));

200

これで配列の添字アクセスのようなことができるようになっている。

関数オブジェクトに対する呼び出しも apply が省略されている。

val f: (Int) => Int = (x: Int) => x * 2;
println(f(10))
println(f.apply(10))

既存の関数をオブジェクト化した場合も同じ。

println(Math.sin(Math.Pi / 2));
println((Math.sin _).apply((Math.Pi / 2)));

ただし、直接に関数を実行したときには、apply が省略されているわけではないので、 「 Math.sin.apply( Math.Pi ) 」と書くことはできない。



いずれにしても、apply は Scala の文法的には特別扱いになっているが、メソッドそのものが特別なわけではない。


2012年7月14日土曜日

[Scale] 数値指定のfor文について

for (i : Int <- 1 to 5) { ... }

以前、for文の記事 を書いたとき、なぜ、わざわざ java の for ( int i=0; i<10; i++) と異なる構文を用意したかと思っていたが、 実はこういうことだった。

val range : Range = 1 to 5.
for (i : Int <- range ) { ... }

Range 型オブジェクトに対する 拡張 for 文だった。
(「拡張」 for 文というか、結局 Scala の for 文はこの形式だけ)

Scala では「1」や「2」などの primitive もオブジェクト扱いなのでメソッドが呼び出せる。
値を返すメソッドは中置記法で書けるので一見気が付きにくい。

for (i : int <- 1 to 5) { ... }   も

for (i : int <- 1.to(5)) { ... }

と書けば Int 型のメソッドが実行されて何かができていることが一目でわかる。
どうも Scala の中にはこういう罠があちこちにあるような気がする・・・



Intクラスのドキュメンテーションによれば、

 *  There is an implicit conversion from [[scala.Int]] => [[scala.runtime.RichInt]]
 *  which provides useful non-primitive operations.

とうことなので実際に to 等のメソッドが用意されているのは RichInt クラスになる。
RichInt クラスで定義されている Range 型を返すメソッドを見てみると、

  def until(end: Int): Range = Range(self, end)
  def until(end: Int, step: Int): Range = Range(self, end, step)
  def to(end: Int): Range.Inclusive = Range.inclusive(self, end)
  def to(end: Int, step: Int): Range.Inclusive = Range.inclusive(self, end, step)

がある。
ステップ指定付きの to() を使ってみよう。

for (i : Int <- 1 to (10,2)) print(i);

13579

until() が Range 型を返しているのに対して、 to() は Range.Inclusive を返している。
Range 型では終端値は含まないのに対して、その派生型である Range.Inclusive は終端値を含むという違いがある。

for (i : Int <- 1 to 5) print(i);
println;
for (i : Int <- 1 until 5) print(i);

12345 1234



[ドリトル] 回転するカメ その2


前回の続き。 自転しながら動くタートルを作る。

前回は独自の「進行方向」プロパティを用意して、forward する際に、角度と移動距離から三角関数で移動後の位置を求めた。
いまいちタートルグラフィックスぽくないので別のやり方でやってみる。三角関数禁止。

基本戦略。
  • 進行方向を向くタートル(非可視)と回転するタートルの2匹組にする。
  • 片方のタートルが外から使える外部タートルでもう一匹は内部タートル
いくつかのオプションがあるので比較検討する。
多きくわけて、「外部/内部どちらが回転するか」、「外部/内部どちらが描画するか」の組み合わせて設計が分かれそう。

2012年7月12日木曜日

[ドリトル] 回転するカメ


前回の記事で タイマーが使えるようになったので使ってみる。
自転しならが円を書く Turtle を作ってみよう。

プロトタイプとしてして作って、使うときにはなるべく自然に Turtle として使えるようにする。

基本戦略。
  • 自身で回転専用の Timer を保持し、一定の速度で自身を回転させる。
  • 実際に進む向きは、専用のプロパティとして保持する。
  • forward をオーバーライドして、実際に進む向きから自身の移動位置を算出する。
  • right/leftturn をオーバーライドして、実際に進む向きのプロパティ値の更新をする。
こんな感じ。create 時に回転速度を引数として与えるようにしてある。

2012年7月11日水曜日

[ドリトル] Timerを使う

タイマーを使ってみよう。
タイマーで定期的な実行ができる。動きが見えるようにゆっくり動かす時に使う。
aTimer ! [ブロック] execute. であらかじめ指定したインターバルで指定回数(または指定時間)実行を繰り返すことができる。

周回する Turtle の速さを Slider で変えてみよう。
Slider を動かすとそれで周回する Turtle の速さを変える。

t1 = Turtle ! create penup 150 back pendown.
slider1 = Slider ! create.
label1 = Label ! (slider1!value?) create.
timer1 = Timer ! create.

slider1:action = [ 
  label1 ! ( self ! value?) set. 
  timer1 ! (0.1 * ( self ! value?) / 50) interval.
].

timer1 ! 0.1 interval 360 times.
timer1 ! [
  t1 ! 10 leftturn 15 forward.] execute.

2012年7月10日火曜日

[ドリトル] 衝突判定 集中砲火版


前回の続きで、衝突判定でもう少し遊んでみよう。
今度は、360度全周囲から突入してみる。
基本方針は以下の通り。
  • 中心にターゲットを配置する。
  • 一度ずつ角度を変えて中心から一定距離進み、pendown して衝突するまで戻る。

t1 = Turtle ! create.

// create target.
TARGETSIZE = 100.
HALFSIZE = targetSize / 2.
t1 ! penup (HALFSIZE) back pendown 1 linewidth.
t1 ! 90 leftturn (HALFSIZE) forward 90 rightturn (TARGETSIZE) forward.
t1 ! 90 rightturn (TARGETSIZE) forward 90 rightturn (TARGETSIZE) forward.
t1 ! 90 rightturn (HALFSIZE) forward 90 leftturn.
t1 ! makefigure (blue) paint.
t1 ! penup movetocenter.
collisioned = false.

t1:backUntilCollision = [ |; count | 
   collisioned = false.
   count = 0.
   [ (collisioned ! not) ! (count < 200) allTrue ] ! while [
     self ! 1 back.
     count = count + 1.
   ] execute.
   self ! penup movetocenter. 
].

t1:collision = [ collisioned = true. ].

// try to collision
inCollision = false.
[ | y |
  t1 ! penup movetocenter.
  t1 ! 1 rightturn 200 forward.
  t1 ! pendown.
  t1 ! backUntilCollision.   
] ! 360 repeat.  
おお。いい感じで衝突判定されている。

2012年7月9日月曜日

[ドリトル] 衝突判定

Dolittleでは、Turtle と 図形との間で衝突判定ができる。
Turtleが他の図形と重なったと判定された時に、 collision命令(「衝突」命令)が実行される。

面白そうなので早速使ってみる。
どのくらいの範囲で衝突したとみなされるのか調べてみよう。

基本的な考え方は以下の通り。
  • ターゲットとなる図形を書く。ターゲットは20x20の正方形
  • Y座標を上から下へずらしながら、左から右へTurtleを動かし衝突するか調べる。
  • 最初に衝突したY座標と最後に衝突したY座標を表示する。
やってみよう。

2012年7月8日日曜日

[ドリトル] GUIイベントの同時実行性

ボタンを押してアクションが実行されるのだが、実行中も少なくとも見た目上はGUI操作などはブロックされておらずバックグランド的に動いているように見える。

確認してみよう。

t1 = Turtle ! create.
t2 = t1 ! create.
t2 ! penup 200 forward.
btn1 = Button ! "No.1" create.
btn2 = Button ! "No.2" create.
btn1:action = [ t1 ! (l1) xcircle].
btn2:action = [ t2 ! (l2) xcircle].

l1 = Label ! "***********" create.
l2 = Label ! "***********" create.

t1:xcircle = [ | myLabel |
  myLabel ! "draing..." set.
  [
    self ! 1 forward 1 rightturn.
  ] ! 360000 repeat.
  myLabel ! "done" set.
].

[ドリトル] GUIをつける

GUI部品も用意されているようなので使ってみよう。
ボタン(Button)、ラベル(Label)、フィールド(TextField)、選択メニュー(SelectMenu)、スライダー(Slider)が用意されている。

t1 = Turtle!create.
Label ! "Depth" create.
field1 = TextField ! 1 create 50 45 size.
btnRun = Button ! "Run" create 80 45 size.
btnClear = Button ! "Clear" create.
lblStatus = Label ! "" create.

t1:koch = [
  | level width ; newWidth |
  [level <= 0 ] ! then [
     self ! (width) forward.
    ] else [
     newWidth = width / 3.
     self ! (level - 1) (newWidth) koch.
     self ! 60 leftturn (level - 1) (newWidth) koch.
     self ! 120 rightturn (level - 1) (newWidth) koch.
     self ! 60 leftturn (level - 1) (width - 2 * newWidth) koch.
   ] execute. 
].
btnRun : action = [ 
  lblStatus ! "drawing..." set.
  t1 ! penup movetocenter 250 back 90 rightturn 100 forward 90 leftturn pendown.
  t1 ! (field1!get) 500 koch.
  lblStatus ! "done." set.
].
btnClear : action = [
  | ; shape1 |
  lblStatus ! "clearing..." set.
  shape1 = t1 ! makeFigure.
  shape1 ! hide.
  lblStatus ! "done." set.
].

[Scala] 実装付き trait の仕組み

前の記事で書いたように、Scala の trait には、
  • 実装を持つことができる。
  • クラスは(Java の Interface と同様に) 複数の trait を実装することができる。
という特徴があるので、多重継承みたいなことができてしまう。
(ちなみに、trait を実装することを Scala では ミックスイン というらしい。)

Scala は Java の上で動くわけなので Java でできないことはできないわけなのだが、どのように実現されているのだろうか?
例外を発生させてスタックトレースを見てみることにする。

まずは、普通にクラスを extends した場合。

object TraitSample {
    def main(args : Array[String]) {
        new English().hello();
    }
}

class Greetable {
  def hello() : String = {
    throw new IllegalArgumentException("in Greetable");
  }
}

class English() extends Greetable {
}

Exception in thread "main" java.lang.IllegalArgumentException: in Greetable at Greetable.hello(TraitSample.scala:9) at TraitSample$.main(TraitSample.scala:3) at TraitSample.main(TraitSample.scala)

普通に見慣れた感じのスタックトレース。スタック中に English.hello()は出現していない。

次に、trait を使ってみる。

object TraitSample {
    def main(args : Array[String]) {
        new English().hello();
    }
}

trait Greetable {
  def hello() : String = {
    throw new IllegalArgumentException("in Greetable");
  }
}

class English() extends AnyRef with Greetable {
}

Exception in thread "main" java.lang.IllegalArgumentException: in Greetable at Greetable$class.hello(TraitSample.scala:9) at English.hello(TraitSample.scala:13) at TraitSample$.main(TraitSample.scala:3) at TraitSample.main(TraitSample.scala)

ふむ。
このスタックトレースを見ると、まず実装クラスの English.hello() が実行されて、そこから、Greetable$class.helloというクラスが呼び出されていることがわかる。

つまり、実装クラスにメソッドが生成されるとともに 実装 trait のオブジェクトも生成されていて、 実装クラスのメソッドから実装 trait オブジェクトのメソッドが実行される、という構造になっているようだ。

[Scala] trait

Scala では Java でいうところの Interface は trait という。
trait を少し使ってみる。

object TraitSample {
    def main(args : Array[String]) {
        val eng : English  = new English();
        println(eng.hello());
    }
}

trait Greetable {
  def hello() : String;
}

class English() extends AnyRef with Greetable {
  override def hello() : String = "hello.";
}

hello.

こんな感じ。「extends AnyRef」は省略できるのだが、派生クラスを省略した場合には実装する最初の trait は extends で書かないとエラーになる。

class English() extends Greetable {
  override def hello() : String = "hello.";
}

こうなると Greetable が trait なのだか class なのだか分からないのでちょっと嫌な感じ。
ちなみに、 AnyRefは参照型の全オブジェクトの親クラス。
詳しくはこちら ( 日経ITプロ Scala言語を探検する 4 ) を参照。

Anyすべてのオブジェクトの親クラス
  AnyValすべてのプリミティブ型(Intとか)の親クラス
  AnyRefすべての参照型オブジェクトの親クラス(上以外)

上の例の override は省略することができる。Scala では、「すでに実装のあるメソッド」をオーバーライドする場合には override を指定しなければならない。もちろんオーバーライドでないのに override を指定するとエラーになるので、実装のない抽象メソッドを実装する場合にも間違い防止に付けておいたほうがいい。

trait は実装を持つこともできる。

...

trait Greetable {
  def hello() : String = "hello.";
}

class English() extends AnyRef with Greetable {
}

hello.

もうこうなると 抽象 class でも trait でもどちらでもよい気がしてくる。
ただ、これはこれで便利で、汎用的な機能をいろいろ trait に実装できるので無駄な実装がかなり減る気がする。

object TraitSample {
    def main(args : Array[String]) {
        val eng : English  = new English();
        println(eng.hello());
        println(eng.bye());
    }
}

trait Greetable {
  def hello() : String = "hello.";
}

trait Byeable {
  def bye() : String = "bye.";
}

class English() extends AnyRef with Greetable with Byeable {
}

hello. bye.

もはや多重継承。実装を宣言している2つの trait が同じメソッドを持っている場合はどうなるのだろうか?
まず実装を持っている trait がひとつだけの場合には何も問題ない。普通に動く。

両方とも実装を持っていた場合にはコンパイルエラーになる。
上のコードで Greetable に Byeable と同じ bye() メソッドを定義するとこのようになる。

overriding method bye in trait Greetable of type ()String; method bye in trait Byeable of type ()String needs `override' modifier

override をつければいいのか? とはいっても両 trait とも何かを override しているわけではないので、trait 側にoverride をつけるわけにはいかない。というわけなので、実装するクラス側で override してやるしかない。
object TraitSample {
    def main(args : Array[String]) {
        val eng : English  = new English();
        println(eng.hello());
        println(eng.bye());
    }
}

trait Greetable {
  def hello() : String = "hello.";
  def bye() : String = "bye [Greetable].";
}

trait Byeable {
  def bye() : String = "bye [Byeable].";
}

class English() extends AnyRef with Greetable with Byeable {
  override def bye() : String = super.bye();
}

hello. bye [Byeable].

super で呼び出されたのは Byeable のほうだった。ちなみに、
...
class English() extends AnyRef with Byeable with Greetable {
  override def bye() : String = super.bye();
}

hello. bye [Greetable].

あと勝ちだった。

2012年7月7日土曜日

[Scala] 多重ループ

for文で多重ループ

    for (i<-1 to 2; j<-5 to 6) print(i + "-" + j + " ")
実行結果:
1-5 1-6 2-5 2-6

ふむ。後ろが先に回っている。
拡張For文形式。ついでに if 句をつけてみる。

    val a = Array(1, 2, 3, 4);
    val b = Array(6, 7, 8, 9);
    for (i <- a if i % 2 == 0; j <- b if j % 2 == 0)
      print(i + "-" + j + " ");
実行結果:
2-6 2-8 4-6 4-8


yield句をつけると返り値はどうなるのだろう。

    val a = Array(1, 2, 3, 4);
    val b = Array(6, 7, 8, 9);

    val result : Traversable[String] = 
        for (i <- a if i % 2 == 0; j <- b if j % 2 == 0) yield
          i + "-" + j + " ";
    println(result);
実行結果:
ArraySeq(2-6 , 2-8 , 4-6 , 4-8 )


ふつうにTraversableで受けれた。返り値まで多次元になるわけではないようだ。

[Scala] 値を返すFor文

久々にScala。
前回はフィルタ条件付きのFor文を見たので、今回は値を返すFor文を見てみる。

    val a : Array[Int] = Array(-1, 2, -3);
    val result : Array[Int] = for (i: Int <- a) yield i.abs;
    for (i <- result) print(i);

yield節をつけることでこのfor文は結果を返すようになる。yieldの後ろがブロック式(複文)の場合には最後の 文 が返る(ブロック式の値は最後の文の値になるのがScalaのルール).

実行結果:
123


Arrayの関数呼び出しを使って書く場合は Traversable#map を使う。
    val result2: Array[Int] = a.map((i : Int) => i.abs);
    for (i <- result2) print(i); 

実行結果:
123

省略して書くとこんな感じ。
    val result3 = a.map(_.abs);

例によって、独自クラスでfor yieldを使えるようにしてみる。

object ForYieldSample {
  def main(args: Array[String]) {
    val a : Array[Int] = Array(-1, 2, -3);
    val fey : ForEachYieldable[Int, Array[Int]] = new ForEachYieldable(a);
    val result : Array[Int] = for (i: Int <- fey) yield i.abs;
    for (i <- result) print(i);
  }
}

class ForEachYieldable [A, Repr <: Array[A] ](col: Repr) {
  def repr: Repr = col;
  def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {
    println("Here is ForEachYieldable#map");
    val b = bf(repr)
    b.sizeHint(repr)
    for (x <- repr) b += f(x)
    b.result
  }
}
実行結果:
Here is ForEachYieldable#map
123

確かに ForEachYieldable#map が実行されている。
元の TraversableLike#map の実装では、
val b = bf(this)
b.sizeHint(this)
となっていたのだが、この ForEachYieldable 自身は Traversable を実装していないので、 実際のデータを保持しているrepr を引数に使っている。このように、map自体の実装で使わなければ ForEachYieldable 自身に foreach を実装する必要はない。

2012年7月6日金曜日

画像のキャプチャ

巷にはいろいろなキャプチャ用ツールがあるようなので調べれば便利なものがいろいろあると思うのだが、とりあえず手元にあるものでなんとかしてみた。

 ■Snipping Tool 

Windows7 プリインストール済みのツール。アクセサリに入っている。
手軽でPNGでも保存できるのだが、減色ができないのでサイズが大きくなってしまう。

 ■IrFanView 

普段ビューアーとして使っている IrFanView なのだがキャプチャ機能がついている。ショートカットは「C」。
キャプチャ機能から直接ファイルに保存することができて、PNG出力する際にはPNGOUTプラグインが使えるのだがうまく減色してくれないみたい。

仕方がないので一度メインWindowに取り込んでから、Save for Webプラグインを使って16色に減色して保存。これでサイズはかなり小さくなるし、写真などをキャプチャするので無ければこれで十分。

2012年7月5日木曜日

[ドリトル] 再起呼び出しでフラクタル図形を描く

Dolittleで定義するメソッドは再起呼び出しをすることができる。
ということで早速フラクタることにする。まずはコッホ曲線
t1 = Turtle!create.
t1:koch = [
  | level width ; newWidth |
  [level <= 0 ] ! then [
     self ! (width) forward.
    ] else [
     newWidth = width / 3.
     self ! (level - 1) (newWidth) koch.
     self ! 60 leftturn.
     self ! (level - 1) (newWidth) koch.
     self ! 120 rightturn.
     self ! (level - 1) (newWidth) koch.
     self ! 60 leftturn.
     self ! (level - 1) (width - 2 * newWidth) koch.
   ] execute. 
].
t1 ! 2 500 koch.
...
t1 ! 6 500 koch.

2012年7月4日水曜日

[ドリトル] メソッドの定義


Dolittleでは、生成したオブジェクトにメソッドを定義することができる。

ポイントは「クラスに定義を追加」するのではなく、生成したオブジェクトに追加するところ。

t1 = Turtle!create.

t1:square = [
  | x |
  self ! 45 leftturn.
  self ! (x) forward.
  self ! 90 leftturn.
  self ! (x) forward.
  self ! 90 leftturn.
  self ! (x) forward.
  self ! 90 leftturn.
  self ! (x) forward.
  self ! 45 leftturn.
].

t1 ! 50 forward.
[ 
t1 ! 30 square.
t1 ! 50 forward.
] ! 4 repeat.

2012年7月3日火曜日

ページガジェットの罠

Bloggerに静的ページを追加した。

で、ページガジェットを追加しようとして、「レイアウト画面」でガジェットを追加しようとした。そうしたらページガジェットは「追加済み」となっていて追加できない。

いろいろ見て回ったのだが、結局わかったことは、

ページ画面で「ページの表示形式」が「表示しない」になっていた

ことが原因だった。
この時は明示的にページを追加する必要があるみたい。
これを「サイドリンク」に変更して解決。

2012年7月2日月曜日

[ドリトル] Dolittleのプラグラムを英語で書く。

先のエントリでも書いたが、Dolittleのプログラミング言語は日本語対応である。

カメ = タートル!作る。 [ カメ ! 50 歩く。 カメ ! 60 右回り。 ] ! 6 繰り返す。


でもプログラムは英語で書きたいと思った時には英語で書ける。

t1 = Turtle!create.
[
t1 ! 50 forward.
t1 ! 60 rightturn.
] ! 6 repeat.

ところがこれが、添付されてくるPDFファイルにも書いてないし、Wikiページにもリンクがない。
検索してようやく一部の情報が記載されているページを見つけた。

"Dolittle" Text http://dolittle.eplang.jp/index.php?idotextE
     基本的な解説など。

Objects http://dolittle.eplang.jp/index.php?dev_ObjectList
      定義済みオブジェクト一覧

Messages http://dolittle.eplang.jp/index.php?dev_MessageList
      定義済みメッセージなど

これでなんとかなるかも。

2012年7月1日日曜日

Logoについて

子供向けに何か面白いの無いかなと調べたのでメモ
今更Logoかという話もあるがやっぱ使って楽しそうなので。

Wikipediaとかにもいろいろあるがとりあえずおもしろそうだったのは以下の2つかな。

StarLogo


Turtleグラフィックス用というよりは分散システムのシュミレーション環境といったほうが正しいかも。子供向けではないな。個人的には面白そう。
StarLogo TNGというGraphical Programming環境も派生版としてある。

[本家@MIT]  http://education.mit.edu/starlogo/
[日本語の情報発信ページ by fujim2] http://www.rhodonite.org/starlogo/

Dolittle


Logo風なタートルグラフィックス環境。 昔あったロゴ坊というソフトの後継。
日本語でプログラムが書けるのが特徴。

カメ1号 = タートル!作る。
カメ1号 ! 50 歩く。 カメ1号 ! 90 右回り。 カメ1号 ! 50 歩く。 カメ1号 ! 90 右回り。 カメ1号 ! 50 歩く。 カメ1号 ! 90 右回り。 カメ1号 ! 50 歩く。 カメ1号 ! 90 右回り。
こんな感じ。
日本語で書ける関係で、変数名、数値や記号、リテラルに至るまで「全角、半角、大文字小文字区別なし」という超仕様。
Appletですぐに試せるページもあるのでちょっとお試しすることもできる。
とりあえずこれを使ってみよう。

[プログラミング言語 ドリトル] http://dolittle.eplang.jp/index.php

サイトがあるのはいいのだが、とにかくこのサイト、中に何があるのかが全く分からない。
Wikiなのだけど、サイトマップ的なものがないので、いろいろあることはあるのだが到達するすべが全くない。うーむ。
幸いバイナリに使い方的なPDFがついているのでそれが頼りになる。
ていうかそれしかないとも言う。