ラベル スクリプト の投稿を表示しています。 すべての投稿を表示
ラベル スクリプト の投稿を表示しています。 すべての投稿を表示

2012年9月10日月曜日

Windows でコントロールパネルの項目を設定するスクリプト – Windows Script Host を利用し JScript によるバッチ処理を行う

1. コントロールパネルの値を設定するためのスクリプト

Windows のコントロールパネルをスクリプト(バッチ処理)により設定したい。

SnapCrab_コントロール パネル_2013-3-1_9-37-52_No-00

コントロールパネルの項目は、設定したい項目を起動した後、キーボードの操作により設定できることが多い。以下は、そのための JScript による関数。

var setControlPanel = function(cmd, title, keystrokes){
    var WshShell =  WScript.CreateObject("WScript.Shell");
    WshShell.Run(cmd);
    do {
        WScript.Sleep(100);
    } while(!WshShell.AppActivate(title));
    WshShell.SendKeys(keystrokes);
};

 

関数の説明

関数 setControlPanel の第1引数は、コントロールパネルの項目を起動するためのコマンドを与える。起動できる対象は、以下を参照。

各項目を起動するためには、control を付ける必要がある。

第2引数は、起動したコントロールパネルの項目の、ウィンドウタイトルを与える。

第3引数は、起動したコントロールパネルの項目に対して、キーボードの操作により設定を行うための一連のキー入力を与える。キー入力の方法については、SendKeys メソッド を参照。

上記を setControlPanel.js と名前を付けて保存する。

 

2. スクリプトの使い方

例えば、マウスの左右のクリックを入れ替えるには、

setControlPanel("control main.cpl",
                "マウスのプロパティ",
                "{+}^{TAB}{HOME}{DOWN}{ENTER}");

サウンドのデバイスを切り替えるには、

setControlPanel("control mmsys.cpl",
                "サウンド",
                "{DOWN 2}%{s}{TAB 3}{ENTER}");

電源のプロファイルを変更するには、

setControlPanel("control powercfg.cpl", 
                "電源オプション", 
                "^{f}{TAB 11}{DOWN}%{F4}");

この例の場合、最初に、検索フィールドをアクティブにしないと、正常にキー入力がされなかった。

 

3. ショートカットからスクリプトを起動する

コントロールパネルの項目を設定する各々のスクリプトは、独自に作成する必要はない。

  1. 以下のコードをを上記のスクリプトに追加し、
  2. そのショートカットを作成して、
  3. 引数を与えることによりスクリプトを起動できる。

SnapCrab_NoName_2013-3-1_10-1-57_No-00

setControlPanel(WScript.Arguments.item(0),
                WScript.Arguments.item(1),
                WScript.Arguments.item(2));

ショートカットのプロパティを開き、リンク先には、

C:\Windows\System32\wscript.exe [スクリプトへのパス] [引数...]

を入力する。

 

ショートカットアイコンのカスタマイズ

ショートカットに独自のアイコンを設定したい場合は、以下を参照。

 

wscript.exe で起動しないときの注意点

追記(2013/03/01): 上記で作成したショートカットは、wscript.exe で起動しなくてもスクリプトは実行される。

ただし、JScript ファイルを実行すると、スクリプトが実行されず、スクリプトを編集するためのアプリケーションが起動することがある。それは、拡張子が .js であるファイルを当該アプリケーションに関連付けてしまった場合に起こる。

SnapCrab_NoName_2013-3-1_9-54-1_No-00例えば、Aptana をインストールし、.js ファイルをアプリケーションに関連付けると、以後、上記のスクリプトは Aptana で開かれてしまう。

このときは、必ず wscript.exe でスクリプトを起動するようにしておく。

 

4. スクリプトの内容について

コントロールパネルの項目が起動していることを確認するために、AppActive メソッドを利用した。

@IT:運用 Windows管理者のためのWindows Script Host入門 第5回 WshShellオブジェクトの詳細(1) 4.キー・ストロークの送信とプログラムのアクティベーション によると、

AppActivateメソッドは、実行に成功すればTrueを、失敗すればFalseを返す。この戻り値を利用して、成功するまで待つことができる。

