2008年5月31日土曜日

Python のリスト内包表記 - Ruby や Haskell の書き方と比べながら

0. Python の気になる機能

 Python チュートリアル の目次をざっと眺め、目にとまったのは次の二つの機能。

両方とも耳馴れない言葉。 (@_@) まずは、リストの内包表記から調べることに。

 

1. リスト内包表記の基本

a. リストの各要素に関数を適用する

最初は、リスト内包表記の使い方を確認する。例として、「数値のリストの各要素を 2 倍する」

print [x*2 for x in [1,2,3,4,5]]

初めて見たとき、どこから読めばいいのか検討がつかなかった。

読む順番は、

  1. for によって、各要素を取り出し、
  2. 各々に対して、操作を加える。

というように、後ろから前へと読み進める。

 

b. リストの各要素から、条件にあったものを抽出する

次に、同じく数値のリストから、特定の条件に合う要素を抽出する。

print [x for x in [1,2,3,4,5] if x > 3]

これまた読みにくい。 (@_@;)

 

c. 要素に対する関数の適用と、抽出を組み合わせる

では、上記二つを組み合わせてみる。

print [x*2+100 for x in [1,2,3,4,5] if x > 2 and x < 5]

慣れないと、どこから読めばいいのやら、迷ってしまう。

追記(2008.6.1) : ちなみに、「Python の好きなところ - kwatchの日記」 によると、Python では、条件の記述において、

2 < x < 5

と書ける。よって、上記のリスト内包表記は、

[x*2+100 for x in [1,2,3,4,5] if 2 < x < 5]

と記述できる。

 

2. リストの要素を組み合わせる

リスト内包表記において、for を複数記述すれば、リストの要素を組み合わせたリストを生成できる。

print [[x,y,z]    for x in [1,2,3]
                  for y in [10,20,30]
                  for z in ['a','b','c']]

上記のように、改行とタブで整形すれば、少し読みやすくなるかな。一行で書かれあるものなんて読みたくないなぁ。

もし、リストの要素を組み合わせるのに、リスト内包表記を使わないならば、

ary = []
for x in [1,2,3]:
    for y in [10,20,30]:
        for z in ['a','b','c']:
            ary.append([x, y, z])
print ary

for ループが 3 重にネストするため、ちょっと読みにくい。

追記(2008.8.19) : 「情報の論理数学入門」 (p14) によると、

「二つの集合 A, B の直積集合 (Cartesian product set) A × B は第 1 成分が集合 A の元で、第 2 成分が集合 B の元となる順序対のすべての集合である。 A, B がともに有限集合のとき、直積集合の元の数は A と B おそれぞれの元の数の積である。080819-003

上記のリスト内包表記は、「直積」と考えればよい。数学の表記に似せてあることがわかる。

 

3. Ruby でリスト内包表記と同等のものを書く

上記のリスト内包表記で得られる結果と、同じものを Ruby で書いてみる。

puts [1,2,3,4,5].map{|i| i*2}

puts [1,2,3,4,5].select{|i| i > 3}

puts [1,2,3,4,5].select{|i| i > 2 and i < 5}.map{|i| i*2+100}

Ruby の方が、

「リストに対して条件を設定し、それに操作を加える」

という思考の流れと、コードの流れが一致しているので書きやすい。

ただし、Ruby にはリスト内包記法がないので、リスト要素の「組合せ」を、Python のように素直に表現できないようだ。

 

4. リスト内包表記の入れ子は、読みづらくなる

リスト内包表記は、ネストさせることができる。しかし、段々と暗号のように見えてくる。 (@_@;)

print [[y for y in [2,3,4,5,6] if y == x] for x in [3,4,5]]

print [[y for y in [2,3,4,5,6] if y in x] for x in [[1,2,3],[3,4,7]]]

print [[y for y in ['h','o'] if y in x] for x in ["hoge","piyo"]]

 

5. リスト内包表記の「内包」の意味

リスト内包表記における、「内包」の意味は、

元々は公理的集合論の用語で、

  • 内包(intension)記法: {f(x) | x ∈ A} みたいな書き方。
  • 外延(extension)記法: {a, b, c, d, e, …} みたいな書き方。

