パスワードを忘れた? アカウント作成
285321 journal

rutoの日記: Haskellの式はかっこで囲ってやると自動でインデントできる

日記 by ruto

なぜ Haskell で 1-liner っぽいコードが出来るのか、ちょっと真面目に考えた

EmacsでHaskell書いてると思った通りにインデントできなくてむきーってなるけど、そういう場合は{;}とオフサイドルールの中間の方法として括弧で囲う方法がある。
例えば

foo
  = (do
      a
      b
      c
      d)

と書くと、emacsのhaskell-modeでは一発でインデントできる。
括弧で囲ってやると構造がインデントによらずに一意になるので、インデントを間違えても変な動作をしなくなる(せいぜいコンパイルエラーになる)。
ダサいけど、;は書きたくないという人向け。

283440 journal

rutoの日記: Scala 2.8 Collections APIを訳しました

日記 by ruto

Scala 2.8ではコレクションまわりのAPIが(互換性を大幅に保ったまま)大きく変わっています。Scala 2.8のコレクションAPIはかなり洗練された設計となっていますが、多くのクラスから出来ているためscaladocやソースだけからの理解は困難です。
Scala 2.8 Collections APIは、Scalaの設計・実装者である(もちろん2.8のコレクションAPIの設計・実装もしています)Martin Odersky氏が、Programming in Scala (邦題: Scalaスケーラブルプログラミング)の共著者であるLex Spoon氏と共にScala 2.8のコレクションAPI について解説した文書です。基本的な設計から各抽象・具象クラスの解説、さらには各クラスの性能特性のまとめJavaのコレクションとの変換2.7からの移行など、Scala 2.8のコレクションについて幅広い範囲をカバーしています。
Scala 2.7についてある程度知っている人を対象としていますが、Scalaを学び始めて基本的な文法を学んだ人が読むのにも適しています。

そんなScala 2.8 Collections APIを日本語に翻訳しました。

Scala 2.8コレクションAPI

日本でのScalaの浸透に少しでも貢献できれば幸いです。

なお、ほぼ同時期にe.e d3si9nさんも翻訳しています。お互いに訳を参考にして翻訳しました。私の訳でわかりづらいところがあれば、ぜひこちらも参照してください。

おまけ: 翻訳メモ

77398 journal

rutoの日記: スクリプト言語にとって、正規言語は速い以上のメリットは無いと思う

日記 by ruto

正規表現より文脈自由文法の方が良いという意見に対する正規表現の擁護
「正規表現が手軽だから」以上が無くて、言語の表現力の話とリテラルとしての正規表現の話がごっちゃになってる気がする。この論法だと、正規表現から上位のクラスの言語用のパーサへ変換する機能を用意されたらそれでいいことになってしまう。

スクリプト言語の機能としての正規言語マッチャは、使う側としては、正規言語(+α)に限れば圧倒的に速くパースできるという以上のメリットは無いと思う。「チューリングマシンが最強」というのは確かで、パーサコンビネータとか手書き再帰下降パーサとかは0型の文法でもパースできて最強だと思う。速度以外は。

もちろん研究者としては機能が制限されてる方がいろいろ性質を保証できたり解析できたりして嬉しいけど、スクリプト言語を使う側にとってそれを生かした便利な機能って、速度とか停止性ぐらいしか今のところないんじゃないだろうか。

速いから正規言語に限るんであって、速度を犠牲にしても良いんなら上位のクラスの言語用の機能だけ用意して、正規表現からそれに変換すればいいと思う。

追記:
見直してみたら、元から正規表現対BNFの話のようです。話をごっちゃにしてたのは私の方だったようです。

43310 journal

rutoの日記: RubyでScalaの_っぽいこと。

日記 by ruto

こんなん作った。hello.rb

これは、

foo1 = procedure do foo(1, _, _) end

と書くと

foo1 = proc do |x, y| foo(1, x, y) end

とほぼ同じことになる。

途中で例外が起きたり、callccを使うと変になるはず。

あと、

procedure do 2.times do p _ end end

は1引数手続きではなく2引数手続きになって、_の値は1回目のループでは1つめの引数、2回目のループでは2つ目の引数になる。