ループについては、JScript のプログラム フロー制御 を参照。

2012年9月8日土曜日

Windows でマウスの左右ボタンを入れ替えるスクリプト(2) - マウスポインタの表示も変更

Windows でマウスの左右ボタンを入れ替えるスクリプト のつづき

1. マウスポインタの形状も変更する

マウスポインタの矢印の形は、左斜め上に傾いている。これは右手で操作することを前提とした形状。そのため、この形のまま左手でマウスを操作すると違和感を感じる。

左手でマウスを操作するときは、マウスポインタの矢印の形が右斜め上に傾いていて欲しい。

そこで、マウスの左右を入れ替えるスクリプトに、マウスポインタの形状を変更する処理を追加した。ただし、左手用のマウスポインタ画像は既に追加してあるとする。

var setControlPanel = function(cmd, title, keystrokes){
    var WshShell =  WScript.CreateObject("WScript.Shell");
    WshShell.Run(cmd);
    do {
        WScript.Sleep(100);
    } while(!WshShell.AppActivate(title));
    WshShell.SendKeys(keystrokes);
};

setControlPanel("control main.cpl",
	"マウスのプロパティ",
	"{" + WScript.Arguments.item(0) + 
		"}^{TAB}{HOME}{DOWN " +
		 WScript.Arguments.item(1) +
		 "}{ENTER}"
);

 

2. スクリプトを実行するためのショートカット

左手用

スクリプトを実行するために、

  1. 上記コードを changeMouseButton.js と名前を付けて保存する。
  2. changeMouseButton.js のショートカットを作成し、Click-Right と名前を変更する。
  3. ショートカットのプロパティを開き、「ショートカット」タブのリンク先の末尾に + 1 を追記する。

… \changeMouseButton.js + 1

最後に、ショートカットのアイコンを Arrow, Right, Small icon に変更した。

これにより、ショートカットをクリックすると、マウスクリックが左利き用に変更される。

ショートカットは、クイック起動で起動できるようにした。

 

右手用

右手用に戻すために、上記と同じ手順でショートカット作成し Click-Left と名前を変更し、ショートカットのリンク先の末尾を – 2 とする。

… \changeMouseButton.js – 2

アイコンは、Arrow, Right, Small icon を利用した。

 

3. スクリプトの内容について

スクリプトで行なっている内容は、コントロールパネルにおける「マウスのプロパティ」を開き、キーボードで設定を変更する操作をスクリプトで代行している。

キー入力を行うには、SendKeys メソッド を利用する。

マウスを左利き用に変更するキー入力は、

{+}^{TAB}{HOME}{DOWN}{ENTER}

右利き用に戻すキー入力は、

{-}^{TAB}{HOME}{DOWN 2}{ENTER}

ショートカットを作成しているのは、スクリプトを起動するときの引数で、上記のキー入力を指定するため。

チェックボックスに対するキーボード操作に関しては、以下を参照。

 

関連記事

2012年8月19日日曜日

Windows でマウスの左右ボタンを入れ替えるスクリプト

1. 左手でマウスを操作する場合、ボタンの左右を入れ替える

左手でマウスを操作する場合、マウスクリックの左右を入れ替えた方が使いやすい。マウスを左右どちらの手で扱えるように練習しておくと、疲れたときに持ち替えることができる。

Windows で、マウスのボタンを入れ替えるには、

  • コントロール パネル > ハードウェアとサウンド > マウス

の「ボタン」タブで、「主と副のボタンを切り替える」にチェックを付ける。

SnapCrab_マウスのプロパティ_2012-8-19_20-32-43_No-00

 

2. マウスのボタンを入れ替えるスクリプト

左右の持ち替えをよく行う場合、毎回マウスのプロパティを切り替えるのは面倒。そこで、マウスボタンを切り替えるためのスクリプトを作成した。

下記のリンク先を保存し、ボタンの左右を切り替えたいときにクリックする。

アイコンを付けたい場合、以下を参照。

追記(2012/08/22)左マウス, 左利き用マウス を使うと、左右のボタンを変更し、アイコンの表示も変更してくれる。

 

