このページの記事一覧
● 2012年6月30日土曜日 - GmailをIMAP経由でThunderbirdでつかう
● 2012年6月29日金曜日 - [Scala] 条件付きFor文
● 2012年6月27日水曜日 - Bloggerのデザインのカスタマイズ
● 2012年6月26日火曜日 - [Scala] 拡張for文
● 2012年6月25日月曜日 - [Scala] For文あれこれ
● 2012年6月24日日曜日 - Scalaは関数言語

2012年6月30日土曜日

GmailをIMAP経由でThunderbirdでつかう

Gmailのメールが増えてきて、Webアクセスだと面倒になってきたのでIMAP経由でThunderbirdで使えるようにしてみる。

設定


設定方法はGmailのヘルプで検索できるので、とりあえずその通りに設定する。
Gmail側は既にIMAPが有効になっているので、Thunderbirdの設定をする。

Thinderbirdのほうもアカウントの追加でGmailのアドレスとパスワードを入れるだけで、
自動的にサーバーのアドレスなどIMAPの設定を取得して設定してくれる親切仕様。
で無事完了。
Gmail側のヘルプには、「送信済みはローカルに保存」とか「削除済みメールはGmailに保存するな、さもないと削除時にすべてのメールが削除される」など恐ろしいことが書いてあるので一応その通りに設定する。

使ってみる

ラベルの扱い


GmailのラベルはThunderbirdのIMAPフォルダとして表現されている。ラベルはネスト構造を持てるがそれもフォルダの階層構造扱いになる。
Gmailのラベルは1通のメールについて複数付与されている。複数付与されているメッセージはThunderbirdから見ると複数のフォルダにメッセージが存在していることになる。Thunderbird側から複数のラベル付けに相当する操作をするにはメッセージをコピーすることになる。これをGmail側から見ると確かに複数のラベルが付与されたことがわかる。Gmailは1通のメッセージに他にラベルがついているか一目でわかるのがいい。
Thnderbird側からは同一フォルダへのコピーはできないようだ。


ラベルの削除


Thunderbirdから特定のラベルを削除するには、対応するフォルダからすでにラベルが付与されているフォルダか「すべてのメール」フォルダに移動すればOK。各ラベルのフォルダから「すべてのメール」フォルダへの移動をすればラベルなしにすることができる。
上で書いたようにGmailでは1通のメッセージにどのラベルがついているかが一目でわかるが、Thunderbirdでは他にどのフォルダにあるのかが分からないのが難点。

スター


あまり使っていないのだけど一応確認。Thunderbirdでのスター操作はGmailに反映される。Thundebirdでスターを付与すればGmailでもスターが付くし、削除すればGmailでも消える。
一方Gmail上でのスター操作はThunderbirdでは反映されない。GmailでスターをつけてもThunderbirdではつかない。またThunderbirdで付与したスターをGmailで削除すればGmailでは消えるがThunderbirdではついたままになる。???
Gmail側でもともとスターをつけて、かつ新たなラベルを付与するとThunderbirdで見てもスターが付与される。つまり最初にThunderbirdのローカルに取り込まれた場合にはGmailのスター設定は参照されるが、一度取り込まれたスターはThunderbirdの設定が使われてしまうということのようだ。

Thinderbirdではスターは同一のメッセージでも各フォルダ内ごとに違う設定を与えることができる。一方でGmailではひとつのメッセージであればスターの設定は一つだけなので、このあたりの仕様の違いが同期動作にも表れているのだろう。

と思ったが、同期する場合もあるみたい。動きが今一つ良く解らない。
一つ確かなのは、GMmailでスターをつければThunderbirdでは「スター付き」フォルダには出現するし、Thunderbirdで「スター付き」フォルダに移動すればGmailでもスターが付く。ThunderbirdではGmailのスター操作はフォルダ操作だと思っておいて、Thunderbirdのスター表示は(Gmail同期に関しては)あてにしないほうがよさそうだ。

重要

基本的にThunderbird上では「重要」フォルダに出現するか否かの意味しか持たない。単体のメッセージ何かのフラグが付くわけではない。

「重要」でないものをThunderbirdで「重要フォルダ」にコピーした場合は、Gmail側では「Googleがさまざまな理由から判断しました」という謎な根拠根拠になる。一度Gmail側で重要と判断したものから重要フラグを外したものについては、Thunderbirdで重要化すると、前の理由が復活するみたい。Thunderbirdでの操作は「あなたが重要マークを付けました」の対象にはならないようだ。




2012年6月29日金曜日