[雑記] クエリ式とリスト内包 (C# によるプログラミング入門) より)

つまり、集合の要素を、個々に指し示すのではなくて、性質によって表わすということ。

しかし、数学的な表現と比べると、Python の表記は読みにくい。 for と if が、そもそも構造化プログラミングのための記法なので、それを流用して表現しているのでダメなのかな?

 

a. Haskell のリスト内包表記の書き方との比較

これに対して、 Haskell のリスト内包表記は読みやすい。

main = do print [x*2| x <- [1,2,3,4,5]]

          print [x| x <- [1,2,3,4,5], x > 3]

          print [x*2+100| x <-[1,2,3,4,5], x > 2, x < 5]

ふつうのHaskellプログラミング」 (p148) によると、

リスト内包表記を使ったコード例としてはクイックソートを実装したqsort関数がよく挙げられます。

About Haskell」 の「クイックソート」は、リスト内包表記が使われているので、シンプルに書かれている。

qsort []     = []
qsort (x:xs) = qsort elts_lt_x ++ [x] ++ qsort elts_greq_x
                 where
                   elts_lt_x   = [y | y <- xs, y < x]
                   elts_greq_x = [y | y <- xs, y >= x]

 

b. C# での書き方

クイックソート対決(Haskell vs C#) - 医者を志す妻を応援する夫の日記」 には、C# による記述の方法が書かれている。

static IEnumerable QuickSort(IEnumerable a)
{
    if (a.Count() == 0) return a;

    int p = a.First();
    var xs = a.Skip(1);
    var lo = xs.Where(y => y < p);
    var hi = xs.Where(y => y >= p);

    return QuickSort(lo).Concat(new[] { p }).Concat(QuickSort(hi));
}

お~、こんな風に書けるのかぁ~ (@_@)

 

6. map(), filter(), lambda と リスト内包表記

5.1.4 リストの内包表記 によると、

リストの内包表記 (list comprehension) は、リストの生成を map()filter()lambda の使用に頼らずに行うための簡潔な方法を提供しています。

ということで、map(), filter(), lambda について調べてみる。

 

a. lambda

最初に lambda 。

4.7.5 ラムダ形式 によると、

キーワード lambda を使うと、名前のない小さな関数を生成できます。例えば "lambda a, b: a+b" は、二つの引数の和を返す関数です。

ちなみに、Ruby では、次のように lambda を使う。

def make_incrementor(n)
 return lambda{|x| x + n}
end

f = make_incrementor(42)
puts f.call(0)
puts f.call(1)

個人的には、proc{ ... } や Proc.new { ... } よりも lambda { ... } の方が読みやすいかなぁ。

追記(2011.11.14) : Ruby 1.9 より、矢印ラムダで書くことができる。

def make_incrementor(n)
  return ->(x){ x + n } 
end

当初、Ruby はブロックの使い方が特徴的なので、同じように lambda { … } と書くほうが良いと感じた。しかし、無名関数くらいは、特別扱いした方が見やすいかな。

Python では、Ruby とは書き方が、微妙に異なる。

lambda a, b: a + b

Ruby のように、lambda がブロックとして、他同列の扱われ方をしているのではなく、無名関数として、特別な記法が前提とされている。

 

b. map, filter 関数

2.1 組み込み関数 には、map と filter 関数の説明が述べられている。

map(function, list, ...)

filter(function, list)

先ほどのコードを、map と filter を使って書き直すと、

print map(lambda x: x*2, [1,2,3,4,5])

print filter(lambda x: x>3, [1,2,3,4,5])

print map(lambda x: x*2+100, filter(lambda x: x>2 and x<5, [1,2,3,4,5]))

Python の組み込み関数は、Ruby と比べると、読みやすさの点では劣るかもしれない。

 

c. reduce 関数

ついでに、リスト操作として便利な、「5.1.3 実用的なプログラミングツール」 で挙げられていた reduce() を試す。

reduce(function, sequence[, initializer])

sequence の要素に対して、シーケンスを単一の値に短縮するような形で 2 つの引数をもつ function を左から右に累積的に適用します。例えば、reduce(labmda x, y: x+y, [1, 2, 3, 4, 5])((((1+2)+3)+4)+5) を計算します。

なるほど、reduce は、「短縮する」という意味なのか。Ruby の inject より、名前的にいいかも。

 

関連記事

2008年5月30日金曜日

Python で特定の範囲の数値を数え上げる - Ruby と比較して

1. Ruby の times メソッド と 範囲を表す Range オブジェクト

「数え上げる」とは、 for ループを使って、特定の範囲にある数値を順に表示すること。

Ruby が最初に紹介されると、必ずと言っていいほど例に取り上げられる

times メソッド

ブロック付きメソッドを見たことがないときは、「なんじゃ、この表記は!?」 (@_@;) と驚いた。

10.times do |i|
	puts i
end

for ループで書くなら、

for i in 0..9
	puts i
end

0..9

というのは範囲オブジェクトを生成する表記。(cf. Range - Rubyリファレンスマニュアル)

 

Integer クラスの upto, downto, step メソッド

Ruby では、数え上げるに Integer クラスの upto, downto, step メソッドも使える。

Integer - Rubyリファレンスマニュアル によると、

times {|n| ... }

upto(max) {|n| ... }

downto(min) {|n| ... }

step(limit, step) {|n| ... }

試してみる。

1.upto(9) do |i|
	puts i
end

9.downto(0) do |i|
	puts i
end

1.step(10, 2) do |i|
	puts i
end

times メソッドと比べると、表記にぎこちなさ感じる。

無理して、ここまでメソッドを定義しなくても…

という印象を受けるのは、 Ruby に慣れていない証拠かな?

てゆうか、times メソッドが、あまりにも自然な感じに読めるので、そのギャップもある。

 

2. Python の range() 関数

Python では、数え上げを行うとき、組込みメソッドである range() を利用する。

2.1 Built-in Functions によると、

range([start,] stop[, step])

試してみる。

for i in range(1,10):
    print i

# 2 ずつ増加させたい場合
for i in range(1,10,2):
    print i
    
# 1 ずつ減らす場合
for i in range(9,0,-1):
    print i

Ruby と比べると、組込み関数 range() を使うのは、律儀な感じを受ける。Ruby のように、Range オブジェクトを生成するための簡略な表記があればいいのに。

 

組み込みオブジェクト

ところで、「組込み関数のページ」は、`2. Built-In Objects’ の章にある。

この「組込みオブジェクト」って何だろう? Ruby のように、Kernel モジュールのようなものなのだろうか?

Ruby には厳密な意味では関数はありませんが、Kernel モジュールで定義されているメソッドは (どこからでも関数形式で呼び出せるので) 他言語における関数のように使えます。

(組み込み関数 - Rubyリファレンスマニュアル より)

これに対して、Python は、

Pythonでは扱えるデータの全てがオブジェクトである。単純な数値といった基本的なデータ型をはじめ、組み込みのコンテナ型、組み込み関数など、これらは全て統一的な継承関係をもつオブジェクトであり「型」をもっている。

Python – Wikipedia より)

やはり、どこかの型に定義されているのだろうか?

`Dive Into Python’ の 4.3. Using type, str, dir, and Other Built-In Functions によると

type, str, dir, and all the rest of Python's built-in functions are grouped into a special module called __builtin__. (That's two underscores before and after.) If it helps, you can think of Python automatically executing from __builtin__ import * on startup, which imports all the “built-in” functions into the namespace so you can use them directly.

なるほど、

__builtin__

というモジュールがあるようだ。 (cf. 26.2 __builtin__ -- Built-in objects )

しかし、‘Ion – Ruby vs. Python’ に書かれているように、

There are no functions and methods separately in Ruby; all of them are methods. In Python, e.g. len() is a function, but items() is a method. Such inconsistencies remind me of PHP, *shiver*.

なぜ、Python では、

"hoge".len()

と書けるようにしないのかなぁ?

 

3. Ruby の step メソッドについて

Range - Rubyリファレンスマニュアル

step([s]) {|item| ... }

Numeric - Rubyリファレンスマニュアル

step(limit, step) {|n| ... } 

Charu3 で HTML タグを入力する

選択してた文字列をタグで囲む

HTML を直接エディタで記述するとき、タグを入力する作業は面倒。 Charu3 は、HTML のタグの入力を手助けしてくれる機能がある。例えば、入力した文字を <b> タグで囲みたい場合、入力文字を選択しておいてから、Charu3 を呼出し、<b> タグを入力する行を選択する。

080530-1

 

なぜこれで入力した文字が <b> で囲まれるようになるかと言えば、「Charuマクロ」の「テキスト取得マクロ」を利用しているからだ。(cf. Charu3 ドキュメント ) 上記の「@b太文字」を 右クリック > プロパティ を見ると、$SEL という文字列が埋め込まれているのがわかる。これが選択した文字列と置き換わる。

<b><charumacro>$SEL</charumacro></b>

追記(2008.9.4) : マクロを入力するには、「マクロテンプレート」のセレクトボックスより「選択文字列」を選択するとよい。

080904-002

 

タグで囲まれた位置にカーソルを移動

上記とは逆に、最初にタグを入力しておき、その後で内容を入力したいことがある。Charu3 でタグを入力したら、カーソルがタグで囲まれた位置に移動してほしい。この場合、「キー入力マクロ」を利用する。Charu3 ドキュメント によると、

<charuMACRO_KEY>キー名,キー名...;回数;待ち時間</charuMACRO_KEY>

また、「キー名、キーコード一覧」より、左の矢印キーは、`LEFT' を入力すればよいことがわかる。これにより、タグを入力した後、カーソルで左へ移動するという一連の動きをマクロとして登録しておける。

例えば、<p> タグを入力したい場合には、次のようにする。

<p></p><charuMACRO_KEY>LEFT;4</charuMACRO_KEY>

2008年5月29日木曜日

Python, Ruby で簡単なテキスト処理 (1) - 特定の単語が含む行を抽出する

1. 特定の単語が含む行を抽出したい

ちょっとしたテキストを加工しようと思う場合、 Ruby を使うことが多い。

例えば、テキストの中から特定の単語が含まれた列を抽出し、何らかの処理をしたいとする。

対象となるテキストは次のもの。

hoge
piyo
ほげほげ
ぴよぴよ
ほげ\nぴよ
10,20,30
100,200,300
  hoge  hoge
  piyo  piyo

 

2. Ruby の場合

ここから、「ほげ」を含む列を抽出する場合、次のように書く。

DATA.each do |line|
	puts line if line =~ /ほげ/
end

__END__
ここに対象のテキストを貼り付ける。

Ruby では、

__END__

以降にあるテキストを読み込んで処理できるので、軽く試したいときに便利。

 

3. Python の場合

まずは、Ruby の __END__ と同じような機能が Python にもないかと探した。

スクリプト言語の比較::__END__ によると、

ない。ただし各モジュール、クラス、関数の最初に記述するドキュメント文字列中に、利用例としてテストケースを記述し、自動テストを実施するdoctestという仕組みがある。

パタッ(o_ _)o~†

スクリプト系の言語なら、同じような記述ができると思ったのが甘かった。 ^^; どうするのが一番楽ができるのだろうか?

とりあえず、変数に対象の文字列を代入して、処理するという形にしてみる。

lines = ur"""ここに対象のテキストを貼り付ける
"""

import re

for line in lines.split('\n'):
    if re.search(ur"ほげ", line):
        print line

文字列の前の ur は、2.4.1 String literals によると、

String literals may optionally be prefixed with a letter "r" or "R"; such strings are called raw strings and use different rules for interpreting backslash escape sequences. A prefix of "u" or "U" makes the string a Unicode string.

Unicode であり、raw string であることを示している。

r を付けたのは、対象のテキストの中に、 \n が含まれるため。 r を付けないと、対象のテキスト中にある \n が「改行」と解釈されてしまう。

それにしても、正規表現を使うだけで、モジュールをインポートしないといけないのは面倒。Ruby のように

 /正規表現/

のように書けないのだろうか... (@_@;)

 

覚え方

ur と re.search を使うことを、記憶しておくには、どうするか?

「裏リサーチ」

と覚えておくことにしよう。

追記(2008/6/3): Windows xp 上で、Python 2.5 を利用している。上記の lines 変数に代入した対象のテキストに「タブや空白」があると、 print 文でなぜか余分な空白行が出力されてしまう。そこで、改行コードを LF (UNIX) にしたら、普通に表示された。 なぜだろう (?_?)

それから、コード上で文字列を分割している split() だと、タブでも分割されてしまうので、 split('\n') に変更した。

Python, Ruby で簡単なテキスト処理 (2) - 表からのデータの抽出」につづく…

 

4. 参考

Firefox のタブの幅を固定し、多段表示したときの視認性を向上 - Tab Mix Plus を使って

1. タブの幅が揃っていると、視認性が向上する

Tab Mix Plus を使って、タブを多段表示できる。

071229-021

この表示で問題になることがある。それは、ページによってタイトルの長さが極端に違うとき。タブの段が、凸凹になり、視認性が損なわれる。目的のページを探すとき、探しにくい。

たいていページのタイトルは、全部見えなくても目的のものを探し出せる。そこで、タブの段数はそのままにして、幅を固定して表示するように変更した。

幅を固定して表示させたのが以下の写真。この表示の方が、目的のタブを探す時間が早くなった。

080529-5

 

2. タブの幅を固定する

Tab Mix Plus の設定を開く。 (ツール > アドオン より)

多段表示には、

  1. 「表示 > タブバー」 を表示。セレクトボックスから、「多段表示にする」を選択。
  2. バーの最大表示段数を「3」を入力。

080529-3

※ ここで、タブバーの位置を「下部」にすると、目的のタブが探しやすくなるかも。

次に幅を固定する。

  1. 「表示 > タブ」を選択。
  2. タブ幅が揃うように、テキストボックスに、二つ同じ値を入力。

080529-6

2008年5月27日火曜日

Google ドキュメントでファイルをエクスポートするとコメントが消える

080527-2Goolge ドキュメントでは、複数の人が文書を閲覧、編集することができる。特に、コメントを書くことができる (右クリック > コメントの挿入) ので、一つの文書上で、複数の人が意見を書き込むとき、誰のコメントかわかりやすくてよい。

 

ファイルのエクスポート

しかし、コメントを含んだ文書を PDF 等に変換すると、コメントしたところがごっそりと消えてしまう。 (@_@;) これが Goolgle ドキュメントの仕様なのだろうけれど、知らずにコメントしまくっていたので、いざ PDF に変換して、メールで送ろうとする段になって困り果ててしまった。

 

HTML を編集

文書を HTML 表示させて (編集 > HTML を編集) 見たら、コメントしたところは、

class="writely-comment"

と指定されていた。

そこで、 HTML をエディタにコピー。置換により、上記を全て削除し、それを Google ドキュメントと置き換えた。この文書を PDF に変換 (ファイル > ファイルのエクスポート... > PDF) したら、コメントも PDF に含めることができた。

080527-3

 

ただし、このままでは、Google ドキュメントにとって、コメントである部分がわからなくなるだろうから、置換する前の文書に版を戻しておいた。 PDF にする必要があり、コメントも含めたい場合に、上記の手順を踏んで作成することにした。

2008年5月24日土曜日

アプリケーションが落ちたときにエラー報告をしない

Windows Live Writer を使ってブログを書いていると、よくアプリケーションが落ちる。 IME を切替えているときに起こるので、 SKKIME と何かがバッティングしているのだろうか (?_?)

そういうとき、必ず、「このエラーを報告しますか?」というようなダイアログが表示される。いちいち報告しないので、このダイアログが表示されないようにしたい。

 

方法

マイコンピュータ  > プロパティ > 詳細設定 > エラー報告 の 「エラー報告を無効にする」を選択する。080524-1

マウスがスムーズに動かない - IntelliPoint が原因か?!

マイクロソフトのマウスを使うと、Firefox でマウススクロールがスムーズにできない

どうもマウスの動きが悪い。

特に、 Firefox でブラウズしているときに、反応が悪いことがある。サイトの読み込み処理をしているとき、マウスを動かすと、マウスポインタが飛ぶようにして動く。ホイールを回しても、スムーズに動かない。ちょっと一呼吸入れてから、やっと動きだすといった感じ。

ハードウェア アクセラレータの値を変更しても、問題は解決しない。

 

IntelliPoint の 6.2 を使うと不調

新しいマウスを購入しようかと思ったこともあるけれど、未だに古いマウスを使い続けている。

  • Microsoft Wiress Laser Mouse 6000

には、専用の

というユーティリティが付属している。

インストールしたバージョンは、6.2 。

このアプリケーションが悪さをしているのではないかと思い、アンインストールしてみた。

案の定、これが原因だった。はずしたとたんに、マウスがスムーズに動くようになった。

 

IntelliPoint 5.5 は動作せず

しかし、古いバージョンの IntelliPoint では、マウスの機能をフル活用できない。マウスの動きも以前と比べてぎこちない感じがする。 IntelliPoint が、マウスの操作に対する反応を調整していたようだ。

IntelliPointの6.xを入れると画面がちらつくので5.xに戻した(管理人日記) - むぅもぉ.jp によると、

しばらく前からの悩みだったのですが、Windowsの画面がちらつくんです。結論を言うと、それはIntelliPointのせいだった。古いバージョンを入れたら直った。

症状は違うけれど、どうやら何かしら関係がありそう。以前のバージョンへのへのリンクがあった

ので、そこからダウンロードして、インストールした。

しかし、エラーが表示されて、ユーティリティの画面を表示することができなかった。

 

IntelliPoint 6.1 だと、以前より少し動きが良い

そこで、Microsoft Hardware | ダウンロード一覧 に、一つ前のバージョン 6.1 があったので、インストールした。

* Microsoft Windows Vista 32 ビット版 対応
IntelliPoint マウス ソフトウェア version 6.1 (Windows版)

(2007/02/21)

その結果、完全ではないけれど、以前よりもスムーズにマウスを動かせるようになった。 ^^

追記(2008.6.13) : 最近の Windows Update のためか(?) 6.2 を使っても反応に問題がなくなった。

2008年5月23日金曜日

Google App Engine でテンプレートを使って画面遷移

前回のコード (Google App Engine でシンプルな画面遷移) は、コントローラ (webapp.RequestHandler のサブクラス) が、画面に表示する内容も生成していた。これを、 Django を利用してコントローラからビューを分離する。

Google App Engine には、Django が含まれている。

For your convenience, the webapp module includes Django's templating engine. This is included with the SDK and is part of App Engine, so you do not need to bundle it to use it.

(Using Templates - Google App Engine - Google Code より)

同上を参考にして、前回のコードを変更した。

 

概略

前回 Apage, Bpage クラスで生成していた HTML を、それぞれ A.html, B.html に移動させた。フォームで投げられたリクエストの内容は、 BPage クラスで取り出し、遷移先である B.html と共に、template に渡す。

080523-1

 

コード

まず、コントローラである APage, BPage を含むファイル。 (gamenseni.py)

import cgi
import wsgiref.handlers
from google.appengine.ext import webapp

import os
from google.appengine.ext.webapp import template

# 遷移元を表示するコントローラ
class APage(webapp.RequestHandler):
    def get(self):
        # テンプレートで表示する変数
        template_values ={}

        # テンプレートファイルへのパス
        path = os.path.join(os.path.dirname(__file__), 'A.html')
        # template に表示を生成してもらったものを出力
        self.response.out.write(template.render(path, template_values))

# 遷移先を表示するコントローラ
class BPage(webapp.RequestHandler):
    def get(self):
	# フォームから送信された内容を取得する
        template_values ={
            'name':     self.request.get('name')
        }

        path = os.path.join(os.path.dirname(__file__), 'B.html')
        self.response.out.write(template.render(path, template_values))

def main():
    # 画面遷移の対応付け
    application = webapp.WSGIApplication(
                    [('/', APage),
                     ('/seni', BPage)],
                    debug=True)
    wsgiref.handlers.CGIHandler().run(application)

if __name__ == "__main__":
    main()

遷移元である、フォームを含む A.html 。

<html>
  <head>
    <title>A</title>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <h1>遷移前</h1>
    <form action="/seni">
        お名前:
        <input type="text" name="name"/>
        <input type="submit" value="送信" />
    </form>
  </body>
</html>

 

遷移先である B.html 。

<html>
  <head>
    <title>B</title>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <h1>遷移後</h1>
    <p>お名前: {{ name|escape }}</p>
  </body>
</html>

{{ 変数 }} で、BPage クラスで template に渡された値を表示することができる。

|escape は、 フォームから送信された内容を表示するときに、 HTML エスケープしている。Django ではフィルタと呼ばれる機能。 Django | The Django template language: For template authors | Django Documentation によると、

escape

Escapes a string’s HTML. Specifically, it makes these replacements:

  • "&" to "&amp;"
  • < to "&lt;"
  • > to "&gt;"
  • '"' (double quote) to '&quot;'
  • "'" (single quote) to '&#39;'

 

app.yaml は前回と同じ。

application: gamenseni
version: 1
runtime: python
api_version: 1

handlers:
- url: /.*
  script: gamenseni.py

2008年5月22日木曜日

Google App Engine でシンプルな画面遷移

Handling Forms With webapp - Google App Engine - Google Code のサンプルを参考にした。

 

「遷移元」のページから、フォームの送信で、「遷移先」に遷移する例。

080522-2

 

遷移元を表示するのが Apage クラス。遷移先を表示するのが BPage。両方とも webapp.RequestHandler を継承している。遷移元からのリクエストと遷移先のページを対応付けるのが、webapp.WSGIApplication。

WSGI とは、18.4 wsgiref -- WSGI Utilities and Reference Implementation によると、

The Web Server Gateway Interface (WSGI) is a standard interface between web server software and web applications written in Python. Having a standard interface makes it easy to use an application that supports WSGI with a number of different web servers.

以下にコードを示す。

import cgi
import wsgiref.handlers
from google.appengine.ext import webapp

# 遷移元のページ
class APage(webapp.RequestHandler):
    def get(self):
        self.response.out.write(u"""
            <html>
                <head>
                    <title>A</title>
                </head>
                <body>
                    <h1>遷移前</h1>
                    <form action="/seni">
                        お名前:
                        <input type="text" name="name"/>
                        <input type="submit" value="送信" />
                    </form>
                </body>
            </html>
        """)

# 遷移先のページ
class BPage(webapp.RequestHandler):
    def get(self):
        result = u"""
            <html>
                <head>
                    <title>B</title>
                </head>
                <body>
                    <h1>遷移後</h1>
                    <p>お名前:
        """
        # リクエストから文字列を取り出す
        result += cgi.escape(self.request.get("name"))
        result += u"""
                    </p>
                </body>
            </html>
        """
        self.response.out.write(result)

def main():
    # 画面遷移の対応付け
    application = webapp.WSGIApplication(
                    [('/', APage),
                     ('/seni', BPage)],
                    debug=True)
    wsgiref.handlers.CGIHandler().run(application)

if __name__ == "__main__":
    main()

Bpage#get()において、文字列をユニコードとして認識されるようにしておかないと(文字列の先頭の`u')、UnicodeDecodeError が表示される。

 

関連記事

Python で HTTP の POST メソッドを送信 - 掲示板の迷惑投稿を一括削除

1. おちゃのこネットの掲示板の投稿を、一括で削除したい

友人が、おちゃのこネット のサービスを利用して、ネットショップを運営している。おちゃのこネットでは、ショップごとに掲示板を持てる。掲示板を使っていて問題となることは、迷惑投稿がたくさん入ること。

検索してみると、多くのショップがやられているようだ。

投稿を削除するには、

ショップの掲示板の一番下に
「以下のフォームから自分の投稿記事を修正・削除することができます」という
削除/修正用のBOXがありますので

1,処理の区分は「削除」に選択して下さい。
2,記事Noは削除されたい記事番号を入力下さい。
3,パスワードの箇所は、ショップマネージャー(管理画面)のログインPWを入れて送信ボタンを押してください。

おちゃのこサポートくらぶ - Q:掲示板(BBS)にショップとは無関係の記事があるので削除したいのですが、どうすればいいでしょうか? より)

