2013-05-09
■ [scala][macro] Scalaマクロについて少しだけ調べた
Scalaにも、Lispのような構文木マクロを入れようという動きがあるらしい。静的型言語の世界では構文木マクロがどのようになるのか興味があったので、少し調べてみた。
http://scalamacros.org というサイトがあるのだが、これを見ると既にScala本体にexperimental扱いで取り込まれているようだ。
概要についてはこのへんの資料が参考になった。
どんなものか
Scalaはコンパイル言語なので、まずマクロ本体をコンパイルしてから、マクロを使ったコードをコンパイルする、という流れになる。
それぞれのマクロは、「構文木を受け取って構文木を返す関数」として記述する。 構文木の型はc.Expr (cはContext)なのだが、Scalaは静的型付け言語なので、「どのような型の式を表す構文木か」という情報が付随している。 ので、例えば文字列リテラルの構文木ならばc.Expr[String] という型になる。
Scalaはhomoiconicな言語 (構文木がプリミティブの組み合わせで表現される言語、Lisp, Prolog, Elixir, Io, Factorなど) ではないので、 以下のように頑張って構文木を組み立てる必要がある。(例は上の記事から拝借)
Literal(Constant(new java.util.Date().toString))
…のだが、これは辛いので、reifyを使うことで簡単に構文木を生成できる。
reify{ "Compiled Time: " + date.eval }
reify自身もマクロとして定義されているらしい。引数で渡された構文木をそのまま値として返せばいいのか。なるほどねぇ (実際にはLispのunquote的な機能もあるのでもうちょっと複雑だけど)
マクロの利用例
https://github.com/pniederw/expecty というテストツールがある。このエラー表示、インパクトありますね…。
java.lang.AssertionError: person.say(word1, word2) == "pong pong" | | | | | | | ping pong false | ping pong Person(Fred,42)
このpower assertionとかいう書式自体は、Spockという Groovy用テストツールに由来する。 Groovyはどうやってこれを実現してるんだろう?と思ったのだが、プラグインでパーサ自体に手を入れられるらしい。マクロどころじゃねぇw
2013-04-17
■ [haskell][types] Haskellの型クラスの実現方法について調べてみた
型クラスの実装について調べていたら、1988年の「How to make ad-hoc polymorphism less ad hoc」という論文に行き当たった。
- http://homepages.inf.ed.ac.uk/wadler/topics/type-classes.html (How to make ad-hoc polymorphism less ad hoc) (Macだとpsファイルがそのまま開けるようです)
これによると、型クラスを使ったHaskellプログラムは、型クラスを使わない(代数的データ型のみの)プログラムに変換できるそうだ。 *1
内容は、Haskellのclass構文とinstance構文の使い方を知っている人なら、上から順に読んでいけば理解できると思います。実装の話は3章からです。 最後のConclusionでは「型クラスはbounded quantierの一種と考えることができるが〜」のような専門用語が出てきますが、そのあたりが気になる人は「型システム入門」(TAPL)を読みましょう。 *2
すごいHaskellたのしく学ぼう!(Miran Lipovaa)
型システム入門 −プログラミング言語と型の理論−(Benjamin C. Pierce)
ad-hoc polymorphismとは
1章に説明がある。length [1,2,3]とlength [1.1, 1.2, 1.3]のような形のpolymorphismでは、length自体の実装はリストの中身がIntでもFloatでも同じで、パラメータとなる型の名前が変化するだけだ。こういうものをparametric多相という。 一方で、3*3と3*3.14では、乗算演算子はIntとFloatで実装が全く違う。こういうものをad-hoc多相という。
例
この論文では、Numの例とEqの例が出てくる。Numは「掛け算や足し算の演算子を、IntでもFloatでも使えるようにしたい」、Eqは「比較演算子を、IntでもFloatでも使えるようにしたい」という話。(型クラスを使うとIntやFloatに限らず、ユーザ定義の型にも+や==を定義できる)
変換の概要
class宣言は、型が持たないといけないメソッド一覧を定義する。それに対しinstance宣言は、実際にメソッドとして振る舞う関数群を与える。なので、これを代数データ型として定義してやる。
-- 足し算関数と掛け算関数を保持するデータ型を定義 data NumDict a = NumDict (a->a->a) (a->a->a) -- Int用のメソッド群はこれ NumDInt = NumDict addInt mulInt -- Float用のメソッド群はこれ NumDFloat = NumDict addFloat mulFloat
+や*を実行するには、実際のメソッド関数が必要になる。なので、NumDictを第一引数にとる補助関数を作り、プログラム中での(+)や(*)の呼び出しをそれの呼び出しへと置き換えてやる。 プログラム中の(+)や(*)がIntを扱うのか、Floatを扱うのかは、型推論で分かっているはずなので、こういう変換ができる。
という感じ。
論文を読んでたときのメモが https://gist.github.com/yhara/5401423 にあります(あまり他の人の参考にはならないと思いますが)。
2013-04-16
■ [misc] WiMAXを自宅回線として利用する際は「機器追加オプション」の有無に注意
自宅の回線を有線LAN(ケーブルテレビ)からWiMAXに切り替えて数年経つ。今月は契約更新月*1なので、回線を再契約して端末を買い換えようかなぁ*2*3と思っていたところ、契約中のBIC WiMAXが「機種変更キャンペーン」という、無料で新品の端末をくれるキャンペーンをやっていたので、それに申し込んでみた。その代わり今後1年間の解除料が通常より上がるらしいが (それを教えてくれるあたり良心的だ)、しばらくは解約する予定はないので問題ないだろう。
で、去年UQ WiMAXからBIC WiMAXに乗り換えるに当たっていろいろハマりどころがあったので、それをメモしておく。
WiMAXはMVNOを選ぶ必要がある
WiMAXは回線とサービス事業者が分かれているため、実際の申し込みはUQ WiMAX(公式)以外にも、BIC WiMAXとか@nifty WiMAXとか、適当な会社を選んで契約することになる。 サービス内容はどこも似たような感じで、「年間パスポート」みたいな名前の1年縛り・月額3880円のプランを選ぶのが基本になる。 だが、「機器追加オプションが提供されているかどうか」という点が事業者によって異なり、そこが人によってはクリティカルな違いになるので、以下で説明する。
「自宅でも外出先でも使いたい」場合
自宅のネット環境を固定回線からWiMAXにした主な理由は、「自宅でも外出先でもネットできる環境」をつくるのにWiMAXを使うのが一番安上がりだったからだ。 (今だとケータイでテザリングできたりするのでまた違うかも知れないが…。*4)
それを実現する方法はいくつかある。
1. 一つの端末を持ち歩く
まず最も単純な方法。1台のWiMAXルータをカバンに入れておき、家に帰ったら充電器に繋いで、家用回線として使う。
外でネットを使うことが毎日あるようなケースなら、これで問題ないだろう。1台持ちなので、「機器追加オプション」の有無も気にする必要はない。
2. 自宅と外出先で同時にネットしたい場合
家族がいるとか、自宅サーバを動かしているとかで、自宅の回線と外出時のネット使用を「同時に」行いたい場合は、回線を2つ契約する必要がある。(もちろんWiMAX端末も2つ必要) 事業者によっては「ファミ得パック」のようなオプションを選ぶと、普通に2回線契約するよりは割安になる。
3. 自宅用と外出先用の2端末でネットしたいが、同時にどちらかだけで良い場合
外でネットすることがあまり頻繁ではない場合、WiMAXルータを充電したり取り外したりするのが面倒なので、家用の端末と外用の端末を別に持ちたいことがある。 *5
このように、「2台持ちしたいが、同時には使わない」場合、事業者によっては「機器追加オプション」のような名前で、月額200円で2台目の端末を登録できることがある。 2011年の情報だが、kakaku.comの以下のスレッドが詳しい。
要約すると、
- 機器追加オプションがあると、月額200円とかで2台目の端末を登録できる
- 機器追加オプションがある事業者と、ない事業者がある (ので、WiMAX端末を2台持ちしたい人は注意)
- 機器追加オプションがあっても、初期費用として105円かかる事業者とそうでない事業者がある (ので、使う月だけオプションを有効化したい人は注意)
- 機器追加オプションがあっても、優先度設定 (2つの端末が同時にネットに繋ごうとしたとき、どちらが優先されるか設定できる機能) がない事業者がある (ので、家と外で使いたい人は外出前に家用端末の電源をオフにする必要がある??未確認)
ということのようだ。
で、
このような機器接続優先設定ができるのが私が知る限りヨドバシ、ビック、UQです。 そして機器追加オプションで登録料を取られないのはビックとUQです。つまり月額200円で使わない月は解除が容易です。 (中略) 機器追加はダイワボウ情報システムでもできますね。
と書かれている。
一応、2013年現在も有効かどうか調べてみた:
- http://www.uqwimax.jp/service/price/option04.html (月額200円、登録料0円、優先度設定あり)
- http://www.diswimax.jp/rn/price/option1.html (月額200円、登録料105円、優先度設定あり)
- http://setsuzoku.nifty.com/wimax/news/change_option.htm (月額210円、登録料0円(使わない月は自動的に課金が外れるらしい)、優先度設定不明)
- http://www.bic-ws.net/info/option.html (月額200円、登録料なし、優先度設定あり)
- http://www.kualnet.jp/faq/sub4.html (月額200円、登録料なし、優先度設定なし (後から繋ごうとした方が割り込むらしい))
- http://www.yodobashi.com/ec/support/service/wimax/agreement/ (月額200円、登録料105円、優先度設定あり)
(疲れたのでここまで。他にもあるかも知れない)
ということで、家用と外用の2台持ちを考えている人は、「機器追加オプションの有無」「登録料の有無」「優先度設定の有無」に注意しましょう。
おわりに
サービス内容が選べるのはいいけれど、こういう微妙な内容で差別化されると辛いですね…。
2013-04-15
■ [ruby] whytheluckystiff.net が微妙に更新される
via @yukihiro_matz
最新の_why情報です
Public Print Queue SPOOL/DESOLEE 2013-01-06T08:21Z SPOOL/TRUMPETS 2013-04-12T19:43Z SPOOL/SOLICIT 2013-04-12T20:10Z SPOOL/CAPRICE 2013-04-12T22:06Z SPOOL/HOMEWORK 2013-04-12T23:19Z
- HN
- このページのコンテンツと一致するgithubリポジトリ
- その中の印刷データっぽいものの復元画像
_why先生OCaml始めたんでしょうか…?
2013-04-14
■ [ruby][event] 頭のおかしいRubyプログラムのコンテストが開催されるぞ (5/18〆切)
5月末のRubyKaigiに合わせて、IOCCCのRuby版的なコンテストが開催されるようです。
「ようです」っていうか僕も審査員なんですが…。しかし他の審査員が強力すぎるので、どの方向からどんな投稿が来ても大丈夫な安心感があります。
mameさんのスライドや、本家にIOCCC入賞した人の記事とか見ると雰囲気が掴めるかもしれません。
なお、要件は「このプログラム、こんな風に動くんだ!」ということですので、本家IOCCC同様、たとえばワンライナでのエントリもアリです。(just another perl hackerみたいなね)
int _;main(O,l,o)char**l,**o;{_++>>9||main(1&(o?(int)o:O)|O*2,l,putchar(_%32?atoi(1[l])>>(7&O<<!o>>!o+29)&32<_|_==16?35:32:10)%10);}
CになくてRubyにあるものっていろいろ考えられるので(オブジェクト、組み込み・添付ライブラリ、RubyGems、多彩orマイナーな文法群などなど…)、いろいろなアプローチが考えられそうですね。
みなさまの創造性・技術力・(and/or)エンターテイメント性にあふれた投稿をお待ちしております。 *1
*1 審査は作者名を伏せた状態で行われるため、審査員陣も投稿が許されています。投稿物のremarks.markdownの方には自分の名前を書かないように注意してください
