appengineの古いドキュメントにいちいち飛ばされるのがイラッとするので
これを使ってます。便利。accept-languageを動的に変えられると
もっといいんですけど、NSAPIとか使わないと無理じゃないですかね。
URL Patterns
https://chrome.google.com/extensions/detail/aeenbkfcmogkgbkkibbjpmkegldfgapl
設定はこんな感じ
2010年3月13日土曜日
2010年2月26日金曜日
Chrome extensions | appengine-easy-monitor
http://bit.ly/aD9QuP
devfest_jpのQuizのため、適当に作りました><
前日にappengineの大規模な障害とかあったので、
こういうのあってもいいかな?
statusページを10分ごとにjqueryで適当にスクレイピングして
当日のステータスに応じたアイコンを出すようにしてみました。
詳細データはアイコンにリンクしています。
devfest_jpのQuizのため、適当に作りました><
前日にappengineの大規模な障害とかあったので、
こういうのあってもいいかな?
statusページを10分ごとにjqueryで適当にスクレイピングして
当日のステータスに応じたアイコンを出すようにしてみました。
詳細データはアイコンにリンクしています。
2010年2月22日月曜日
Scalaでappengineのapiproxy hookを作る
Hackathonから帰ったあと、@marblejenkaさんがappengineのlower levelなネタを
作ってるのを聞いてたので、appengineのライブラリ以外をscalaで作ったらどうなるんだろ、
と思ってApiProxyのHookを書いてみた。
簡単だろ、と思ってたら意外なところでハマってしまった。
最初こんな感じで書いた。
アウト。
コンパイル時に型が違いますエラーをdelegate.makeXXX,logの呼び出しで喰らう。
Delegateが共変ではないってことになるのかな。
渡すdelegateはApiProxy.getDelegateで取得することを想定しているのだけど、
これ仮型引数が分からない。scalaのエラーによると、<? extends Environment>
ってのは分かってるんだけど、型として<? extends Environment>ってのは用意できない。
まあJavaで同じことしてもエラーになるんだけど、ApiProxy.getDelegateはraw type
、イレイジャ通って戻ってくるので、キャストして呼べるんだよね。
1日悩んで、どうしたらいいんだろと考えてひらめいた。
これならOK。
コンストラクタの引数を元に仮型引数を決定できるので渡されたdelegateを
元に推論すればいいじゃん!とひらめいたのでした。
・直接このHookのmakeSyncCallは呼び出せない
・Hook内でEnvironmentをいじれない
けれども。
多分Javaだとタイプセーフにはできないような気がする。
作ってるのを聞いてたので、appengineのライブラリ以外をscalaで作ったらどうなるんだろ、
と思ってApiProxyのHookを書いてみた。
簡単だろ、と思ってたら意外なところでハマってしまった。
最初こんな感じで書いた。
01 | class Hook D elegate( val d elegate : D elegate[ _ < : Environemnt]) |
02 | extends D elegate[Environment] { |
03 |
04 | def makeSyncCall(e : Environment, |
05 | s : String,m : String,r : Array[Byte]) : Array[Byte] = { |
06 | d elegate.makeSyncCall(e,s,m,r) |
07 | } |
08 |
09 | def makeAsyncCall(e : Environment, |
10 | s : String,m : String,r : Array[Byte], |
11 | c : ApiConfig) : Future[Array[Byte]] = { |
12 | d elegate.makeAsyncCall(e,s,m,r,c) |
13 | } |
14 |
15 | def log(e : Environment,r : LogRecor d ) = { |
16 | d elegate.log(e,r) |
17 | } |
18 |
19 | } |
アウト。
コンパイル時に型が違いますエラーをdelegate.makeXXX,logの呼び出しで喰らう。
Delegateが共変ではないってことになるのかな。
渡すdelegateはApiProxy.getDelegateで取得することを想定しているのだけど、
これ仮型引数が分からない。scalaのエラーによると、<? extends Environment>
ってのは分かってるんだけど、型として<? extends Environment>ってのは用意できない。
まあJavaで同じことしてもエラーになるんだけど、ApiProxy.getDelegateはraw type
、イレイジャ通って戻ってくるので、キャストして呼べるんだよね。
1日悩んで、どうしたらいいんだろと考えてひらめいた。
01 | class Hook D elegate[E < : Environment]( val d elegate : D elegate[E]) |
02 | extends D elegate[E] { |
03 |
04 | def makeSyncCall(e : E, |
05 | s : String,m : String,r : Array[Byte]) : Array[Byte] = { |
06 | d elegate.makeSyncCall(e,s,m,r) |
07 | } |
08 |
09 | def makeAsyncCall(e : E,s : String,m : String,r : Array[Byte], |
10 | c : ApiConfig) : Future[Array[Byte]] = { |
11 | d elegate.makeAsyncCall(e,s,m,r,c) |
12 | } |
13 |
14 | def log(e : E,r : LogRecor d ) = { |
15 | d elegate.log(e,r) |
16 | } |
17 |
18 | } |
これならOK。
コンストラクタの引数を元に仮型引数を決定できるので渡されたdelegateを
元に推論すればいいじゃん!とひらめいたのでした。
・直接このHookのmakeSyncCallは呼び出せない
・Hook内でEnvironmentをいじれない
けれども。
多分Javaだとタイプセーフにはできないような気がする。
Scala Hackathon #2に参加した
2/20に開催された@yuroyoroさん主催のscala hackathon #2に参加した。
場所はOracle青山センター、とても綺麗な施設で、かっこよかった。
で、今回自分が何をしていたかというと、
・既存blogのatomからbloggerにインポートするappengineアプリをscala化する
ってのをテーマにやろうと思ってたんだけど、思った以上に基礎ができていない
ことが判明したので
・swingアプリをかっこよくscalaで短く書く
にした。
Javaでの繰り返し、swingのイベントハンドラ処理ってのは冗長な記述が多い
⇒scalaってLLだべ?
⇒かっこよくJavaScriptとかそういうのみたいにワンライナーで書く
⇒モテる
そういう動機。
ただ、swing周り、scalaでは全てのswingコンポーネントが
ラップされているわけでは無いようなので、自分で書くべきところが
多そうだなー、という印象。イベントハンドラは取り合えず後回しにして
繰り返しをかっこよく書くことに専念した。
たとえば、テーマのクラス、Javaで書くとこんな感じ。
getDefaultsをオーバーライドして、テーマのデフォルト値を上書きする。
冗長なのは、forとinstanceofでのエントリのフィルタリング。 これをscalaでもっと短くしていきたい。
主要な部分は短くなったけど、valへの代入と値を返す部分が残る。
Scala特有の書き方はscalaの型で無いとダメなところが一番の理由かな。
implicit conversionを勉強すると省略する方法が分かるのかもしれない。
あとはコレクションの扱いが色々あって、書き方が一通りでは無いから
もう少しかっこいいのが書けそうな気がする。
ハマッたこと。
1.mapのエントリについて
UIDefaultsはHashtableインターフェースを実装しているので、エントリは
Entryであらわせるんだけども、これがscalaだとどのように帰ってくるか
最初分からなかった。コンパイルエラーでは (k,v) のような表現の型なのは
分かるんだけど、検索キーワードになるような言葉を付けてくれよとは思った。
調べた結果、Tupleと言うみたい。
アクセスするには、entry._1とかentry._2とか書くとらしいんだけど、
@yuroyoroさんのアドバイスで{case (k,v) => } というようなPartial Functionを
書くと_1とか_2とか書かなくてもいいよ!と聞いて、
ん、もしかしたら、forでも(k,v)?と書いてみたら受けることができた。
※そもそもPartial Functionってなんぞやと思って調べたところ、
「引数と戻り値に対して仮型引数を定義する関数の型」っぽい。
caseの一つ一つをPartial Functionとして定義できるってことが分かった。
2.条件分岐、型のマッチ
上記ではif文の中のisInstanceOfでフォントかどうか評価しているんだけど、
isInstanceOfってかっこ悪くね?⇒caseクラスいいんじゃね?⇒
でも結局この(k,v)ってペアのvの評価を一発で出来ないとかっこ悪くね?
どう書くんだろ?
ここまででHackathonが終わってしまった。
10:00~19:00までやってこれだけかよ!
とりあえず、今回書いたコードでscalaのかっこいいところ
1.forの中にfilterを書ける。
2.forの処理結果をコレクションで戻せる。
@yuroyoroさん、ほんと、初心者の質問してしまって申し訳なかったです。
さすがにそろそろコップ本を買って勉強します。
※コードと格闘しててLTはほぼスルー気味でした。ごめんなさい。
場所はOracle青山センター、とても綺麗な施設で、かっこよかった。
で、今回自分が何をしていたかというと、
・既存blogのatomからbloggerにインポートするappengineアプリをscala化する
ってのをテーマにやろうと思ってたんだけど、思った以上に基礎ができていない
ことが判明したので
・swingアプリをかっこよくscalaで短く書く
にした。
Javaでの繰り返し、swingのイベントハンドラ処理ってのは冗長な記述が多い
⇒scalaってLLだべ?
⇒かっこよくJavaScriptとかそういうのみたいにワンライナーで書く
⇒モテる
そういう動機。
ただ、swing周り、scalaでは全てのswingコンポーネントが
ラップされているわけでは無いようなので、自分で書くべきところが
多そうだなー、という印象。イベントハンドラは取り合えず後回しにして
繰り返しをかっこよく書くことに専念した。
たとえば、テーマのクラス、Javaで書くとこんな感じ。
getDefaultsをオーバーライドして、テーマのデフォルト値を上書きする。
01 | public class MyTheme extends NimbusLookAndFeel { |
02 | @Override |
03 | public UIDefaults getDefaults() { |
04 | UIDefaults table = super .getDefaults(); |
05 | for (Entry<Object,Object> entry:table.entrySet()) { |
06 | if (entry.getValue() instanceof Font) { |
07 | table.put(entry.getKey(), new Font( "MS UI Gothic" ,Font.PLAIN, 12 )); |
08 | } |
09 | } |
10 | return table; |
11 | } |
12 | } |
冗長なのは、forとinstanceofでのエントリのフィルタリング。 これをscalaでもっと短くしていきたい。
1 | class MyTheme(font : Font) extends NimbusLookAn d Feel { |
2 | override def get D efaults : UI D efaults = { |
3 | val d efaults = super .get D efaults |
4 | d efaults++ = ( for ((k,v) <- d efaults if v.isInstanceOf[Font] ) yield (k,font)) |
5 | d efaults |
6 | } |
7 | } |
主要な部分は短くなったけど、valへの代入と値を返す部分が残る。
Scala特有の書き方はscalaの型で無いとダメなところが一番の理由かな。
implicit conversionを勉強すると省略する方法が分かるのかもしれない。
あとはコレクションの扱いが色々あって、書き方が一通りでは無いから
もう少しかっこいいのが書けそうな気がする。
ハマッたこと。
1.mapのエントリについて
UIDefaultsはHashtableインターフェースを実装しているので、エントリは
Entry
最初分からなかった。コンパイルエラーでは (k,v) のような表現の型なのは
分かるんだけど、検索キーワードになるような言葉を付けてくれよとは思った。
調べた結果、Tupleと言うみたい。
アクセスするには、entry._1とかentry._2とか書くとらしいんだけど、
@yuroyoroさんのアドバイスで{case (k,v) => } というようなPartial Functionを
書くと_1とか_2とか書かなくてもいいよ!と聞いて、
ん、もしかしたら、forでも(k,v)?と書いてみたら受けることができた。
※そもそもPartial Functionってなんぞやと思って調べたところ、
「引数と戻り値に対して仮型引数を定義する関数の型」っぽい。
caseの一つ一つをPartial Functionとして定義できるってことが分かった。
2.条件分岐、型のマッチ
上記ではif文の中のisInstanceOfでフォントかどうか評価しているんだけど、
isInstanceOfってかっこ悪くね?⇒caseクラスいいんじゃね?⇒
でも結局この(k,v)ってペアのvの評価を一発で出来ないとかっこ悪くね?
どう書くんだろ?
ここまででHackathonが終わってしまった。
10:00~19:00までやってこれだけかよ!
とりあえず、今回書いたコードでscalaのかっこいいところ
1.forの中にfilterを書ける。
2.forの処理結果をコレクションで戻せる。
@yuroyoroさん、ほんと、初心者の質問してしまって申し訳なかったです。
さすがにそろそろコップ本を買って勉強します。
※コードと格闘しててLTはほぼスルー気味でした。ごめんなさい。
登録:
投稿 (Atom)