管理画面からも投稿を削除できる。しかし、個別に削除するのは面倒なので、できればスクリプトで一括削除したい。

 

2. 削除用のスクリプト

Python を使い、urllib2 モジュールを利用する。

ソースコードは、urllib2モジュール - ひきメモ を参考にした。

import urllib
import urllib2

# 掲示板のアドレス
url = 'http://XXXXXXXX.ocnk.net/bbs'

# パスワード
passwd = 'XXXXXXXX'

# 削除したい記事の No.
#
# ex. 記事 No.1,3,5 を削除 codes = [1,3,5]
#     記事 No.1 ~ 10 を削除 codes = range(1,11)
codes = []
#codes = range()


# 指定された No. の投稿を削除する
def delpost(code, passwd):
    params = {
        'update'        : 'true',
        'mode'          : 'del',
        'code'          : code,
        'password_bbs'  : passwd
    }
    urllib2.urlopen(url,
                    urllib.urlencode(params))

for code in codes:
    delpost(code, passwd)

掲示板のアドレスと、削除用のパスワードを指定し、削除対象の投稿の No. を入れて実行する。

 

参考

2008年5月21日水曜日

iKnow でベーシック英語を学ぶ

1. これまで英語の勉強をする機会を作らなかった

英語にはじめて触れてから、どれくらい経っているだろうか?一生懸命勉強したのは、受験勉強をした高校まで。文法中心でヒアリングや会話の練習をしたことがない。