[Scala] 条件付きFor文

単純に繰り返すだけではなくいろいろな機能があるので、それらも見てみよう。
今回は条件付きFor文。

for文に条件を指定することで適用対象をフィルタすることができる。
val a = Array(1, 2, 3, 4);
for (i: Int <- a if i % 2 == 0) print(i);
実行結果は、
24
この機能はこんな風にもかける。
val a = Array(1, 2, 3, 4);
a.withFilter((i: Int) => i % 2 == 0).foreach(i => print(i))
これだけを見ると、withFilter()でフィルタされたArrayが返ってきて、 それにforeachをしているように見えるがちょっと違う。
続けないでちゃんと書くと、
val a = Array(1, 2, 3, 4);
val filtered : FilterMonadic[Int, Array[Int]] 
    = a.withFilter((i: Int) => i % 2 == 0);
filtered.foreach((i: Int) => print(i))
こんな感じ。
実際に、a.withFilter() の結果として帰ってきているのは、
print (filtered.getClass());
で見ると、scala.collection.TraversableLike$WithFilter であることがわかる。

ちなみに、TraversableLike$WithFilter#foreach の実装を見ると、
def foreach[U](f: A => U): Unit =
  for (x <- self)
    if (p(x)) f(x)
となっている。

つまり、withFilter()で帰ってきているのはデータ(Array)とフィルタ条件を持ったObjectで、そのforeach()の中で条件付きfor文を実行しているということになる。

結論: 最初から、条件付きfor文を使えばいいじゃん。


foreach構文を使うためには対象のオブジェクトは
  def foreach[U](f: A => U): Unit 
メソッドを実装する必要があった。
foreach - if 構文を使うためには、
def withFilter(p: A => Boolean): FilterMonadic[A, Repr]
を実装する必要がある。
object ForIfSample {
  def main(args: Array[String]) {
    val array : Array[Int] = Array[Int](1,2);
    val fe = new ForEachIfable[Int, Array[Int]](array);
    for (i: Int <- fe if i % 2 == 0) print(i);
  }
}

class ForEachIfable[A, Repr <: Array[A] ](col: Repr) {
  self=>;
  def repr: Repr = col;
  
  def foreach[U](f: A => U): Unit = {
    println("Here is ForEachIfable#foreach");
    for (x : A <- repr)  print(x);
  }

  def withFilter(p: A => Boolean): FilterMonadic[A, Repr] = {
    println("Here is ForEachIfable#withFilter");
    new WithFilter(p);  
  }
  
  // 以下のWithFilterクラスはTraversable.WithFilterと同じ。
  
  class WithFilter(p: A => Boolean) extends FilterMonadic[A, Repr] {

    def map[B, That](f: A => B)
               (implicit bf: CanBuildFrom[Repr, B, That]): That = {
      val b = bf(repr)
      for (x <- self) if (p(x)) b += f(x)
      b.result
    }
    def flatMap[B, That](f: A => GenTraversableOnce[B])
               (implicit bf: CanBuildFrom[Repr, B, That]): That = {
      val b = bf(repr)
      for (x <- self)
        if (p(x)) b ++= f(x).seq
      b.result
    }
    
    def foreach[U](f: A => U): Unit=
        for (x : A <- self) if (p(x)) f(x)
        
    def withFilter(q: A => Boolean): WithFilter =
        new WithFilter(x => p(x) && q(x))  
  }
}
withFilter()が返すFilterMonadicの実装はTraversable.WithFilterクラスの実装をそのまま使っている。 そのため、ForEachIfableがやや無理やりになっている。
実行結果:
Here is ForEachIfable#withFilter
Here is ForEachIfable#foreach
12
確かに、ForEachIfable#foreach、withFilterが実行されていることがわかる。

2012年6月27日水曜日

Bloggerのデザインのカスタマイズ

Bloggerはレイアウトがいろいろ選択できたり、ガジェットを配置できたりしてなかなか便利なのだが、いかんせん本文のカスタマイズ要素が少ない。

ここはいろいろコードを書くことが多くなりそうなのだが、コードを書くのに適した装飾がデフォルトではないので自分で用意するしかなかったので、忘れないうちにメモっておこう。

2012年6月26日火曜日

[Scala] 拡張for文

Scalaの拡張For文はこんな感じだった。

val a : Array[String] = Array("x", "y", "z");
for (s: String <- a) print(s);

この構文は scala.collection.IterableLike インターフェース(Scale的にはtraitと呼ぶ)の
foreach[U](f: A => U): Unit
を呼び出すことで実現されている。

