Hatena::ブログ(Diary)

学び、そして考える RSSフィード

2010-08-14

[][] Thinkpad X61 tablet で Ctrl + Alt + Down で画面回転するのを無効にしたい

Eclipseショートカットキーを積極的に使っていこうと思い、Window → Preferences → General → Key にあるショートカット一覧をCSVエクスポートして、それを見ながら片っ端から試していた。

Ctrl + Alt + Down が「Copy Line」と機能なのだが、押した瞬間画面がブラックアウト。30秒ほどして画面が180度回転して表示された。

タブレットPCならではの機能である画面回転が発動した模様。どこかでショートカットキーの設定が上書きされているのだろう。さてどこで?

意外に手強くて、ThinkVantageの「キーボードカスタマイズユーティリティ」や、「タブレットショートカット・メニュー」にも見あたらない。

結局ググる

How to disable screen orientation hotkeys? (Ctrl-Alt-arrow) | TabletPCReview.com - Tablet PC Reviews, Discussion and News

にて発見。Ctrl + Alt + F12 でIntel Control Panel というのが立ち上がる。

ホットキータブの、「ホットキーの有効化」のチェックを外す。

f:id:p-nix:20100814225255j:image

これで無事「Copy Line」が動作。現在行の内容をコピーして下の行に貼り付けてくれます。



2010-07-08

[] amazonでおすすめされたけど、プラトンアリストテレス

久しぶりに amazon の自分へのおすすめ商品見てみた。


プラトンプラトンプラトンプラトンアリストテレスプラトンアリストテレスプラトンアリストテレスプラトンプラトンプラトン……


どういうアルゴリズムでこんなことに。そんなに古典哲学の本を買っているわけでもないのに。

ここまで来ると何が何でも読め、という強要にも思えてくる。。

具体的にはこんな本をお薦めされてました。

饗宴 (岩波文庫)

饗宴 (岩波文庫)

法律〈上〉 (岩波文庫)

法律〈上〉 (岩波文庫)

パイドン―魂の不死について (岩波文庫)

パイドン―魂の不死について (岩波文庫)

プロタゴラス―ソフィストたち (岩波文庫)

プロタゴラス―ソフィストたち (岩波文庫)

ニコマコス倫理学〈上〉 (岩波文庫)

ニコマコス倫理学〈上〉 (岩波文庫)

ソクラテスの弁明・クリトン (岩波文庫)

ソクラテスの弁明・クリトン (岩波文庫)

ニコマコス倫理学〈下〉 (岩波文庫 青 604-2)

ニコマコス倫理学〈下〉 (岩波文庫 青 604-2)

メノン (岩波文庫)

メノン (岩波文庫)

弁論術 (岩波文庫)

弁論術 (岩波文庫)

法律〈上〉 (岩波文庫)

法律〈上〉 (岩波文庫)

ゴルギアス (岩波文庫)

ゴルギアス (岩波文庫)

パイドロス (岩波文庫)

パイドロス (岩波文庫)

読もうかな、でもちょっと重いな−。。

2010-03-23

[][] Flex 4インストール後にFlashDevelopでコンパイルエラー

うわぁー、すごい長い間放置してた。すみません、生きてます。