そのため、未だに英語をしゃべることはできない。身の周りのものを英語で言うことすらできない。大学時代は、英語の論文を読まざる負えないときだけ読んだ。仕事で英語のサイトを読む必要があったり、読みたい本が英語である場合は、仕方なく読んでいた。

必要に迫られてから、必要な内容にぶつかるというのが一番身につく。これまで、英語を話さなくてはいけない状況に陥ったことがない。だから、話せないし、文章を書くこともできない。簡単な内容でも、英語で言うことができない。

英語を勉強したいと思っていても、機会を作ってこなかった。せめて、英語を聞きとれるようになりたい。

 

2. iKnow でマイペースに学習する

ラジオやテレビの英語の番組を録画して学ぼうとしたことがある。

ラジオやテレビで英語を学ぼうとしても、よほど気合いを入れないと続けることができない。

これに対して、iKnow はイイ。ネット上のサービスなので、自分のペースで学ぶことができる。

学習するためのアプリは Flash で作られており、動作がスムーズ。学習状況の進捗の管理もしてくれる。どれくらい学習が進んだのか、把握できるガジェットが提供されているところも良い。

モチベーションをいかにして保つかという、学習にとって一番の原動力を保つための設計がされている。SNS 的なところも取り入れられており、次世代の Web アプリだと関心した。

 

