型レベル数値リテラルを使って型レベルFizzBuzz

型レベルFizzBuzz(及び、type familyにおけるガードの書き方) - claustrophobiaを見て自分も型レベルFizzBuzz書いてみました。 GHC 7.8以降で動作します。

Natを受け取るとFBkindを持つ型を返すFizzBuzz型族と、FBに対するsingletonになるSFB型を定義して、 あとは型からsingletonを生成してそれをprintしています。

SNumberT 1
SNumberT 2
SFizzT
SNumberT 4
SBuzzT
SFizzT
SNumberT 7
SNumberT 8
SFizzT
SBuzzT
SNumberT 11
SFizzT
SNumberT 13
SNumberT 14
SFizzBuzzT
SNumberT 16

TypeScript 0.95でコンパイルできないジェネリックメソッドのコード

0.91ではコンパイルできた以下のコードが0.95ではコンパイルできなくなっている。バグ?

interface IFoo {
    f<T>(): T;
}   

class Foo implements IFoo {
    f<T>(): T {
        return null;
    }
}   

エラーメッセージ:

/Users/emon/Desktop/test.ts(5,7): error TS2137: Class Foo declares interface IFoo but does not implement it:
        Types of property 'f' of types 'Foo' and 'IFoo' are incompatible:
                Call signatures of types '<T>() => T' and '<T>() => T' are incompatible.

追記:Issuesに上がってた。

Interface declaration with generics not working in TypeScript 0.9.5

PDOにInterface欲しい

PHPの色々なフレームワークでDatabase Driverのラッパーが量産されているのが不毛に思った。 ここに共通化されたインターフェイスがあればフレームワークの違いを気にせず色々できるのになと。

そこで、PSR-3のLoggerのように標準化できないのかなと思って調べてみると、DoctrineのDBALが目に付いた。

ソースを読んでみると、DBALのConnectionインターフェイスPDOのサブセットになっている。 そうすると、PDOに対する実装であるPDOConnectionConnectionに対して実装を宣言するだけで済むわけだ。

PDOインターフェイスとして定義することで、PDOの機能をそのまま同じインターフェイスで使うことができるし、PDOを使う時には不要な抽象化レイヤーを挟まないのでシンプルでいいなと。 PDOは事実上の標準なので多くの場合これで必要十分だと思う。

しかしながら、DBALにはクエリビルダーなど不要な機能も含まれているしdoctrin/commonへの依存もある。Connection部分だけ抜きだしたpackageがあればいいのだけど、今の所ないようだった。

ということでPDOのサブセットとしてのインターフェイスだけを提供するcomposerのpackageを作りました。

https://github.com/emonkak/pdo-interface

VimScriptでIteratorを作ってメソッドチェインで処理する

業務でPHPを使っていてarray系の関数の酷さに耐えかねて作ってしまったUnderbar.phpですが、 VimScriptでもIteratorを作ってメソッドチェインで処理したくなってきますね!

ということで書きました。特に実用性はありません。

Opera 15のショートカットキーカスタマイズ

/Applications/Opera.app/Contents/Versions/15.0.1147.132/Opera Framework.framework/Resources/opera.pakにデフォルト設定のJSONが入っていたので、これを参考にProfileディレクトリのPreferencesを書き換えれば色々できそう。 nストロークキーをマッピングできるかどうかは不明。 あとActionの連結ができればこれはもう最強伝説だね!

まあどうせまたLinux版は1年以上放置されそうだけど……。

