2008年9月20日土曜日

Logicool Qcam のユーティリティをアップデート

追記(2008.9.22) : やっぱりダメだった。またスカイプ暴走。 (+_+) コントロールパネル > プログラムの追加と削除 より、 Logicool Qcam のみ削除した。


以前、 Logicool Qcam に付属していたユーティリティを常駐させていると、Skype の調子が悪くなった。そのため、ドライバのみをインストールして、タスクトレイに常駐するユーティリティを削除した。( Web カメラを使うと Skype が頻繁に暴走する ) 最近、そのユーティリティがアップデートしたようなので、再度インストールして調子を見てみた。

 

再インストール

Logicool > サポート&ダウンロード > ダウンロード からユーティリティをダウンロード。インストール後に、タスクトレイのアイコンを右クリック > 「アップデートをチェック」を選択すると、新しいアップデータがある旨が表示されるのでダウンロードしてインストール。再起動。

デバイスマネージャでドライバの日付を見ると、ドライバ自体は前回と変わらないようだ。多分。新しくなったのは、タスクトレイに表示されている目玉のおやじのようなアイコンのユーティリティ。

080920-003

 

Skype も以前と比べるとバージョンアップがされている。 (前回の記事は 2008.8.7) だから、どちらが原因だったのか、それもとも交互作用だったのかわからない。そういえば、 Windows Update もあったかもしれないから、もう何が何だか… (@_@;) 現在使っている Skype のバージョンは、、

バージョン 3.8.0.154 ファイルサイズ 21 MB。公式リリース。リリース日: August 14, 2008。ファイル名: SkypeSetup.exe

 

結果

使って数時間が経過するが、今のところ以前のようにユーティリティが頻繁に起動し、それと同時にカメラのランプがパカパカと点滅するということがない。また、Skype が暴走するということもない。 ^^

 

余談

Skype for Windowsベータ版 のスクリーンショットを見たら、使い勝手が向上しているかもという期待が。

Google Sites をウェブマスターツールに登録

友人も Google Sites を使ってサイトを作ってみた。しかし、一ヶ月以上経っても Google のインデックスに登録される気配がない。おかしいなぁ (@_@;) Google に認識されるようにウェブマスターツールを使ってみようか。

 

サイトの登録

ウェブマスターツールを使う前に、まずは基本の Google に URL を追加 。

 

ウェブマスター ツール

Google Sites で作成されたサイトの確認 - ウェブマスター向けヘルプ センター の説明に従った。

ウェブマスター ツール において、Google Sites で作成したサイトの URL を入力し、「サイトを追加」ボタンを押す。

「サイトを確認」において、セレクトボックスより「メタ タグを追加」を選択し、表示されたメタタグをコピー。

080920-002

 

 Google Sites において、 Site settings > Other Stuff の「Google Webmaster Tools verification」に上記でコピーしたメタタグを入力し、設定を保存する。

080920-003

 

ウェブマスター ツールにおいて、「確認」ボタンを押して、Google Sites を確認する。

JavaScript における 3 つの for 文

1. for – 配列の要素を添字で順に参照

配列の要素を添字で順に参照する for 文。

例えば、「HTML の全 A タグを取得して、その内容を出力」する場合、以下のように書く。

anchors = document.getElementsByTagName('a');
for (var i=0; i<anchors.length; i++){
 console.log(anchors[i])
}