3. スクリプトについて

スクリプトは、以下を元に作成した。

var WshShell = WScript.CreateObject("WScript.Shell");
WshShell.Run("control main.cpl");
WScript.Sleep(500);
WshShell.AppActivate("マウスのプロパティ");
WScript.Sleep(500);
var Keystrokes = " {ENTER}"
WshShell.SendKeys(Keystrokes);

マウスのプロパティを起動するには、

@IT:Windows TIPS -- Knowledge:コントロール・パネル・アイテムをコマンドラインから呼び出すによると、

マウス
main.cpl
control MOUSE

スペースキーをキーとして入力するには、

WSH JScriptを使いこなそう ~キーボード操作~によると、

Space	
" "
半角スペース

Windows でマウスの左右ボタンを入れ替えるスクリプト(2) - マウスポインタの表示も変更 につづく…

2011年3月8日火曜日

Scala の List クラスで map, filter, foldRight と シーケンス内包表記

1. Scala の覚えやすそうな点と、すぐに忘れそうな仕様

Scala に興味を持った理由は、「今からでも遅くない これから始めるScala(前編)」 で挙げられていた以下の特徴による。

  • オブジェクト指向と関数型言語の特徴を組み合わせています。Scalaでは、関数をオブジェクトとして扱うことができますし、高階関数も利用できるなど、関数型言語からさまざまな特徴を取り入れています。
  • Scalaは静的型付け言語ですが、型推論によって型の記述を省略することができます。変数や関数の宣言時に、コンパイラが型を推論してくれるため、型の指定をいちいち行わなくてもよいのです。
  • Trait(トレイト)という、実装を持つことができるインターフェイスを利用して、Mix-Inができます
  • 暗黙の型変換(implict conversion)などを利用して、DSL(ドメイン固有言語,Domain-Specific Language)を作成しやすくなっています。
  • マルチコア時代を意識した、分散処理ライブラリ(Actorライブラリ)が用意されています。

(太文字は引用者による)

久しぶりに本を購入して読んでいる。しかし、いつもの如く頭に入らないし、覚えたものは身に付かず抜けていく。

Scala は、統一されていて覚えやすい仕様もあれば、「何だかごちゃごちゃしていて忘れること間違いなし」と感じるところもある。結果として見やすくなるコードのために覚えておくルールの多さに圧倒されてしまったり。。 (+_+)

Guido van RossumNeopythonic: Scala? で次のように述べている。

Perhaps my biggest disappointment in Scala is that they have so many rules to make it possible to write code that looks straightforward, while being anything but -- these rules all seem to have innumerable exceptions, making it hard to know when writing simple code will work and when not.

 

a. Haskell の関数と似た名前のメソッド名

Scala は関数型の特徴を持ち合わせている。しかも型推論をしてくれる。しかし、「Haskell ではこう書けるのに、何で Scala はだめなんだろう?」と疑問を抱くことがある。例えば、

  • メソッドの引数は必ず型を指定しないといけない。

Haskell で関数を定義するとき、引数の型を省略しても型を推論してくれる。

Prelude> let add x y = x + y

Scala では引数の型を指定しなくてはならないので面倒。 (+_+)

scala> def add(x:Int, y:Int) = x + y

この辺り、オブジェクト指向と折衷しているのが理由なのだろうか?スクリプトを書くのにお手軽に使えると期待していただけにちょっと残念。

ところで、Haskell との比較で言えば、関数名が似ているのはなぜだろう?例えば、Haskell でリスト操作に不可欠な、

  • map
  • filter
  • foldr

(cf. Prelude, Data.List)

各々の言語でこれに対応した関数、メソッドを比較すると、

Python map filter reduce 2.1 組み込み関数
Ruby collect, map find_all, select inject Enumerable
Scala map filter foldRight, :\ scala.collection.immutable.List 

これを見ると Haskell の関数名に Scala が一番似ていて、次に Python 。Ruby のメソッド名はかなり異なる。

scala.collection.immutable.List  には、上記以外にも類似したメソッドが見受けられる。もちろん、Python でも関数型プログラミングを意識したモジュールには似た名前の関数が定義されているけれど。