Flex 4 SDK の最新版が出てたのでインストール。(Home Project for Open @ Adobe / Home / Projects

いつものように FlashDevelopからコンパイルすると以下のようなエラー。

Warning: This compilation unit did not have a factoryClass specified in Frame metadata to load the configured runtime shared libraries. To compile without runtime shared libraries either set the -static-link-runtime-shared-libraries option to true or remove the -runtime-shared-libraries option.

どうやら、FLex SDKのframeworkフォルダにある flex-config.xml の内容が変わっているようである。

static-link-runtime-shared-libraries タグの値が true → false に。そして、runtime-shared-library-path タグの中身が大幅増量。

対策としては、上記メッセージに従って、コンパイル時の引数に「-static-link-runtime-shared-libraries=true」を加えればよい。

FlashDevelopでは、Project→Properties→Compiler Options→Additional Compiler Options のところに追加。

これでエラーは出なくなったが、コンパイラ引数の設定はプロジェクト毎なので、プロジェクト作成ごとにこの設定行うのメンドイかも。

デフォルトコンパイラ引数設定できないものか。ちょっとよく分からない。


Flex 4の目玉機能って、デザイン(GUI)との連携の良さ、あたりだと思うので、そうなるとデザイン画面のないFlashDevelopではあまりメリットを享受できないのかもしれない。そうなると Flash Builder 4 の方に分があるのかな−。まださわっていないので評価できないけど。


最近、

にはまっています。まさに「神の書」と呼ぶにふさわしいでき。

2009-12-19

[] ラムダ式関数の部分適用、カリー化

長くなった。。Real World Haskell―実戦で学ぶ関数型言語プログラミング P103 〜 P107 あたりの話。


記述に正確を期すようにすればするほど難しい言葉ばかりが並んでしまって何が何だか分からなくなってしまう。

分かりやすさを優先して多少はくだけた表現でもいいよね、と言い訳。例えば、

くだけた表現
a は多相型といって、様々な型を取りうるということを表しています。つまりどんな型でもいいよ、ってこと。
厳密な表現
a は多相型で、これはすべての型の上で全称修飾された型を表します。多相型の表現式は本質的には、型の族をあらわすものです。(http://www.sampou.org/haskell/tutorial-j/goodies.html を参考)

厳密な記述ももちろん必要。でも今の自分には高すぎるハードルである。



おさらい。

Haskell関数型言語と呼ばれている。その名の通り、「関数」が重要な役割を果たす。

では関数とは何か。

関数とは、入力された値をいろいろ加工して返す(出力する)ものである。入力があって出力がある。これが関数

そしてある関数の出力は別の関数の入力となり、その出力は別の関数の入力となり・・・・・・、と連なって

プログラムが構成される。そんなのが関数型言語によるプログラム、だと思う。たぶん。

Haskell のもう一つの特徴として、型を重要視する、というのがある。ある関数を使いたいとき、まずどんな型なのかを調べる。

自分で関数を定義する場合もどんな型にするのかをまず考える。関数には入力(引数)と出力があるから実際には入力と出力の型ね。

型に厳密なおかげでバグの少ないプログラムを書くことができるのもメリット。(もっとメリットあるんだろうけど)


例) dropWhile の型

型を調べるには、ghci プロンプトから、:t 関数名 [Enter] とすればよい

dropWhile :: (a -> Bool) -> [a] -> [a]

dropWhile :: 以降が型の説明。最も右側の値が出力の型を示す。それ以外(つまり (a -> Bool) -> [a] )が入力(引数

の型である。よって dropWhileは、(a -> Bool) と [a] の2つの型の引数を受け取り、[a] の型の値を返す関数であることが分かる。例 終わり。


ここまできてようやく関数の中身について調べる。dropWhile とは、第2引数であるリストに対し、リストの先頭から走査して、第1引数の条件を満たす間、その値を削除する。条件を満たさなくなった時点で残りのリストを返す関数である。具体的には、

*Main Data.Char> dropWhile odd [1,3,5,2,6,7]
[2,6,7]

リストの先頭からたどって、奇数である間(つまり、1、3、5に対して)それを削除する。よって残ったのは[2,6,7]

*Main Data.Char> dropWhile isSpace "   abc "
"abc "

リストの先頭からたどって、空白である間(つまり最初のスペース3つ)を削除。残ったのは "abc "(末尾の空白は残る)

おさらいここまで。


無名関数(ラムダ関数

たった1つの関数だけでプログラムが完結することはないわけで、実際には複数の関数を組み合わせてプログラムを構成することになるでしょう。

少し複雑な例を。リストのリストの各項目に対して、あるリストを1つでも含んでいれば True を返す IsInAny を考える。(p104)

条件が複雑な場合、その部分を別の関数として切り出すのは様々な言語でよく行われる。

-- 使い捨て関数を使うやり方
import Data.List
isInAny needle haystack = any inSequence haystack
    where inSequence s =  needle `isInfixOf` s

このように、inSequence が中継役となる。言い換えればそこでしか使われない、いわゆる使い捨て関数である。

こういう使い捨ての関数って関数名を何にするか、とかで結構迷ったりするんですよね。そこで、使い捨て関数を使わないやり方として無名関数(ラムダ関数)というのがあります。Haskell 独自のものでは無く、今では C#JavaScript などでもおなじみですね。

-- ラムダ式を使う方法
isInAny2 needle haystack = any (\s -> needle `isInfixOf` s) haystack

引数の箇所に直接条件式を組み込むことでソース短くなりました。しかし、短くなったのはいいのですが、可読性が落ちたともいえます。あまり多用すると見づらいソースになる可能性もあります。


もっと良い方法は無いのでしょうか?


あるんです。


部分適用(部分関数適用)

結論から言うと、

-- 部分適用を使う方法
isInAny3 needle haystack = any (isInfixOf needle) haystack

と書けます。シンプルですね。右辺の (isInfixOf needle) と書けるところがポイントですね。

ここで型に目を向けましょう。 isInFixOf は、

isInfixOf :: (Eq a) => [a] -> [a] -> Bool

つまり、引数を2つ([a] と [a])受け取って Bool型を返します。(※ (Eq a) はとりあえず置いておく)

繰り返します。受け取る引数は2つです。

でも、(isInfixOf needle) という部分は isInfixOf が引数を1つしか受け取ってはいないように見えます。これはどういうことでしょう。エラーにはならないのでしょうか。


実は、isInfixOf は引数を1つだけ受け取ることもできます。いや、isInfixOf だけではなくすべての関数は1つだけ引数を受け取ることができます。受け取る引数が足りない場合、それは残りの引数の型を返す関数として動作します。(関数を返す関数という時点で戸惑いますが Haskellではよくあること)


いや、実はこの説明でも不完全です。もっと正確に言うなら、

Haskell のすべての関数は1つしか引数を受け取ることができません。

な、なんだってー

最初の dropWhile の例で、

(a -> Bool) -> [a] -> [a]

のうち、最初の2つが引数(入力)、一番右が出力と言いましたが正しくありません。見て分かるとおり、これってどこまでが入力でどこまでが出力なのかわかりにくいでしょ、どちらの区切りも -> なので。

-> には一つの意味しかありません。-> の左が引数の型、右が返す型。それだけです。

dropWhile は2つの引数を受け取るように見えるけど実際は1つの引数を受け取って、1つの引数を受け取る関数を返します。

だから引数1つでもエラーになりません。

必要な引数より少ない引数を与えることで、それは関数を返す関数として働きます。

これを関数の部分適用といいます。別名「カリー化」です。

部分適用することで、使い捨て関数を書くことなく、かつシンプルな記述ができます。徐々に引数を適用することでパーツ分けされるというか、視認性も良いです。


これだけだと狐につままれたような気持ちなので、型に着目して再度検討。

isInfixOf :: (Eq a) => [a] -> [a] -> Bool

部分適用部分 (isInfixOf needle) に対して仮にneedle の値を"aa" とすると(needleのままだと型が決定できなくて後の説明が苦しかったので)

isInfixOf "aa" :: [Char] -> Bool

である。つまり文字列を受け取ってBoolを返す関数として働く。一方、any の型は、

any :: (a -> Bool) -> [a] -> Bool

第一引数 (a -> Bool) のところに (isInfixOf "aa") を入れても型的には矛盾しないので大丈夫。


結論としては、関数の部分適用のおかげで、複数の関数が組み合わさったような構成でもシンプルに書けるよ、ってことでいいのかな?

使い捨て関数を使うことなく、ラムダ式を使うこともなく。



疑問点

部分適用 = カリー化 でいいのだろうか。http://lambda-the-ultimate.org/node/2266 などでは 部分適用 != カリー化 みたいに書かれているけど。まだよく分からない。


後書き

引数や、-> の定義が二転三転したわけですが、そもそもそれらの意味というのを考えるからこのようなことになるのでないか、とか思ったり。形式論レベルと意味論レベルの混在というか。とはいってもそううまくいくものでもないけど。

2009-12-18

[] foldl について

「畳み込み」を行う関数の一つである foldl 。

*main> foldl (+) 0 [1,2,3]
6

のようにリストの中身である1、2、3を左から足して、結果が6になる、という挙動を示す。いったいどういう仕組みなのだろうか。


foldl の定義は、


foldl :: (a -> b -> a) -> a -> [b] -> a                ・・・ 1)

foldl step zero (x:xs) = foldl step (step zero x) xs   ・・・ 2)
foldl _    zero []     = zero                          ・・・ 3)