3. ベーシック英語とは

ところで、数少ない単語で英語を組み立てる、「ベーシック英語」というものがある。

ベーシック英語 - Wikipedia によると、

イギリス心理学者言語学者チャールズ・ケイ・オグデンによって考案された人工言語である。文法は英語の文法を簡略化したもので、少ない単語で表現されている。

人工的な言語である「エスペラント語」と比較しても、学びやすいらしい。

オグデンによると、通常の英語を学習するには7年、エスペラントには7ヵ月必要であるのに対して、ベーシック英語は7週間で学習することができるとされる。 (同上より)

ベーシック英語の特徴は、

動詞、名詞が少なくなっている分を、複数の語を組み合わせたり、一つの単語に複数の意味を持たせたりすることで補っている。 (同上より)

850語で考える英語―ベーシック・イングリッシュ: 後藤 寛: 本 (p5) によると、単語を合成することに関して、基本的な原則として、次のように述べられている。

850語中の基本的にどの語も他の語と結合させ、いわゆる合成語として用いることができる。

eye + glass → eyeglass

rain + drop → raindrop

 

4. 語の合成

  サピアの「言語」には、「合成語」の例として、複雑な語の例が述べられている。

ユタ州南西部の乾燥した高原に住むインディアンの言語だ。 wii-tokuchum-punku-rugani-yugwi-va-ntu-m(u) という語は、この語をもつ言語自体にとってさえ異常に長いものだが、それにもかかわらず、心理的には少しも奇怪な語ではない。これは、「これからすわってナイフで黒い雌牛(または雄牛)を切り分けようとしている連中」という意味である。このインディアン語の要素の順序どおりに言えば、「ナイフ - 黒い - 野牛 - 所有物 - 切り分ける - すわる(複数) - 未来分詞 - 有生複数」である。(p56)

(太字は引用者による)

これ、文じゃないの?と思ったけれど、これで一語らしい。

 

5. iKnow のベーシック英語

iKnow にベーシック英語のコースがあった。