"Keybindings": {
  "Settings": { "AdvancedEnabled": false },
  "Basic": {
    "AccessKeyToggle": ["Esc+Shift"],
    "AddBlankTab": ["Ctrl+T","Command+T"],
    "AddToBookmarks": ["Command+Shift+D","Command+D"],
    "Back": ["Command+Left"],
    "Bookmarks": ["Command+Shift+B", "Command+B"],
    "CloseActiveTab": ["Command+W", "Ctrl+F4"],
    "ClosePrivateWindow": ["Ctrl+Shift+Q"],
    "CloseWindow": ["Command+Shift+W"],
    "Copy": ["Command+C"],
    "Cut": ["Command+X"],
    "CycleBackwardInActivationList": ["Ctrl+F2"],
    "CycleForwardInActivationList": ["Ctrl+F1"],
    "Delete": ["Del"],
    "DevTools": ["Command+Alt+I"],
    "DevToolsConsole": ["Command+Alt+J"],
    "DevToolsInspect": ["Command+Alt+C"],
    "EditProperties" : ["Command+i"],
    "ErrorConsole": ["Command+Shift+O"],
    "Exit": ["Command+Q"],
    "Extension": ["Command+Shift+E"],
    "Find": ["Command+F"],
    "FindInline": ["OemPeriod","OemComma"],
    "FindNext": ["Command+G"],
    "FindPrevious": ["Command+Shift+G"],
    "FitToWidth" : ["F11+Ctrl"],
    "FocusAddressbar" : ["Command+L","Command+E","Ctrl+F5"],
    "FocusNextWidget": ["Tab"],
    "FocusPage" : ["Ctrl+F6"],
    "ForceReload": ["Shift+F5","Command+Alt+R"],
    "Forward": ["Shift+Backspace","Alt+Right","Command+Right"],
    "GoToEnd": ["End","Ctrl+End"],
    "GoToPage" : ["F2"],
    "GoToSpeedDial_1" : ["Command+1"],
    "GoToSpeedDial_2" : ["Command+2"],
    "GoToSpeedDial_3" : ["Command+3"],
    "GoToSpeedDial_4" : ["Command+4"],
    "GoToSpeedDial_5" : ["Command+5"],
    "GoToSpeedDial_6" : ["Command+6"],
    "GoToSpeedDial_7" : ["Command+7"],
    "GoToSpeedDial_8" : ["Command+8"],
    "GoToSpeedDial_9" : ["Command+9"],
    "GoToTop": ["Home","Ctrl+Home"],
    "HideOpera": ["Command+H"],
    "History": ["Command+Shift+H", "Command+Alt+2"],
    "Homepage" : ["Space+Meta", "Command+Home"],
    "NavigateDown": ["Down"],
    "NavigateLeft": ["Left"],
    "NavigateRight": ["Right"],
    "NavigateUp": ["Up"],
    "NavStop": ["Esc"],
    "OpenDocument" : ["Command+O"],
    "OpenLinkInBackground": ["Command+Shift+Enter"],
    "OpenLinkInNewPage": ["Command+Enter"],
    "OpenMenu" : ["Command+M"],
    "OpenPrivateWindow": ["Command+Shift+N"],
    "OpenWindow": ["Command+N"],
    "PageDown" : ["PageDown","Space"],
    "PageLeft" : ["Command+PageUp"],
    "PageRight" : ["Command+PageDown"],
    "PageUp" : ["PageUp"],
    "ParentDirectory": ["Command+Backspace"],
    "Paste": ["Command+V","Meta+Y"],
    "PasteAndGo": ["Command+Shift+V"],
    "PastePassword": ["Command+Alt+Enter"],
    "Preferences": ["Command+OemComma"],
    "Print" : ["Command+P"],
    "PrintPreview": ["Command+Shift+P"],
    "QuickPreferences": ["Alt+F12"],
    "Redo": ["Command+Y","Command+Shift+Z"],
    "Reload": ["F5","Command+R"],
    "ReloadFrame": ["Alt+F5"],
    "ReopenLastClosedTab": ["Command+Shift+T"],
    "ResetZoom" :["Mul", "Command+0", "Command+Num0"],
    "Save" : ["Command+S"],
    "SelectAll": ["Command+A"],
    "SelectPreviouslyActiveTab": ["Ctrl+Grave"],
    "SelectTabToTheRight": ["Ctrl+Tab"],
    "SelectTabToTheLeft": ["Ctrl+Shift+Tab"],
    "ShowContextMenu": ["Command+Shift+M"],
    "ShowHelp" : ["Command+Shift+OemSlash"],
    "SwitchToNextPage": ["Command+Shift+Right"],
    "SwitchToPreviousPage": ["Command+Shift+Left"],
    "ToggleFullscreen": ["Command+Shift+F"],
    "ToggleKeyboardSelection" : ["F7"],
    "ToggleOverstrike": ["Ins"],
    "Transfers": ["Command+J"],
    "Undo": ["Command+Z"],
    "ValidateSource": ["Command+Shift+U"],
    "ViewSource": ["Command+U", "Command+Alt+U"],
    "ZoomIn" : ["Command+OemPlus", "Command+Shift+OemPlus", "Shift+OemPlus", "Command+Plus", "Plus", "OemPlus"],
    "ZoomOut" : ["Command+OemMinus", "Command+Minus", "Minus", "OemMinus"]
  },
  "Advanced": {
    "Back": ["Z"],
    "FastForward": ["Shift+X"],
    "Find": ["OemSlash"],
    "FocusNextFrame": ["3"],
    "FocusPreviousFrame": ["Shift+3"],
    "Forward": ["X"],
    "LoadAllImages" : ["I"],
    "ResetZoom": ["6", "Num6"],
    "Rewind": ["Shift+Z"],
    "SelectNextElement" : ["D"],
    "SelectNextHeading" : ["S"],
    "SelectNextLink" : ["A"],
    "SelectPrevElement" : ["E"],
    "SelectPrevHeading" : ["W"],
    "SelectPrevLink" : ["Q"],
    "ShowAddressDropdown" : ["H"],
    "ShowImagesToggle": ["Shift+I"],
    "ZoomIn": ["0", "Num0"],
    "ZoomInMore": ["8"],
    "ZoomOut": ["9", "Num9"],
    "ZoomOutMore": ["7"]
  }
}