試しに `for each...in - JavaScript | MDN’ のページで、上記の文を Firebug のコンソールで実行する。結果は以下の通り。

<a href="#pageContent">
<a href="#searchInput">
<a title="メインページへ" href="/">
<a id="toolslink" href="#sitetools">
(略)
<a href="/index.php?title=Special:Article&type=backlinks&pageid=29784">
<a class="dismiss" onclick="return MTMessage.Hide();" href="#">
<a id="MTMessageDetailsLink" class="details" onclick="return MTMessage.ShowDetails(this);" href="#">

ページ中に含まれる 「A タグ」が全て出力されたことが分かる。

 

2. for each - 配列の要素の「値」を順に走査

添字を利用する for文を使わずに、配列の要素を順に走査したい for each 文を利用する。

for each...in – MDC によると、

指定された変数を、オブジェクトの全プロパティの値に対して反復します。異なるそれぞれのプロパティに対し、指定された文が実行されます。

この文は JavaScript 1.6 で作られた。

New in JavaScript 1.6 – MDC によると、

JavaScript 1.6 は Firefox 1.5 以降でサポートされています。

先ほどの例と同じページを対象にして、for each … in を試してみる。

anchors = document.getElementsByTagName('a');
for each(var p in anchors){
 console.log(p);
}

結果は以下の通り。

<a href="#pageContent">
<a href="#searchInput">
<a title="メインページへ" href="/">
<a id="toolslink" class="" href="#sitetools">
(略)
<a href="/index.php?title=Special:Article&type=backlinks&pageid=29784">
<a class="dismiss" onclick="return MTMessage.Hide();" href="#">
<a id="MTMessageDetailsLink" class="details" onclick="return MTMessage.ShowDetails(this);" href="#">
70
item()
namedItem()

あれ?さっきよりも、表示されるものが増えてしまった。 (@_@;)

 

HTMLCollection

例のコード内でアンカータグを取得するメソッドは、document.getElementsByTagName()。これによって返されるものは、HTMLCollection 。

Document Object Model HTML によると、

An HTMLCollection is a list of nodes. An individual node may be accessed by either ordinal index or the node's name or id attributes.

HTMLCollection は node のリスト。個々の node にはインデックスで参照できる。

HTMLCollection の定義を確認する。、(同上より)

interface HTMLCollection {
  readonly attribute unsigned long    length;
  Node               item(in unsigned long index);
  Node               namedItem(in DOMString name);
};

先ほどの出力の最後に表示さたもが、上記のプロパティに対応している。

出力内容は for each の説明にある通り、 HTMLCollection の全プロパティが表示されたということ。

 

3. for … in - 配列の要素の「値」を得る

for each  に似ていて、同じく全プロパティに対して走査するのが for … in 。

for...in – MDC によると、 for 文と同じく昔からあるようだ。同じく試してみると、

anchors = document.getElementsByTagName('a');
for (var p in anchors){
 console.log(p);
}

結果は、

0
1
2
3
(略)
67
68
69
length
item
namedItem

確かに for each に似ている。しかし、異なる点は、

for each...in - for...in に似ていますが、プロパティ名そのものではなく、オブジェクトのプロパティの値に対して反復します。 (同上より)

 

4. まとめ

追記 (2009.3.13) : JavaScript はハッシュが基本的な構造。 (cf. JavaScript のハッシュとオブジェクト)、

ハッシュの用語で言うなら、

  1. for ... in は「キー」を得られる。
  2. for each ... in は「値」を得られう。

と覚えておけばいい

var hash = {hoge:"ほげ", piyo:"ぴよ"}; 

// キーを走査
for (var key in hash){
    console.log(key);
} 

// 値を走査
for each (var val in hash){
    console.log(val);
}
結果は、
hoge
piyo
ほげ
ぴよ

2008年9月19日金曜日

Spket IDE で Greasemonkey

Greasemonkey の編集エディタを Spket IDE に設定

Spket IDE については、「Spket IDE, Firebug を使って JavaScript」を参照。

ウィンドウ右下の Greasemonkey のアイコンで右クリック > ユーザスクリプトの管理。

080919-001

 

表示されたウィンドウの左下の「編集」ボタンを押す。

080919-003

 

使用するエディタを設定するためのダイアログが表示されるので、c:\Program Files\spket\spket.exe を選択する。この設定は、 ロケーションバーで、 about:config > 「greasemonkey.editor」に保存される。エディタを変更したい場合は、この値を変える。

 

スクリプトの作成

先ほどと同じ Greasemonkey のアイコンで右クリック > 新規ユーザースクリプト でダイアログが表示される。

080919-004

OK ボタンを押すと、 Spket IDE で開かれる。

 

テンプレート

作成するスクリプトは、他のスクリプトに影響を与えないようにブロックスコープ入れた方がいいみたい。 (cf. JavaScript のブロックスコープ)

// ==UserScript==
// @name           hoge
// @namespace      http://jutememo.blogspot.com/
// ==/UserScript==
(function () {
        //ここに実際のコードを書く
})();

 

ログの出力

3.2. Logging with GM_log [Dive Into Greasemonkey] によると、

Greasemonkey provides a logging function, GM_log, that allows you to write messages to JavaScript Console.

GM_log(“ログ情報”) というように使う。 (cf. GreaseMonkeyでalertを使わないでデバッグする方法 )

 

表示先

Firefox のメニューより、「ツール > エラーコンソール」を選択すると、デバッグ情報が表示されるウィンドウがでてくる。

080919-005

 

追記(2008.9.20) : Firebug のコンソールの右上のオプション「クロームのエラーを表示」にチェックを入れたら、Firebug でも GM_log() によるログの出力が表示された。

追記(2009.9.25) : 「クロームのメッセージを表示」のチェックも必要。

080920-007

また、Greasemonkey + Firebug + GM_log - 冬通りに消え行く制服ガールは、夢物語にリアルを求めない。 – subtech によると、

Firebug 1.0 以降では extensions.firebug.showChromeMessages を true にしないと GM_log のメッセージが表示されないらしい

Python のジェネレータ (2) - リストの走査

Python のジェネレータ (1) - 動作を試す のつづき

1. ジェネレータをどこで使うのか?

ジェネレータの動作について、何となく雰囲気を理解できた。しかし、どのような目的に使うのか、今一分からない

「あ!これはジェネレータを使うと、問題を解くのが楽だ。」

「ジェネレータを使った方がシンプルに書ける」

ということが分かるようになりたい。

 

イテレータを置き換えるジェネレータ

最初に覚えたことは、

ジェネレータを使うと、イテレータを簡単に作成できる。

ということ。イテレータとは、複数のオブジェクトに対して、要素を一つづつ辿るための手段。よって、ジェネレータは、複数の要素を辿るために利用できる。

080329-004例えば、Group クラスが Person クラスに対して責務があるとする。イテレータを自前で実装するには、境界条件を考えながら、イテレータプロトコルに沿うようにする。

自前で実装したイテレータは、ジェネレータで置き換えることができる。

イテレータを自前で実装することと比べると、ジェネレータを使った方がシンプルに書ける。

 

2. ジェネレータを使い、リストを走査する例

ジェネレータを使うことができる例を挙げる。

には、「リストの各々の要素に対して、右隣の要素との差をリストとして返す」処理の例が書かれている。

>>> a = [0,1,2,3,4,5] (略)

… 一つ前の要素との差を求めたかった。a[1]とa[0]の差は1といった感じで、a=[0,1,1,1,1,1]になって欲しい。0番目は何もしない。

ジェネレータを使わずに定義するなら、

def sa(ary):
    result = []
    for x in zip(ary[:-1], ary[1:]):
        result.append(x[1] - x[0])
    return result

def sa_wrapper(ary):
    return ary[:1] + sa(ary)
    
print sa_wrapper([0,1,2,3,4,5])

関数 sa をリスト内包表記で置き換えると、

def sa(ary):
    return [b-a for a, b in zip(ary[:-1], ary[1:])]

この問題に対して、ジェネレータを使ってみる。

080918-003最初に、ジェネレータを利用したときのイメージを考える。

  1. 対象のリストの要素に対して、0 番目と 1 番目の要素から走査するジェネレータを2つ想定する。
  2. 各々のジェネレータから要素を順に取り出し、関数 zip でジェネレータ g1 から取り出した値を g2 から引いた値をリストにする。
  3. 最後に、元の先頭の要素を求めるリストの先頭にくっつける。

ジェネレータを使わない場合、

ary[:-1], ary[1:]

のようにして部分リストを取得する。この処理をジェネレータで置き換える。

def gen(ary, i):
    u""" リストの i 番目の要素から走査するジェネレータ """
    for e in range(i, len(ary)):
        yield ary[e]

a = [0,1,2,3,4]
print [a[0]] + [a-b for a,b in zip(gen(a,1), gen(a,0))]

 

ジェネレータを使うメリット

ジェネレータは、イテレータのように要素を1つずつ取り出しては処理を行う。そのため、ジェネレータを使うメリットは、

ary[:-1], ary[1:]

のように部分リストを完全に取得する必要がないこと。もし、対象のリストがとても長く、

「要素を検査した結果、すぐに値を返す」

というような処理が含まれる場合、効率的に計算が行われる。

 

3. 再帰的な処理で置き換える

以下、ジェネレータとは関係がない。上記の例を再帰的な処理で置き換えてみる。

  1. 空のリストが来たとすると、そのまま返す。
  2. 要素が一つの場合も、何もせずにそのまま返す。
  3. 要素が二つのときは、2 番目の要素から先頭の要素を引いた値をリストにして返す。
  4. 要素が三つ以上のときは、同様に2 番目の要素から先頭の要素を引いた値をリストにしたものと、2 番目以降の要素を再帰的に呼出した結果のリストと結合して返す。
def rec(ary):
    if len(ary) <= 1:
        return ary
    elif len(ary) == 2:
        return [ary[1] - ary[0]]
    else:
        return [ary[1] - ary[0]] + rec(ary[1:])
    
def rec_wrapper(ary):
    if ary == [] or len(ary) == 1: return ary
    return [ary[0]] + rec(ary)

a = [0,1,2,3,4]
print rec_wrapper(a)

先頭の要素を、リストの先頭に持ってくる処理も再帰呼出しの中に含めるように変更する。

def rec2(ary):
    if len(ary) <= 1:
        return ary
    elif len(ary) == 2:
        return [ary[0]] + [ary[1] - ary[0]]
    else:
        return rec2(ary[:-1]) + [ary[-1] - ary[-2]]

print rec2(a)

 

要素を指定できるようにする

上記では、ジェネレータを使って書いたときの柔軟さが失われている。

ジェネレータを使った書き方は、引数 i によって隣接する要素だけではなくて、i 個離れた隣の要素から引いた値のリストを返すことができる。上記の再帰関数も、同じように指定された i だけ隣の要素から引いたリストを返すように変更してみよう。

080919-006まずは、具体的な例で考える。例えば、i = 3 で、3 つ隣の要素から各要素を引いた値のリストを得る場合。このとき、リストが返されるために、元になるリストは少なくとも 要素を 4 つ持っていないといけない。 要素が 3 つ以下であれば、何せずに元のリストをそのまま返すとする。逆に 5 つ以上であれば関数を再帰的に適用する。

これを一般的に書くならば、

  1. 引数 i + 1 と、リストの大きさが同じ場合、 i 番目の要素から先頭の要素を引いた値をリストにして返す。
  2. 引数 i  >= リストの大きさであれば、何せずにそのまま返す。
  3. それ以外のときは、再帰的に関数を適用
def rec3(ary,i):
    if len(ary) <= i:
        return ary
    elif len(ary) == i+1:
        return [ary[i] - ary[0]]
    else:
        return [ary[i] - ary[0]] + rec3(ary[1:],i)

def rec_wrapper3(ary,i):
    if len(ary) <= i: return ary
    return [ary[0]] + rec3(ary,i)

print rec_wrapper3(a,1)

同じように関数 rec2 も変更してみる。

def rec4(ary,i):
    if len(ary) <= i:
        return ary
    elif len(ary) == i+1:
        return [ary[0]] + [ary[i] - ary[0]]
    else:
        return rec4(ary[:-1],i) + [ary[-1] - ary[-1-i]]

print rec4(a,1)

シンプルに見えるけど、見直してもすぐに理解できなくなってしまった。 パタッ(o_ _)o~†

 

処理を分割する

上記の定義は複雑すぎる。理由は、処理が適切に分割されていないため。

行なっている処理は、2つに分かれている。

  1. リストの各々の要素に対して、右隣の要素との差をリストとして返す。
  2. 対象の先頭要素を、結果の先頭に追加する。

予め Haskell で書いてみる。

sa (x:[])   = []
sa (x:y:xs) = y-x : sa (y:xs)

sa_wrapper xs | length xs <= 1 = xs
              | otherwise      = head xs : sa xs

Python で書きなおすと、

def sa(ary):
    if len(ary) <= 1: return []
    else: return [ary[1]-ary[0]] + sa(ary[1:])

def sa_wrapper(ary):
    if len(ary) <= 1: return ary
    else: return ary[:1] + sa(ary)

これで読みやすくなった。

Python のジェネレータ (3) につづく…