今度は続けることができるかもしれない。

2008年5月19日月曜日

Python はじめの一歩

Python を試してみる」のつづき

1. Instant Hacking を読む

Python をするための環境を整えたので、次は、Python に慣れるため、

pyscripter を使いながら試してみる。

pyscripter は動作も軽く、メソッドの補完をしてくれるから、コードを書いていて心地良い。^^

 

2. Instant Hacking のメモ

  • : が、まとまりを表わすのに使われる。この記号の次の行からインデント。これに見慣れると、Ruby の end は邪魔に感じる。
  • 条件分岐における elif は 、else と文字数を揃えることにより、可読性を上げてるのかな?
  • 入力を促すのは input() 関数。
  • for ループにおいて、文字列のリストは [] を省略できるようだ。
  • for ループで、インデックスを生成するには range(1, 10) 関数を使う。ただし、中身は 1 ~ 9 までであることに注意。
  • sleep(3) 。引数は、秒数。
  • リスト操作
    • []
    • append()
    • remove() 。中身の値を引数に指定。
    • [3:5] 。インデックスが 3 ~ 4 までの要素を取り出す。
  • del で変数を削除できる。
  • クラス
    • クラスにおける、メソッドの第一引数は、そのクラスのオブジェクトを参照できるように、self など適当な引数が必要。
    • new を使わずに、クラス名() でオブジェクトを生成する

 

3. メソッドの第一引数は、なぜ必要なのか?

Instant Hacking によると、

全てのオブジェクトのメソッドは、self(またはそれに近い名前の…)と呼ばれる第1引数をもっていなければなりません。

うーん、この書き方は冗長な気がする。(@_@;)

Ruby のように、

@ 付けたらインスタンス変数になる

というように、なぜしなかったのだろうか?

「またはそれに近い」

と括弧で括られていることよりも、self はキーワードではないことがわかる。

18.3. Defining classes in Python によると、

The self parameter represents the object itself. You could of course use any other word like carrot or ego, but this would not help the reading of your code by others...

それにしても、なぜ、メソッドの第一引数 self を指定しないといけないのだろうか? Python のクラスシステム を読んだけれど、自分の知識では理解できない。Python のベース部分が関数型で、その上にオブジェクト指向の環境を構築しているため、その自然な実装として今のような形になったということだろうか?

TSpython 発言 には、

Pythonは、関数もメソッドも全て「オブジェクト」です。(...) メソッドの呼び出しには二通りあります。
class A:
  def mes0(self, n):
    self. n = n
    return self
上のようなクラスがあり、a = A()でインスタンスを作ったとすると、メソッド mes0を呼び出す方法としては…… a.mes(10) という方法と、 A.mes(a, 10) という方法が両方できます(というか、後者の略記法が前者と思った方がいいかも……)
Words on a Blog: Pythonic programming and the "self" keyword にも、同様のことが書かれている。

I think explicitly using self as the first argument is a good idea, to some extent. It's kind of quirky (I'm pretty sure you can name it whatever you want, and it would still work), but having self be in the parameter list shows C programmers (and other, maybe more inexperienced OO programmers) how instance methods basically work. They aren't some voodoo magic higgity biggity, they really just pass the object as an invisible first argument to the method. In the above case, m.printInfo() is really just shorthand for MyClass.printInfo(m). Python's explicit requirement of self as the first argument makes it so that it's clear to people what the difference between instance and static methods are (even though they're different in Python than Java, et al).

(太字は引用者による)

追記 (2011.12.7) : Python で既存のクラスを拡張 を参照。

 

4. 次に読む予定の記事

 

5. 参考

2008年5月17日土曜日

GIMP を使い手動で画像を lomo 風に加工する

1. 印象的な写真が撮れるトイカメラ

最近、トイカメラがブームのためか、猫も杓子も lomo 風で、粗くてコントラスの強い画像を目にすることが多い。やや食傷気味だけれど、やっぱり自分が「おっ!」と思う写真は、 lomo 風であることが多い。

VISTAQUEST

デジタルなトイカメラである VISTAQUEST のトイカメラ を見ると、その筐体のカワイさも相まって、欲しくなる。

Kenko DSC517

トイカメラを検索してみると、Kenko DSC517 で撮影された画像 が個人的には好み。青色がとても印象的な写真だ。しかし、既に販売終了している。パタッ(o_ _)o~†

Vivitar Ultra Wide&slim

デジカメでないのなら、Vivitar Ultra Wide&slim で写したものがよかった。

 

2. lomo風の写真の特徴

lomo 風の写真は、次のような特徴がある。

  1. 色彩が鮮やかで、やや画像が粗い。
  2. 明るいところが極端に明るく、暗いところが極端に暗い。
  3. 周囲に半透明の黒いグラデーションがかかっている。
  4. 特定のスポット (主に中心) が極端に明るい。

GIMP のフィルタを使えば、簡単に lomo 風にすることができる

今回は GIMP の基本的な機能だけを使い、写真を lomo 風にしてみる。

加工するのは以下の写真。

moto

 

3. 画像にメリハリをつける

最初に、「明るいところが極端に明るく、暗いところが極端に暗い」ようになるように調整する。

  • メニューより 色 > カーブ...

を選択し、以下のようにカーブを設定する。

080517-5

画像によっては、真ん中辺りを持ち上げたり、または、下げたりするとよい。

この設定は、GIMP のドキュメント 5.7.  Curves によると、

Main Editing Area
  • The vertical gradient: it represents the the destination, the output tonal scale. It ranges from 0 (black) to 255 (white), from Shadows to Highlights.

チャンネルが「明度」となっているので、下の横軸のグラデーションが、対象の画像の明さの分布を表している。縦軸は、それぞれの明度をどのような値に変換したいかを表す。

例えば、右上の点は、対象の画像の明るい部分を持ち上げ、左下の点は、暗い部分をより暗くしている。

適用した結果、以下のようになった。

moto_curve

 

4. 色彩を鮮かに

次に、lomo と言えば鮮かな青というイメージがあるので、色彩を鮮かに調整する。

  • メニューより、色 > 色相 - 彩度...

を選択し、彩度を少し上げる。

080517-7

これにより、少し青が強くなった感じ。

moto_saido

 

5. 周辺を暗くする

次に、写真の周囲を暗くする。

  1. 新規レイヤーを作成。
  2. 円で選択するツール (Ellipse Select Tool) を使い、画像からややはみだすように円を描く。
  3. 選択を反転する。 (選択 > 反転)
  4. 選択した部分を黒で塗り潰す。 (Bucket Fill Tool)

moto_tunnel

選択を解除して、全体にガウシアンぼかしを強めにかけて、黒い部分をぼんやりさせる。

  • フィルター > ぼかす > ガウシアンぼかし