shift/reset言いたかっただけなので、実はもっと簡単に書ける。

def procedure
  proc do |*args|
    old_index = Thread.current[:index]
    old_args = Thread.current[:args]
    Thread.current[:index] = 0
    Thread.current[:args] = args
    begin
      yield
    ensure
      Thread.current[:index] = old_index
      Thread.current[:args] = old_args
    end
  end
end

def _
  Thread.current[:index] += 1
  Thread.current[:args][Thread.current[:index] - 1]
end

これは例外には対応しているけど、やっぱりcallccに対応していない。

30626 journal

rutoの日記: Javaで、C++のクラス内typedefっぽいことをやる

日記 by ruto

『ジェネレーティブプログラミング』という本を読んでいる。といっても前半は飛ばしたし、後半もあまり読めてないんだけど。
そこで構成レポジトリというのがでてきておもしろい。

例えば行列計算ライブラリを作るとする。
行列は要素の型がfloatだったりdoubleだったり複素数だったり、行列で使うベクトルの型も行列の種類によって違ったりして、その組み合せは膨大になる。
そのため、C++ならテンプレートを使って、行列クラスは要素の型やベクトルの型を受け取るようにするとよい。
つまり、

template<class ElementType, class VectorType>
class Matrix {
  (ElementTypeやVectorTypeをここで使う)
}

みたいな感じ。
このとき、要素の型とベクトルの型を両方いちいち指定するのはめんどうなので、まとめてどこかに1つだけ書いておいて、それを参照するようにできると便利。
それが構成レポジトリと呼ばれるものである。つまり、

struct FooConfigrationRepository {
  typedef double ElementType;
  typedef FooVector<ElementType> VectorType;
}

と書いておいて、

template<class Config>
class Matrix {
  (ElementTypeの代わりにConfig::ElementTypeを使う)
}

という風にMatrixの方を書き換えておけば、FooConfigrationRepository1つを渡すだけで済むので楽だし、後で変更するときもここだけ変えればいいので楽になる。

というのが構成レポジトリのごく簡単な説明。
ただ、『ジェネレーティブプログラミング』ではC++での例は載っているけど、Javaの例は載っていない。
そもそもJavaではクラス内でtypedefできないのでC++と同じようにはできない。

しかし、JavaでもGenericsを使えば似たようなことはできる。
まず、構成レポジトリは次のように書く。

interface ConfigrationRepository<ElementType extends ElementInterface, VectorType extends VectorInterface<ElementType>> {
  VectorType createVector(int size);
  ...
}
 
class FooConfigrationRepository implements ConfigrationRepository<Double, FooVector<Double>> {
  public FooVector<Double> createVector(int size) {...}
  ...
}

それで、受け取る方は次のように書く。

class Matrix<ElementType extends ElementInterface, VectorType extends VectorInterface<ElementType>, Config extends ConfigrationRepository<ElementType, VectorType>> {
  (ElementTypeやVectorTypeを使う)
}

それで、これらのライブラリを使う場合には次のようにする。

class Main {
  public static void main(String [] args) {
    start(new FooConfigrationRepository());
  }
  <ElementType extends ElementInterface, VectorType extends VectorInterface<ElementType> Config extends ConfigrationRepository<ElementType, VectorType>> void start(Config config) {
      Matrix<ElementType, VectorType, Config> bar = new Matrix<ElementType, VectorType, Config>(config);
      ...
  }
}

つまり、例えばFoo<Double, Integer>という型を、2つの型DoubleとIntegerを要素として持つレコードとして使っている。
そこから要素を取り出すときは、<X, Y, Z extends Foo<X, Y>>という風にパターンマッチを使って取り出している。

ただ、C++に比べて記述はかなり汚なくなっていてあまり実用的ではないし、ここまで凝ったことはJavaではやらないのがJavaの流儀っぽい気がする。

# JavaのGenericsっていままで詳しく調べたことなかったので、実はもっとスマートな方法があるかもしれない。

412833 journal

rutoの日記: マリオ1において、壊れるブロックはキノコ王国住人ではなく、アイテムの出るブロックのみが住人なんじゃないだろうか。

日記 by ruto