Scala と Haskell の言語設計者は何か関係でもあるんだろうか?

Scala の設計者である Martin OderskyThe Origins of Scala で次のように述べている。

Bill Venners: How did Scala come about? What is its history?

Martin Odersky: Towards the end of my stay in Zurich, around 1988/89, I became very fond of functional programming. So I stayed in research and eventually became a university professor in Karlsruhe, Germany. I initially worked on the more theoretical side of programming, on things like call-by-need lambda calculus. That work was done together with Phil Wadler, who at the time was at the University of Glasgow. One day, Phil told me that a wired-in assistant in his group had heard that there was a new language coming out, still in alpha stage, called Java. This assistant told Phil: "Look at this Java thing. It's portable. It has bytecode. It runs on the web. It has garbage collection. This thing is going to bury you. What are you going to do about it?" Phil said, well, maybe he's got a point there.

The answer was that Phil Wadler and I decided take some of the ideas from functional programming and move them into the Java space. That effort became a language called Pizza, which had three features from functional programming: generics, higher-order functions, and pattern matching. Pizza's initial distribution was in 1996, a year after Java came out. It was moderately successful in that it showed that one could implement functional language features on the JVM platform.

(太字斜体は引用者による)

一緒に仕事したという Philip Wadler と言えば、The Haskell 98 Language Report Preface に名前があるように、Haskell の言語仕様を決める委員会の editor であり、Glasgow Haskell Compiler 発祥の University of Glasgow で教授をしていた人物。「モナドって何?」と調べていれば行き当たるであろう Monads for functional programming の著者。

… ということは、関数名が Haskell に似ていたとしても、あながち偶然でもないということだろうか?

 

b. 他によく似た名前の関数を持つ言語は?

Scala が影響を受けた言語について調べてみると、

Java, Pizza, Haskell … と順にある。

Fold (higher-order function) - Wikipedia には fold 系の関数の各言語の一覧が載せられている。この中で Scala の foldRight に似ている名前を持つ言語は Ocaml と Scheme 。それぞれ関数名は fold_rightfold-right

  • List より : map, filter, fold_right
Scheme は、

うーん、こちらの方が名前は似てるなぁ。結局、どの言語が一番影響を与えて関数名が決まったんだろう???

 

それはさておき、リスト操作における重要な関数である、

で練習した関数を Scala でも手を動かして覚えることに。 (+_+)

 

c. Meadow で Scala のスクリプトを実行

… とその前に、「オブジェクト指向プログラマが次に読む本 -Scalaで学ぶ関数脳入門」には Scala の実行方法として以下の 3 つが挙げられていた。

  • シェルで対話的に実行する
  • スクリプトを記述して実行する
  • プログラムを記述して実行する

対話的というのは REPL のことで、ちょっと試したいときに使う。それ以外は main メソッドを持つシングルトンオブジェクトを書いてコンパイルして実行しないといけない思っていた。その中間に位置する実行方法があったのに気づかず。。 (+_+)  これからはスクリプトとして書いて実行してみよう。

( cf. Getting Started with Scala の Script it! )

以前、エディタで Scala を実行する方法をいくつか見た。

やはり、Meadow を使っていこうかな。

方法は、

  1. REPL を使うときのようにエディタに書いて
  2. M-x scala-run-scala を実行
  3. C-c C-l でスクリプトを実行。

( cf. EmacsでつくるScala開発環境 前編(scala-mode) - tototoshiの日記 )

 

2. map

まずは、リストの要素を 2 倍にすることから。

Haskell で書くなら、

Prelude> let l = [1..5]
Prelude> map (\x –> x * 2) l

セクションを利用すると、

map (*2) l

 

a. map メソッドにおける型変数

map メソッドの型を見ると、(scala.collection.immutable.List)

def map [B] (f: (A) ⇒ B) : List[B]

メソッドで型変数 B が宣言されている。

なぜこの型変数 B が書かれているのかと言えば、List クラスの型変数 A

class List [+A] …

はリストの要素の型を表しており、map メソッドの引数で要素を変換する関数、

f: (A) ⇒ B