080517-9

レイヤーダイアログにおいて、モードから「微粒子結合」を選び、不透明度を適当に下げる。

080517-11

これにより、周辺の黒い部分が溶け込んだ。

080517-12

 

6. 中央を明るくする

次に、写真の中央を明るくする。

先ほどと同じく、新規レイヤーを作成する。

中央に白い円を描く。

080517-14

選択を解除し、全体に対して「ガウシアンぼかし」をかける。

080517-15

レイヤーダイアログにおいて、モードを「オーバーレイ」にし、不透明度を適当に下げる。

080517-16

これにより、Lomo 風の写真の出来上がり。

moto_owari

元の画像と並べて比較すると、違いがはっきりと分かる。

moto

 

関連記事

2008年5月15日木曜日

JavaScript のブロックスコープ - Java, Ruby との比較

1. ブロック内の変数のスコープ

Java のブロックにおける変数のスコープ

Java における「ブロック」とは、「Java言語規定 ブロック及び文」によると、

ブロック(Block) は,中括弧で括られた一連の文及び局所変数宣言文とからなる。

ブロック内における変数のスコープは、「14.3.2 局所変数宣言の有効範囲」によると、

ブロック内で宣言された局所変数の有効範囲は,ブロックの残り部分とし,変数そのものの初期化子を含む。局所変数仮引数の名前は,その有効範囲内の局所変数又は例外仮引数として再宣言してはならない。再宣言すると,コンパイル時エラーとなる。

つまり、{ } で囲まれた中で宣言された変数は、そのブロックの内側でのみ有効となる。

 

JavaScript にブロックスコープはない

これに対して、JavaScript では、「Core JavaScript 1.5 Guide:Block Statement - MDC」によると、

 重要:JavaScript にはブロックスコープがありません

えぇ~ (@_@;) こういう風にデザインされている理由って何だろう?実装のしやすさかな?

I don't have any documentation, but I'd guess that ease of implementation is the motivation.

(Block-scope | Lambda the Ultimate より)

 

2. Ruby のブロックスコープ

404 Blog Not Found:LLいろいろ、スコープいろいろ」によると、

このスコープの「レキシカルさ加減」が、実は言語によって結構違うので、この機会にちょっとつっこんでおくことにする。…

… 、pythonもrubyも、この点においてはむしろJavaScriptに近い挙動を示します。(...)

特にrubyのブロック引数がブロックローカルではない点は、オレオレ詐欺に引っかかったようなみじめさを感じさせずにいられません。

Rubyで関数プログラミング Part 6 【ファーストクラスの関数】」にも、同様の指摘がある。

Rubyの関数オブジェクトは、どうやら「関数」オブジェクトではないそうです。つまり、proc(lambda)で作ることのできるオブジェクトとは、(Smalltalk的な)ブロックであるらしく、|x,y|と引数を指定しても、それは仮引数ではなく、ブロック外の同名の変数(つまり、ブロック外のx,yという名の変数)を上書きしてしまうのだそうです。

これに関して、Matzにっき(2005-03-09) の「Ruby 2.0 ブロックローカル変数」に、以下のように書かれている。

Rubyのブロックスコープをなんとかしたいとずっと考えてきた。で、今までにもいろいろなアイディアを練ってきたのだが、なかなか決められなかった。最近になってやっと「これなら」というものが出来上がったように思う。

仕様は以下の通り。

  • ブロックパラメータはローカル変数のみ
  • ブロックパラメータのスコープはブロックローカル
  • ブロックパラメータ名が外側のローカル変数と重複したらエラー(前田くんの勝ち)※
  • ブロックパラメータの後ろに「; 変数」という形でそのブロック内でだけ有効な変数名を指定できる※
  • これらの変数も重複はエラーになる
  • ブロック内で初出の変数のスコープはブロックローカル(今まで通り)※
  • メソッド内で使われたスコープが終わってしまった変数への参照は警告になる※

追記 (2011.12.2) : Ruby 1.9 では、ブロック変数のスコープの仕様が変更された。

第6回 Ruby 1.9に起きた変化 - O'Reilly Japan Community Blog」によると、

Rubyにはブロックというものがあります。縦棒(|)の中に変数があって、(直前に書かれたイテレータの各要素が)渡されパラメータとして代入される。これはもともとループの抽象化として誕生したので、棒の間はループの各要素が代入される場所だったんです。(ブロックパラメータは)任意の変数、つまりグローバル変数でも、ローカル変数でも、配列でも大丈夫。何でも置けたんです。

ところが1.9からはちょっと変わっていて、グローバル変数を置こうとするともうダメ。これまではオブジェクトの属性に代入できたり、配列のスライスを呼び出せたのも、できなくなりました。それと同時に、(ブロックパラメータに指定された)ローカル変数のスコープは、ブロックの範囲内にとどまるということ。

 

3. JavaScript で、変数をブロックスコープのように扱うには、関数を使う

まるごとJavaScript & Ajax ! Vol.1 によると、

JavaScript の変数のスコープは「{}」で囲われたブロック単位ではなく、関数単位になります。(p96)

(function(){
 var tmp = 0;
 for( var i=0; i<10; i++ ){
 // などなど、初期化処理を行う
 }
})();