スーパーマリオブラザーズに対するツッコみとして、レンガに変えられたキノコ王国住民を破壊するのはどうよ、ってのがよくある。

しかし、説明書には次のような記述がある

レンガに変えられたり、消されたりしたキノコを見つけて助けると、彼等からパワーをもらって、次々と変身します。

ここから考えると、壊れるブロックはただのブロックで、叩くとアイテムが出るブロックがキノコ王国住民なんじゃないだろうか。

消されたりしたキノコってのは隠しブロックのことで。

481355 journal

rutoの日記: LinuxでMX Airはどう見えるか

日記 by ruto

今までOrbit Optical使ってたんだけど、ボタンがへたってきたのでポインティングデバイスを買い替えることにした。

またOrbit Optical買ってもいいんだけど、もうちょっと冒険してみようと思って、空中マウスの一種であるMX Airを買ってみた(腕のねじれないデバイスが欲しかった)。

で、繋いでみたところ、専用ドライバの無いLinuxでもある程度は使えた。以下詳細。

  • デスク上での移動
    → 通常のマウスの動き
  • 左右ボタン
    → 左右ボタン
  • 空中での移動
    → 通常のマウスの動き
  • ホイールをゆっくり撫でる
    → ホイールイベント
  • ホイールをすばやく動かして話す
    → 連続したホイールイベント(手を離した後も発生)。音もマウスからでる。
  • ホイール上の上下ボタン
    → ホイールイベント(オートリピート有り)
  • BACKボタン
    → サイドボタン(input.hで言うところのBTN_SIDE)
  • BACKボタンを2秒以上押す
    → 空中でのカーソル移動停止
  • SELボタン
    → 左クリック(BTN_LEFT)
  • 再生/一時停止ボタン
    → 出力無し(ただし、押しながらジェスチャをすると本体から音は出る)(追記: 別デバイスファイルで、クリック時に再生/一次停止(KEY_PLAYPAUSE)イベントを出力、ジェスチャで次の曲/前の曲(KEY_NEXTSONG/KEY_PREVIOUSSONG)イベントを出力。)
  • VOLボタン
    → 出力無し(ただし、押しながらジェスチャをすると本体から音は出る)(追記: 別デバイスファイルで、クリック時にミュート(KEY_MUTE)イベントを出力、ジェスチャで音量調節(KEY_VOLUMEDOWN/KEY_VOLUMEUP)イベントを出力)

SELが左ボタンと同じイベントなのと、再生/一時停止ボタンやVOLボタンが認識されてないのが痛い。それ以外はまぁまぁ。

さらに自作ツールでevdevを調べてみたところ、以下のイベントを発生させると宣言している。

Event type 0x00  (Sync Events)
  Report  Config
Event type 0x01  (Keys or Buttons)
  Mouse Button Left  Mouse Button Right  Mouse Button Middle  Mouse Button Side  Mouse Button Extra  Mouse Button Forward  Mouse Button Back  Mouse Button Task  Unknown 0x118  Unknown 0x119  Unknown 0x11a  Unknown 0x11b  Unknown 0x11c  Unknown 0x11d  Unknown 0x11e  Unknown 0x11f
Event type 0x02  (Relative Axes)
  X  Y  Horizontal Wheel  Wheel

以下追記

音量調節ボタンなどは別のデバイスファイルに割り当てられる。それらは以下のイベントを出力すると宣言している。

Event type 0x00  (Sync Events)
  Report  Config
Event type 0x01  (Keys or Buttons)
  Mute  Volume Down  Volume Up  Pause  Stop  Props  Undo  Copy  Paste  Find  Cut  Help  Calc  Sleep  File  WWW  Mail  Bookmarks  Back  Forward  Eject CD  Next Song  Play/Pause  Previous Song  Stop CD  Record  Rewind  Config  Homepage  Refresh  Scroll UP  Scroll DOWN  Unknown 0xb5  Unknown 0xb6  Play  Fast Forward  Bass Boost  Print  Unknown 0xe7  Unknown 0xe8  Unknown 0xe9  Unknown 0xea  Unknown 0xeb  Button 0  Program  Radio  Channel Up  Channel Down
Event type 0x02  (Relative Axes)
  Horizontal Wheel