により、元の要素の型とは異なる型になる可能性があるため。(型変数の前に `+’ が付いている意味は横に置いておく。)

この辺り、Java で似たような実装を試したときを参考に。

とりあえず、map メソッドを使う分には詳細を理解する必要はない。

 

b. 無名関数と引数の型を省略

Scala で無名関数を定義するときは、以下のような形式。

(引数:型) => 式

例えば、数値が与えられたら 2 倍する関数を定義するなら、

val f = (x:Int) => x * 2

Haskell で

–>

と書くところを

=>

とすることに注意。また、面倒だけれど、無名関数の引数は型を指定しなければならない。

リストの要素を 2 倍するには、

val l = List(1,2,3,4,5)
l.map((x:Int) => x * 2)

(以下、上記変数 l を使う。)

map 関数の引数として無名関数を与えると、引数の型をしなくてもよい。

l.map((x) => x * 2)

これは変数 l が

List[Int]

という型であり、リストの要素が Int 型だとわかることを利用して、先ほどの map メソッドに当てはめると、

def map [B] (f: (Int) ⇒ B) : List[B]

となり、map メソッドの第1引数の関数の引数の型を推論できるため。

ついでに、引数が 1 つだと ( ) も省略できる。

l.map(x => x * 2)

 

c. 無名関数の引数の省略

また、Haskell のセクションに似た書き方も用意されている。無名関数の引数は、

_

で代用できるので、

l.map(_*2)

 

d. メソッド呼び出し . の省略

それから、メソッドの呼び出しである . も省略できる。

l map (_*2)

シンプルに書けたけれど、ここまでの道程が長い。。(+_+)

 

e. 変更可能なリストを利用する場合

ところで、上記のリストは変更不能な (imutable) リストを利用した。 Scala ではこの使用が推奨されている。

これに対して、変更可能なリストを使いたい場合は、

  • scala.collection.mutalble

を使う。

scala.collection.mutable.LinkedList の要素を追加するメソッド は

def :+ (elem: A) : LinkedList[A]

これを利用すると、

import scala.collection.mutable.LinkedList

var result = LinkedList[Int]()
for (e <- l){
  result = result.:+(e * 2)
}
println(result)

変更可能な変数は var を使って宣言。

result 変数を更新している箇所は、以下のように置き換えることができる。

result = result :+ e * 2

更に省略するなら、

result :+= e * 2

慣れないと、なぜこういう風に書けるのかわからなくなってしまうけれど。 ^^;

 

f. シーケンス内包表記

The Scala Language Specification には、

For Comprehension

と書かれており、A Tour of Scala では Sequence Comprehensions とある「シーケンス内包表記」。

List comprehension - Wikipedia に for と yield を使った説明がされていることより、

「リスト内包表記」

と同じような機能を持つようだ。これを使うなら、

for (e <- l) yield e * 2

Ruby の yield や、Python の yield と同じ予約語名なので頭の中が混乱してきた。。 (+_+)

 

3. filter

次に、filter メソッド。型を見ると、引数に述語 (predicate) を与えれば良いことがわかる。

(cf. scala.collection.immutable.List, Haskell の Prelude 散策 (2) - 述語)

def filter (p: (A) ⇒ Boolean) : List[A]

map メソッドと同じように徐々に省略できるところを省いていくと、

val l = List(1,2,3,4,5)
l.filter((x:Int) => x > 3)
l.filter((x) => x > 3)
l.filter(x => x > 3)
l.filter(_>3)
l filter (_>3)

シーケンス内包表記では、

for (e <- l; if e > 3) yield e

( ) を使わずに { } で書くと ; も省略できる。

for { e <- l
      if e > 3
} yield e

他の言語における for とちょっと違うので、混同しないように注意が必要。

 

4. foldRight

最後に、リストの値を集約する foldRight メソッド。(scala.collection.immutable.List)

def foldRight [B] (z: B)(f: (A, B) ⇒ B) : B

map, filter メソッドと違い引数が 2 つ。しかも、それぞれの引数が独立しているように見える括弧の書き方。

以下のようなシグニチャでないことに注意。

def foldRight [B] (z: B, f: (A, B) ⇒ B) : B

各々の引数を括弧で括る書き方は、Scala におけるカリー化の手段。引数のリストがあると言えばいいのかな?

カリー化とは、Chapter 8. Functional Programming in Scala によると、

… currying transforms a function that takes multiple parameters into a chain of functions, each taking a single parameter.

In Scala, curried functions are defined with multiple parameter lists,

def cat(s1: String)(s2: String) = s1 + s2

Of course, we could define more than two parameters on a curried function, if we like.

(太字は引用者による)

メソッドの引数が複数の括弧 ( )  で囲まれている様は、「複数の仮引数のリストを持っている」と言えば良いみたい。つまり、メソッドの引数の括弧が一つというのは、引数の書き方としては特殊な一例に過ぎないと。括弧ごとにメソッドの呼び出しを行うことができ、残りの引数を順に与えていき、最終的に全体の関数と同じ関数の連鎖が生まれる。

foldRight の場合で言えば、

リスト.foldRight(値)

により、foldRight の第 2 引数を受け取る関数が生成される。

では、foldRight を使って、要素を全て足す計算をしてみる。先ほどと同じく、徐々に省略した書き方をすると、

val l = List(1,2,3,4,5)
l.foldRight(0)((x:Int, y:Int) => x + y)
l.foldRight(0)((x,y) => x + y)
l.foldRight(0)(_+_)
(l foldRight 0)(_+_)

 

a. 別名 :\

foldRight と同じ機能のメソッドとして :\ がある。

def :\ [B] (z: B)(op: (A, B) ⇒ B) : B

なぜこんな形のメソッドがわざわざ定義してあるかと言えば、以下の foldr を説明した図を見れば一目瞭然。

http://en.wikipedia.org/wiki/Fold_(higher-order_function)

Fold (higher-order function) - Wikipedia, the free encyclopedia via kwout

上記と同じ計算をするなら、

l.:\(0)(_+_)
(l :\ 0)(_+_)

これまた慣れないと読みずらい。

 

b. foldLeft と /:

foldRight はリストを右 (末尾) から左 (先頭) へと計算を進めるのに対して、foldLeft は左 (先頭) から右 (末尾) へと計算を行なう。

(l foldRight 100)(_-_)    // (1-(2-(3-(4-(5-100))))) => -97 (l foldLeft 100)(_-_)     // (((((100-1)-2)-3)-4)-5) => 85

foldLeft の別名は /: 。foldRight の :\ とは対照的。

(l :\ 100)(_-_)
(100 /: l)(_-_)

: で終わるメソッド名は右結合なので、第1引数を左に置く。この例外的なルールにより、左から計算を畳み込んでいく様をコードから連想できるようになっている。

. によるメソッドの呼び出しで書くなら、

l./:(100)(_-_)

こういう例外的なことが存在することが良いことなのか悪いことなのか。うーん…

 

c. reduceRight とreduceLeft

Haskell では foldr の第2引数がなく、リストの要素のみに二項演算子を適用していく関数名は foldr1 。

Prelude> foldr1 (+) [1..5]
15

scala には foldRight1 というメソッドはなく、reduceRight が代わりに存在する。

l reduceRight (_+_)

当然ながら、対照的な reduceLeft もあり。

l reduceLeft (_+_)

 

d. map , filter を foldRight で書き直し

次に、map メソッドで要素を 2 倍した関数を foldRight で書き直したい。

Haskell では以下のように書ける。

Prelude> foldr ((:).(*2)) [] [1..5]
[2,4,6,8,10]

Scala では空リストを Nil で表現する。

scala.collection.immutable.Nil

object Nil extends List[Nothing] with Product

これを利用して、以下のように書けばいいのかと思いきや、エラーとなる。 (+_+)

(l foldRight Nil)(_*2::_)

エラーがでないようにするには、foldRight の第1引数の型を明示する。

(l foldRight List[Int]())(_*2::_)

理由は、Programming in Scala (p326) によると、

Generally, when tasked to infer the type parameters of a polymorphic method, the type inferencer consults the types of all value arguments in the first parameter list but no arguments beyond that.

(太字は引用者による)

メソッドの型推論は、仮引数のリストのうち、最初の実引数を調べることによって行われるようだ。

foldRight の型で言えば、

def foldRight [B] (z: B)(f: (A, B) ⇒ B) : B

引数 z を元に型推論が行われる。

Nil の型について :: メソッドを使って調べてみると、

scala> Nil
res0: scala.collection.immutable.Nil.type = List()

scala> 1::2::3::Nil
res1: List[Int] = List(1, 2, 3)

scala> "hoge"::"piyo"::"fuga"::Nil
res2: List[java.lang.String] = List(hoge, piyo, fuga)

:: メソッドに与える引数の型により、返り値の型が決まる。

ところで、foldRight の第1引数 z の型変数は B と書かれており、リストの要素から型を決めることができない。仮引数 z に Nil を与えても型が決まらない。だから、型を指定しなければならないということかな。

(l foldRight List[Int]())(_*2::_)

この場合の foldRight の型は以下のような感じ。

def foldRight(z: List[Int])(f: (Int, List[Int]) ⇒ List[Int]) : List[Int]

ごちゃごちゃしていて頭混乱するなぁ~。

 

map の定義

map 関数を foldRight メソッドを使って定義するなら、

def mymap[A,B](l: List[A], f:(A) => B) :List[B] = (l :\ List[B]())(f(_)::_)

Haskell では、型を明示しなくても推論してくれるのでシンプルに書ける。

mymap f = foldr ((:).f) []

 

filter の定義

filter メソッドを使った 3 以上要素を抽出する関数を :\ メソッドで書き直すなら、

(l :\ List[Int]())((x,y) => if (x>3) x::y else y)

filter メソッドを :\ メソッドを使って定義するなら、

def myfilter[A](l: List[A], p: (A) => Boolean) :List[A] = 
  (l :\ List[A]())((x,y) => if (p(x)) x::y else y)

Haskell なら、

myfilter p = foldr (\x y -> if p x then x:y else y) []

 

5. その他

a. Range で数値のリストを生成

ついでなので、範囲を表わす scala.collection.immutable.Range を使い、1 から 10 まで足してみる。

((1 to 10) :\ 0)(_+_)
(1 to 10) reduceRight (_+_)
(1 to 10) sum

 

b. ブロックを使って副作用

純粋関数型でないメリットは、変数の更新や副作用を簡単に書けること。( それがバグの温床にもなるけれど… )

ブロック { } を foldRight で用いると計算途中の値を出力できたりする。ブロックは最後の式の値が返されるので、以下のように書くと、計算途中の変数の値を出力可能。

((1 to 5) :\ 0){ (x,y) =>
  println(y)
  x + y
}

結果は、

0
5
9
12
14
res647: Int = 15

これは Ruby の inject メソッドを書くときに似ている。

puts (1..5).inject(0){ |x,y|
  puts x
  x + y
}

実行すると結果は、

0
1
3
6
10
15

あ~、Ruby の inject メソッドは左から右へと畳み込んでいくんだったか。つまり、Scala で書くと、

(0 /: (1 to 5)){ (x,y) =>
  println(x)
  x + y
}

2008年1月3日木曜日

Gimp でスクリプト (Script-Fu) をインストールする

1. スクリプトのインストール先を設定

Gimp のメニューから

  • ファイル > 環境設定

を選択する。

080103-007

「環境設定」の左側のペインで、

  • フォルダ > スクリプト

を選択すると、スクリプトの保存先のフォルダが表示される。

デフォルトでは、「ユーザのホームディレクトリにあるフォルダ」と、「GIMP をインストールしたフォルダ」内の script フォルダが表示されていた。

  • C:\Documents and Settings\ユーザ名\.gimp-2.4\scripts
  • C:\Program Files\GIMP-2.0\share\gimp\2.0\scripts

080103-006

 

2. スクリプトをインストール

スクリプトファイルを、上記のフォルダに入れる。

  • メニューの 拡張 > Script-Fu > スクリプトリフレッシュ

を選択して、スクリプトを有効にする。

080103-008

スクリプトのドキュメントを読み、メニューのどこに表示されるようになったか確認する。