PHPでフィボナッチ数列を出力するソースコードを出力するプログラム

Quineみたいなものだけど、自身のソースコードを次々に書き換えて
それを新たに起動したPHPプロセスに標準入力として与えている。

fib.php

<?php
function php($input) {
    $process = proc_open('php', array(array('pipe', 'r'), array('pipe', 'w')), $pipes);
    if (is_resource($process)) {
        fwrite($pipes[0], $input);
        fclose($pipes[0]); 
    
        $output = stream_get_contents($pipes[1]);
        fclose($pipes[1]);
        proc_close($process);
    
        return $output;
    }
}
function callback($output) {
    $n = 50;
    $lines = explode("\n", trim($output));
    $count = count($lines);
    $lines[] = end($lines) + prev($lines);
    $f = __FILE__;
    $s = file_get_contents($f);
    $s = preg_replace("/__FILE__[;]/", "'$f';", $s);
    $s = preg_replace('/0\n1\n/', implode("\n", $lines), $s);
    return $count < $n ? php($s) : end($lines);
}
ob_start("callback") ?>
0
1
<?php ob_end_flush() ?>

Result

$ time php fib.php 
12586269025
php fib.php  0.51s user 0.28s system 92% cpu 0.851 total

あなたが学ぶべき10のプログラミング言語

純粋関数型言語は当然学ばなければなりません。
副作用の分離とモナドによる抽象化は本当のプログラマーなら知っておくべきでしょう。
遅延評価のメリット・デメリットとそれを活かしたアルゴリズムも重要です。

  • Scala

オブジェクト指向と関数型の機能を合わせ持ったマルチパラダイム言語のScalaを学ぶことは、あなたにとって新たな知見となるでしょう。
Twitterのインフラで使われるなど実績も十分で、現在のプログラマーにとっては当然のように使えるべき言語の1つです。
Haskellもまたそうですが、Scalaは型が強力なので型レベルプログラミングを学び、コンパイル時のエラー検出について考えてみるのもよいでしょう。

マルチコアのCPUが当たり前になった現在では、難しい並列処理をいかにして簡潔に実現するのかというのは非常に重要なテーマです。
Erlangは並列処理を念頭において開発された言語で、アクターモデルによる並列処理が特徴です。
アクターモデルによる新しい並列処理のアプローチは今後必ず重要になってくるので当然学ぶべきでしょう。
Rubyライクな記述のできるElixirを学ぶのもいいかもしれません。

HTML5が普及してWebアプリケーションの重要性増しており、JavaScriptの重要性もまた非常に高まっています。
プロトタイプベースのオブジェクト指向や、プロトタイプチェーンによる継承など、クラスベースのオブジェクト指向と違ったアプローチは学ぶ価値があるでしょう。
また関数が第一級のオブジェクトなので関数型のような記述も可能です。
関数型言語で学んだ知見はここでも多いに役立つでしょう。

歴史ある関数型のLISPやその方言のSchemeなどはプログラマーを名乗るのであれば書けて当然の言語でしょう。
S式による一貫した記法によってコードそものものを第一級のオブジェクトとして扱える柔軟性は他にはない素晴しいものです。
マクロによるプログラミングについても大いに学ぶことがあるでしょう。

歴史ある関数型言語MLから派生して生まれた、オブジェクト指向の機能を持った関数型言語です。
純粋な関数型言語Haskellとはまた少し違ったアプローチのOCamlを学ぶことで、関数型言語に対する理解がさらに深まるでしょう。

  • Coq

プログラムにはバグが付きものですが、バグを無くすにはどうすればいいでしょう。
テストを書けばテストケースに漏れがない限りはプログラムの品質を保証できます。
しかし、定理証明系のCoqを使えば、プログラムの動作を完全に証明することもできます。
テスト駆動開発、ビヘイビア駆動開発に続く、証明駆動開発について学ぶことは新しい知見となるでしょう。

Templateを使ったGenericプログラミングや、constexprによるコンパル時実行、型推論、ラムダ式など先進的な機能がたくさん詰ったC++は是非学んでおきたい言語です。
ある程度の規模の高速なネイティブプログラムを開発しようと思うとCでは非力すぎるため、多くの場合C++が最良の選択肢でしょう。
高速なネイティブプログラムが必要となる場面というのは未だ多く、学ばなければならない言語の1つでしょう。

Luaはプログラムに組み込んで使うこと目的として開発されたJavaScriptライクなスクリプト言語です。
言語として特徴的なのは途中で処理を止めて再開することができるコルーチンを持っている所でしょう。
スクリプト言語でありながら動作が非常に高速で、プログラムに組込むDSLとして最適と言えます。
例えばプログラムの設定ファイルの記述をLuaで柔軟に行なえるようにするなど、DSLを組込みこんだ設計というのは学ぶべき価値があるものです。