Event type 0x03  (Absolute Axes)
   Volume        value 0 minimum 1 maximum 652 fuzz 0 flat 0

同梱されているWindows用のユーティリティー(SetPoint)で設定した設定はハードウェアに保存されるわけではないらしく、Linuxでは有効にならない。ただ、前述のプログラムの出力を見ると、キーのカスタマイズはソフトウェアによる変換ではなく、ハードが直接別のイベントを出力しているのだと予想できる。おそらく、なんらかのコマンドを送るとハードウェアが別のイベントを送信するようになるのではないかと思う。

442516 journal

rutoの日記: FirefoxのRadialContext拡張の不具合への対症療法 2

日記 by ruto

Firefox用拡張でRadialContextというのがあって、これを使うと普通のコントキストメニューの代わりにドーナツ状のパイメニューがポインタの周りに出るようになる。
素晴しいのはポインタをドーナツの外に動かそうとしてもちゃんとメニューがポインタに付いてくる点で、マウスジェスチャーの感覚で使える。しかもマウスジェスチャと違ってアイコンが表示される上、ポインタを動かさないでいると説明テキストが出るので、割り当てを忘れてしまっても大丈夫。
これがあるお陰で私は他のブラウザを使えない。

だけど、けっこう前からしばらく使っていると突然メニューが動かなくなって、しかもマウスやキーボードのイベントをグラブしたままになるのでFirefoxがまともに使えなくなくなってしまう。

これじゃ使いものにならないってんで調べてみたところ、とりあえず対症療法が見付かった。
rcMenu.jsでラベルのfontWeightを設定しているところでエラーが出ていた。
設定しているところは幾つかあってその内1つでは
try {...} catch(ex) {dump("Why does setting the font weight fail sometimes?\n" + ex.toString() + "\n");}
という風に例外をキャッチしているが、その他の部分では例外をキャッチしていない。これが原因っぽい。
また、showLabelsの
this.lnode.style.lineHeight= 20*100/currentZoom+ "px";
this.lnode.style.fontSize= 8*100/currentZoom+ "pt";
の部分でも例外が起きている。
とりあえず例外が起きている部分を、try...catch...で囲むと、今のところ一応動いてる。
エラーメッセージにあるように、この例外がなぜ起きるのかは謎なので根本的な解決にはなってない。

おまけ:
application/xhtml+xmlなページでパイメニューが表示されないのは、rcIntegration.jsの
pie_context.body= pie_context.frame_doc.getElementsByTagName("BODY")[0];
というところで大文字の"BODY"を指定してるのが原因っぽい。その後に
if (!pie_context.body) {
        pie_context.body= pie_context.frame_doc.getElementsByTagName("body")[0];
}
を入れてみると表示される。

492377 journal

rutoの日記: Hotwire紹介

日記 by ruto

グラフィカルなCLI系でまた1つ。

Hotwire

  • Pythonで書かれていて、パイプラインの中はPythonオブジェクトが通る。
  • レンダラを登録することでオブジェクトの表示方法をカスタマイズできる。
  • プログラミング言語であることを目指していない。
  • 普通のコマンドも使える。端末制御にも対応。
  • 他のマシンでコマンドを実行してローカルマシンで結果を表示することも可能。

あと、類似プロジェクトのリストが参考になる。けっこうあるもんだな。

493002 journal

rutoの日記: GUIもコピペできればいいのに 1

日記 by ruto

viやEmacsを使うことは、先験的であり超越論的である

GUIエディタよりコマンドラインエディタが本質的に優れているなどという理由では、決してない。

(既存の)GUIの設定ツールによる管理の悪い点はコピペしたりできない点。個々のテキストフィールドはコピーできるけど、設定画面全体のコピペはできない。

GUIもコピペしたりファイルに保存できればいいのに。と思ったけど、「それなんてxfy?」だな。

ところで、元エントリは一般的なGUI vs CLIの話なのか、viという具体的なテキストエディタの良し悪しの話なのか、専用管理ツールによる管理 vs 汎用テキストエディタによる管理の話なのか読み取れない。

typodupeerror

最初のバージョンは常に打ち捨てられる。

読み込み中...