2013年8月25日日曜日

F#の%a書式指定はとても扱いづらい

F#のPrintfモジュールはある程度の書式指定ができるようになっていますが、基になっているOCamlが貧弱なせいもあってString.Format()ほどの表現力はありません。 何か手はないかと考えたところ %a 書式指定を思い出しました。Core.Printf モジュールには

2 つの引数を必要とする一般的な書式指定子。 1 つ目の引数は、2 つの引数を受け取る関数です。この関数の 1 つ目の引数は、指定した書式設定関数 (TextWriter など) に対応する型のコンテキスト パラメーターです。2 つ目の引数は出力する値であり、この値によって、該当するテキストを出力するか、返すかを指定します。
2 つ目の引数は、出力する特定の値です。

とあります。いまいちわかりづらいので英語版ドキュメントも確認しましたが同じ内容で意味がよくわかりません。念のためOCamlのmodule Printfも確認します。

user-defined printer. Take two arguments and apply the first one to outchan (the current output channel) and to the second argument. The first argument must therefore have type out_channel -> 'b -> unit and the second 'b. The output produced by the function is inserted in the output of fprintf at the current point.

なるほどわかりません。

とりあえずF#で書いてみたところ、非常に面倒くさいことが判明しました。1つ目の引数の説明「TextWriter など」が罠です。 なんとprintfとsprintfとで要求される関数が違いました。具体的に関数を挙げた方がわかりやすいので、現在時刻をコンソール出力してみます。

let formatter_for_printf (textWriter : TextWriter) (dateTime : DateTime) = textWriter.Write("{0:MM/dd HH:mm}", dateTime) let formatter_for_sprintf () (dateTime : DateTime) = String.Format("{0:MM/dd HH:mm}", dateTime) printfn "%a" formatter_for_printf DateTime.Now sprintf "%a" formatter_for_sprintf DateTime.Now |> Console.WriteLine

つまり同じ %a でも

  • printfで出力する時は(TextWriter -> 'T -> unit) 'Tが必要
  • sprintfで出力する時は(unit -> 'T -> string) 'Tが必要

ということのようです。

OCaml側は確認していませんがドキュメントからはそう読み取れないため、F#の(限りなくバグに近い)仕様かなと思います。

2013年5月29日水曜日

DataContractJsonSerializerでDictionaryを表現 再び

以前、DataContractJsonSerializerでDictionaryを表現という記事を書きましたが、あれから4年半経ち時代が変わりました。 .NET Framework 4.5からDataContractJsonSerializer constructorDataContractJsonSerializerSettings classを引数に取り、このclassはUseSimpleDictionaryFormat propertyを持っています。 そう、つまり…標準機能でDictionaryが表現できるようになっていました。

2013年2月16日土曜日

F#の||>演算子について

F#言語仕様には|>演算子と||>演算子と|||>演算子が定義されています。|>演算子はシンボルと演算子のリファレンスにも掲載されていますし、比較的よく使われています。

x |> f
とすると f(x)が実行されるものです。さて残りの2つ、これらは言語仕様には存在だけが記されており、それぞれop_PipeRight2、opPipeRight3にコンパイルされることしかわかりません。調べたところ、これらは
let inline (|>) x f = f x let inline (||>) (x,y) f = f x y let inline (|||>) (x,y,z) f = f x y z
のようなものだということがわかりました。つまり左辺にはタプルを受け、右辺の関数にタプルの値を展開して引数として適用するものです。

結論。高度に発達した関数型言語はググラビリティが非常に高い。(op_PipeRight2でググったけどこの話題が全然見つからなかった…。)

2012年12月10日月曜日

-ms-filterは無意味

Microsoft Internet Explorerにはバージョン4.0で導入されたfilterプロパティがあります。IEバージョン8からCSS標準に準拠するために-ms-filterプロパティが導入されました。しかし導入経緯を理解せず、ただ単に記述しているサイトおよび解説サイトを散見するため、この記事を書きました。

2012年6月4日月曜日

CSS Media Queries Hacks

​スタイルシートは認識するセレクター・プロパティにだけ適用されればそれで済むはずと考えていたこともありました。しかし、CSS animationのできるブラウザーではCSS Sprite画像を読み込んだ上でアニメーション、そうでないブラウザーではアニメーションGIF画像を読み込む、なんてことをする場合、どちらのブラウザーでもbackground-imageプロパティは認識されてしまうため、ブラウザーに応じて動作を変えることができません。

そこで目を付けたのがCSS Media Queriesという機能です。この機能を使うとブラウザーのサイズなどに応じてスタイルシートを変更することができます。
各種ブラウザーには独自の拡張機能がありこれを利用するとブラウザーごとに異なるスタイルを適用することができます。昔あったスターハックの合法版といったところでしょうか。

これを組み合わせるとこんな風に書けます。
@media (-moz-touch-enabled:0), (-moz-touch-enabled:1){ /* Gecko 1.9.2 (Firefox 3.6)以降に適用 */ } @media (-moz-device-pixel-ratio){ /* Gecko 2.0 (Firefox 4)以降に適用 */ } @media (-ms-high-contrast: none){ /* Internet Explorer 10に適用 */ } @media (-webkit-animation){ /* Webkit (Safari4以降 or Chrome)に適用 */ }
簡単ですが動作サンプルを。

2012年3月3日土曜日

IMG要素のonloadイベントについて

ふと見かけたので正しいのかわかりませんが、書き留めておきます。 IMG要素のonloadイベントがIE系でうまくいかないときの対処とかやっぱりIE9でもキャッシュ有効時のimg要素はonloadを無視する件とか見つけました。 しかし、onload eventを読むと

To ensure that an event handler receives the onload event for these objects, place the script object that defines the event handler before the object and use the onload attribute in the object to set the handler.
You need to set the image.onload before you set the image.src.
書かれています。 つまり、
  • IMGタグよりも前にイベント内容を含むSCRIPTタグを配置する
  • src属性を設定する前にonloadイベントを設定する
ですかねぇ。

2011年7月13日水曜日

IStructuralEquatableの使い方

IStructuralEquatableについて今までいまいちわからずにいました。ググって出てきたページを読んでいたら使い方が微妙で違和感を覚えたためじっくり調べてみました。そうしたらもうちょっと使いやすいものだということがわかりました。
StructuralComparisons.StructuralEqualityComparerはオブジェクトそのものではなく、その要素を比較するIEqualityComparerを提供します。これを使ってIEqualityComparer<T>の実装例を書いてみました。

public class StructuralEqualityComparer<T> : IEqualityComparer<T> where T: IStructuralEquatable { public bool Equals(T x, T y) { return StructuralComparisons.StructuralEqualityComparer.Equals(x, y); } public int GetHashCode(T obj) { return StructuralComparisons.StructuralEqualityComparer.GetHashCode(obj); } }
こう書いてしまえばどう使うのかわかりやすいでしょうか。このサンプルそのものは new StructuralEqualityComparer<int[]>() のように使えます。
なんでこんなクラスをわざわざ作るのかというと、LINQで要求される比較演算子はどれもIEqualityComparerでなくIEqualityComparer<T>だからです。