foldlは引数を3つとる関数である。

1. step:リストの各値に適用する関数(この場合、+なので足すわけである)

2. zero:初期値。そして、計算途中の値を蓄積する場所である。ここに途中経過を蓄えながら再帰的に計算を行っていく

3. (x:xs):対象となるリスト

具体的に fold (+) 0 [1,2,3] がどのように計算されるか順を追って調べてみよう。

foldl (+) 0 [1,2,3]
==> 2)式左辺を当てはめる
    step = +
    zero = 0 
    (x:xs) = [1,2,3] 、つまり x = 1、xs = [2,3]
    
    として 2)式右辺に適用
    foldl (+) ((+) 0 1) [2,3]
    ※ここで、((+) 0 1 ) というのは(0 + 1) と同じだから以降は後者の書き方にするよ、その方がシンプルなので。
    よって、
    foldl (+) (0 + 1) [2,3]

==> 上記結果を 2)左辺と照らし合わせる
    step = +
    zero = (0 + 1)    ← リストの最初項目(つまり 1)に関数(+) を適用した途中結果が格納されている
    (x:xs) = [2,3] 、つまり x = 2、xs = [3]
    
    2)式右辺を適用
    foldl (+) ((0 + 1) + 2) [3]

==> 上記結果を 2)左辺と照らし合わせる
    step = +
    zero = ((0 + 1) + 2)  ← リストの内容のうち、1と2を適用した結果が格納されている
    (x:xs) = [3]、つまり x = 3、xs = []  xsは空要素となる
    
    2)式右辺を適用
    foldl (+) (((0 + 1) + 2) + 3) []

==> 上記結果を 2)左辺と照らし合わせる
    step = +
    zero = (((0 + 1) + 2) + 3)
    3つ目の引数は [] である。
    
    3つ目の引数が[] なので 3)式が適用される。つまり返ってくる値はzero。よって、
    (((0 + 1) + 2) + 3)

==> 再帰処理は終点まで到達。(((0 + 1) + 2 ) + 3) の値が計算されて答えは 6
    

もう一度まとめる

foldl (+) 0 [1,2,3]
==> foldl (+) (0 + 1) [2,3]
==> foldl (+) ((0 + 1) + 2) [3]
==> foldl (+) (((0 + 1) + 2) + 3) []
==> (((0 + 1) + 2) + 3)
==> 6

というわけである。ふむふむ。

ここに至るまで、自分の場合紙と鉛筆が必須でした。流れをガリガリ書かないとなかなか見えてこない。

それにしても、このような計算の経緯を視覚化するツールとか無いのかな。言い出したものが作れの法則なのだろうけど。