実際には、IterableLike traitを実装しなくても、
単に、foreach[U](f: A => U): Unitが実装されていれば拡張for文を使用できる。

手抜きだけれどもこんな感じになる。

object ForSample {
  def main(args: Array[String]) {
    val fe : ForEachable = new ForEachable();
    for (i: Int <- fe) print(i);
  }
}
class ForEachable {
  def foreach[U](f: Int => U): Unit = {
    f(1);
    f(2);
  }
}
実行すると
12

胡散臭すぎる。
for文ぽく書いてはあるが、結局対象オブジェクトのforeachを呼び出すための構文のようだ。

留意するべきは、一見、対象のオブジェクトから値を取り出してfor文本体を実行しているように見えるが、実際にはfor文本体の実行部をどのように使うかもすべて対象のオブジェクト側にゆだねられている。
全く使ってくれないかもしれないし、2回づつ呼ばれるかもしれない。

object ForSample {
  def main(args: Array[String]) {
    val fe : ForEachable = new ForEachable();
    for (i: Int <- fe) print(i);
  }
}
class ForEachable {
  def foreach[U](f: Int => U): Unit = {
    f(1); f(1);
    f(2); f(2);
  }
}
実行結果:
1122

Javaチックな構文に騙されてはいけない。

2012年6月25日月曜日

[Scala] For文あれこれ

For文の書き方についてのメモその1
まずは基本形
for (i <- 1 to 5) print("*")
変数の型宣言もちゃんと書くとこんな感じ。
for (i: Int <- 1 to 5) print("*")
わざわざ <- なんて持ち出さないで普通に = で書かせてくれればいいのに。
(追記:実は、Range オブジェクトだった。 → 数値指定のfor文について

オブジェクトのループはこう。
val a = Array("x", "y", "z");
for (s: String <- a) print(s);
foreach文を使うとこんな感じになる。
Scala的にはこっちなのだろうか。
val a = Array("x", "y", "z");
for (s: String <- a) print(s);

a.foreach((s:String) => print(s));
a.foreach(s => print(s));
a.foreach(print(_));
a.foreach(print);
上から、

  • ちゃんと書いた場合
  • 変数の型を省略した場合
  • 匿名変数を使った場合
  • 変数も省略した場合

4番目あたりになるとわかっていないと意味不明なのでよほど自明な場合以外はあまり使いたくない。基本的にScalaは省略記法がたくさんあるので手を抜こうと思えばどんどん抜ける。
自分で書いたコードを自分で使うだけならいいけど、Teamで使う場合には、それなりにCoding Ruleをきちんと整備しないと訳が分からなくなりそう。
ある程度までは可読性、生産性ともに上がると思うが、度を過ぎた省略は個人的には好きではない。

foreachの引数は関数なので本体部分が複文にもなる。
その場合はこんな感じに。

a.foreach((s:String) => { val ss = s + "*"; print(ss) })
あまり長くなると見にくくなるのでやっぱり拡張For文形式が好きかも。

2012年6月24日日曜日

Scalaは関数言語

Bloggerを使ってみるついでにいろいろとメモ代わりに書いていくことにする。
とりあえず話題のScalaを触ってみたメモをいろいろ。

関数型言語ということなのでまずはそのあたりから。

object FuncSample {
  def main(args: Array[String]) {
    val func1 = sum _;
    println(func1(1,2));
  }
  def sum(val1: Int, val2: Int) : Int = {
    val1 + val2;
  }
}

インスタンスを作れるクラスはJava同様 classで定義するのだが、
Javaでいうところのstaticな関数はobjectの中に定義する。
メソッドを定義する際には、「{」の前に=をつけるみたいだが、戻り値のないものは省略できる。

定義した関数を「関数として」参照する場合には関数名に「_」をつける。
でそれを変数に代入して呼び出すことができる。

もちろん実行結果は、
3
上の例で
var func1 = sum _;
の部分は、変数の型が省略されている。
省略しないでちゃんと書くなら、
var func1 : (Int,Int) => Int = sum _;
となる。
関数の型を記述する場合には、
「(変数の型のリスト) => 戻り値の型」
と書く。

インスタンスメソッドを関数として参照する場合にはこんな感じ。
object FuncSample {
  def main(args: Array[String]) {
    val fs: FuncSample = new FuncSample;
    val func1 : (Int,Int) => Int = fs.sum _;
    println(func1(1,2));
  }
}

class FuncSample {
  def sum(val1: Int, val2: Int) : Int = {
    val1 + val2;
  }
}

ふむ。