「(function(){ ~ }」が無名関数の定義になります。その直後に再びカッコ()が置かれているため、その無名関数がその場で実行されるというトリックです。(p97)

同様のことが Block-scope | Lambda the UltimateStatic scoping に書かれている。

 

Greasemonkey において、変数をブロックスコープのようにする方法

 まるごとJavaScript & Ajax ! Vol.1 の「ものぐさな Greasemonkey の飼いかた」の最初のスクリプト(p158)に、以下のようにあったのは、変数をブロックスコープにして実行するための工夫だったのかぁ。

(function () {
 //ここに実際のコードを書く
})();

 

ブックマークレットにおいて、変数をブロックスコープのようにする方法

追記(2008.5.27):

において、参考にした

にも、同様の手法について言及されている。

変数をローカルにするには

無名ファンクションのインスタンスを生成して、これを呼び出すようにするといいようです。

 

4. JavaScript 1.7 の let

New in JavaScript 1.7 - MDC4 Block scope with let には、

The let statement provides a way to associate values with variables, constants, and functions within the scope of a block, without affecting the values of like-named variables outside the block.

として、次のサンプルが挙げられていた。

var x = 5;
var y = 0;

let (x = x+10, y = 12) {
  print(x+y + "\n");
}

print((x + y) + "\n");

2008年5月14日水曜日

JavaScript のハッシュとオブジェクト

ハッシュ

JavaScript の基本は「ハッシュ」。

 {キー:値}

var obj = {'name':'太郎', 'age':18, 'address':'東京'};

上記 obj は、ハッシュのキーによる呼出し、 obj['name'] によって値 「太郎」 を取得できる。一般的なオブジェクト指向言語のプロパティのように、 obj.name によっても値 「太郎」 を取得できる。

(cf. Using Object Initializers - MDC の 「オブジェクト初期化子の使用」 )

プロパティは動的に追加できる。これは新しくハッシュにキーと値を追加したのと同じこと。上記 obj の定義後に、

obj.weight = 60;

とすると、あたかも実行時にオブジェクトの属性が新たに追加されたように見えるが、ハッシュを格納した変数 obj にキー weight : 値 60 の項目を追加したに過ぎない。

Core JavaScript 1.5 Guide:Objects and Properties - MDC によると、

JavaScript におけるプロパティと配列は密接に関連しています。事実、それらは同一のデータ構造への異なるインタフェースなのです。

追記(2008.9.4) : cf. JavaScript でキー入力に応じて HTML の要素の値とスタイルを変化させるのコメントを参照。

 

関数

ハッシュの値 (オブジェクトのプロパティ) として 「関数」 を入れることもできる。

obj.hello = function(){return 'こんにちは、' + this.name + 'です。'};

obj.hello(); // こんにちは、太郎です。

上記は無名の関数を定義したところ。

関数を呼出すときは

()

を忘れないように。 () がないと、関数自身を指すことになる。

this

は関数を持つオブジェクト自身を指す。関数を保持するオブジェクトによって変化する。

注意すべきは、関数がオブジェクトに対して定義されていること。 Java のクラスのように、生成するオブジェクトの雛形として関数を定義しているわけではない。

obj.hello() 

obj['hello']() 

でも呼出せる。 () が関数を評価するという意味があるようだ。

 

コンストラクタ関数

オブジェクトの初期化子とは異なる方法でオブジェクトを生成することができる。下記はコンストラクタ関数を利用して、オブジェクトを生成。この書き方は Java のようにクラスを定義して、オブジェクトを作るのに似ている。

function Obj(name, address, age){
    this.name = name;
    this.address = address;
    this.age = age;
}

var a = new Obj("Tarou", "Tokyo", 20);

追記(2008.9.4) : コンストラクタ関数の覚え方。普通に関数を書くように書く。ただし、ローカル変数を this で修飾するだけ。関数名がクラス名に相当する。


prototype

コンストラクタ関数 Obj から生成したオブジェクト全てに作用するプロパティを追加したい場合は、 prototype を利用する。クラスベースのオブジェクト指向言語におけるクラス定義の方法を真似ている。

先ほどの Obj にプロトタイプのプロパティ hello に関数を定義してみる。

Obj.prototype.hello = function(){
   return "こんにちは、" + this.name + "です。" ;
        }
a.hello();

 

関連記事

2008年5月13日火曜日

Google ドキュメントで見出しの体裁を整える - CSS を使って

1. 見出しに色をつけて、目立たせたい

Google ドキュメントで、文章の構造を明確にしたい場合、「見出し」を使う。

当初、見出しを目立たせるために、見出しの背景色を手動でつけていた。一つ一つ指定しなくてはならなかったので面倒で非効率。しかし、今では CSS で一括指定することができる。

 

2. CSS により指定する方法

メニューより、編集 > CSS を編集

080513-2

表示されたダイアログに、以下の CSS を貼り付ける。色については、カラーコード & 配色シミュレーション を利用して決めた。

h1 {
 background-color: #ffe3dd;
 padding: 0.2em;
}
h2 {
 background-color: #ddedff;
 padding: 0.2em;
}
h3 {
 background-color: #ccffd2;
 padding: 0.2em;
}
h4 {
 border-bottom: 1px dotted;
}

 

3. CSS を適用した結果

表示形式より、見出しを選択すると、背景色がついて見やすくなった。 ^^

080513-3

飽きたら、別のことを徹底的にやる

A:

「どうも、今やっていることがつまらなく感じようになってしまった。

同じことを繰返しているだけだ。

はじめに取り掛かったときの新鮮さがない。

いつも同じところをループしている感じと言えばいいのか...

どうすればいいのだろう?」

B:

「飽きたら、それをやめる。

多分、頭の中が飽和してるんだ。

同じことを同じ方向でばかり見ているから、視点が固定される。

 

そういったものを、意識化しようとしたり、また、意識的にずらそうとしても無駄だよ。

想像している以上に、自分の思考というものはコントロールできない。

思考が自分のものだと思っているのなら、それはあまりにもオメデタイ。

言語の流れの上に乗っている帆船のように思った方がいい。

 

思考が飽和している状態で進めても、よい結果は得られない。

だから、全く別のことをするんだ。

それも、徹底的にね。

「何か今やっていることにつながるかもしれないから」なんて欲を出してやらない方がいい。

 

新しいことに飽きたら、多分、また同じ場所に戻ってきたくなるさ。

あくまで、自然に戻りたくなるのを待つこと。

そうすれば、別の風景が見えてくる。

そして、そこが同じ場所ではないことに気がつくのではないかな。」

2008年5月9日金曜日

Windows で Ruby

インストール

本家ダウンロード によると、

One-Click Ruby Installer for Windows (英語) 安定版に多数の便利なライブラリを加えたもの。ベースはmswin32版

これがお手軽に設定してくれそう。

[one-click, self-contained Windows installer] から ○○ Final Release をダウンロードし、インストール。

080509-2

 

パスの設定

スタート > 「マイコンピュータ」で右クリック > プロパティ

詳細設定 > 環境変数 > システム環境変数 の Path に c:\ruby\bin; を追加する。

080509-1

 

エディタ の設定

cf. サクラエディタ で Ruby

 

ダブルクリックで実行

コマンドプロンプトや、IDE の下でスクリプトを実行することができるが、 アイコンをダブルクリックして実行したい。

例えば、 「hoge という名前のフォルダを作成する ruby スクリプト」がある場合、 .rb という拡張子をつけてスクリプトを保存する。

Dir::mkdir("hoge")

このファイルをダブルクリックすると、上記のスクリプトが実行され、 hoge というフォルダが作成される。だだし、 hoge というフォルダが既に作成されていた場合、スクリプトを実行しても、コマンドプロンプトが一瞬表示されるだけで、スクリプトを実行した結果どうだったのかわからない。

バッチファイル

バッチ処理をするためのファイルを作成し、その最後に pause という命令を書いておくと、実行した際に、すぐに消えてしまうコマンドプロンプトを表示させておくことができる。先ほど作成したスクリプトの名前が makehoge.rb だとすると、 makehoge.rb.bat のように、最後に .bat をつける。

ruby makehoge.rb
pause