2011年2月14日月曜日

nScript講座 第14回



さて、と。
前回の続きということでやります。

が、今回結構相当便利で重要なことをやります。
Pine自身も理解するのに結構かかってます。
現にやっと今日わかりましたから。

てなわけで、わかったところでさっそく記事にしちゃおうと思います!!
ではサンプルを見てください。



////term.ns////////////////////////////////
#import (*.ns);

var cmd;

Function main() {
puts(" Hello Terminal!!\n\n");
while(1) {
puts(" >");
cmd=gets(10);

//ここから
// switch(cmd) {
// case "pwd":
// pwd.main();
// break;
//
// case "exit":
// break 2;
//
// default:
// puts("Can't find command\n");
// break;
// }
//ここまでが前回の形

exec_flag = all.?(cmd);
if (exec_flag==1) continue;
puts ("Command %cmd% is not found\n");

}
}
////pwd.ns//////////////////////////////////
ArgMatch main("pwd") {
puts("%GetCurrentDirectory()%\n");
}
//////////////////////////////////////////////////


はいここまでです。
メインスクリプトのmain関数をコメントなしにまとめると、
//////////////////////////////////////////////////////////////
Function main() {
puts(" Hello Terminal!!\n\n");
while(1) {
puts(" >");
cmd=gets(10);
exec_flag = all.?(cmd);
if (exec_flag==1) continue;
puts ("Command %cmd% is not found\n");
}
}
/////////////////////////////////////////////////////////////
となります。
かなり短くなってますよね?
それこそコマンドを十数個にふやしてる場合には限りなく有効的です。
その代わり何が問題かって、それはやっぱり......


・pwd.nsの関数の定義がArgMatchではじまる
・all.?()というわけのわからない記述がある
ことの二つでしょう。


今回学ぶことはかなりnScript限定の書き方になっています。
他の言語でこの機能がついた言語はみたことがないので。
また、製作者であるnakkaさんもこれを特徴の一つとしています。


ずばり、名前から教えましょう。


これは「引数検索」という方法で関数を呼び出しています。
この名前がヒントとなっています。


引数検索とは、引数検索を掛けられるように定義された関数に対して、指定された
文字列でマッチする引数を持つ関数がないかを検索し、マッチした関数を実行する
という、とても画期的な関数呼び出し方法なのです。
このとき、引数検索を掛けられる形式で関数を定義しなければなりません。
しかし定義の仕方は普通の関数と大して変わりません。
ArgMatch 関数名(文字列,引数....) {
という記述から関数を書き出せばそれが引数検索用の関数になります。
引数は、第二引数以降からは普通の引数を定義できます。
そして、普段第一引数を記述する部分には、文字列を用意しておきます。
ArgMatch func("func",n1,n2) {
と、いう感じで使います。
この関数を呼び出すためには、引数検索でfuncという文字列をかければヒットします。
で、引数検索で関数を呼び出すときはどうやって呼び出すかというと、
?(検索文字列,n1,n2);
と記述すればいいわけです。


?()の秘密はわかりましたが、その前につくall.がわかりませんよね。
前回を思い出してください.......
スクリプト名.関数名()
と記述することで、外部スクリプトから関数を呼び出すことができましたね?
このとき、スクリプト名の部分をall、つまりすべてに置き換えることで、すべての外部
スクリプトの中から関数を探してきて実行できるのです。
ちなみに前回のスクリプトのスクリプト名.main()のようになっていたところをallにすると
どのようになるかというと、main()は複数のスクリプトの中にあるので即ち何回も検索
にヒットするということになりますよね?main()という関数がじゃんじゃんみつかります。
このとき、決してエラーになったりはしません。
main()が見つかった順番に、その関数を実行していきます。ですから言わずもがな
変な動作にはなります......w
まあ、とりあえずこの事実は抑えといてください。


これでall.と?()の秘密がわかりました。
これら二つの記述を組み合わせることによって、
all.?(cmd)
という記述が完成するわけなのです。


この記述は、「すべての外部スクリプト対象に引数検索でcmdの文字列にヒットした
関数を呼び出して、実行する」という意味になります。
そしてこの呼び出し方をすると、ヒットしたときにヒットした個数を返してくれます。
ですから、外部スクリプトの中から一つだけヒットする今回のスクリプトでは、ヒット
すると1を返して、ヒットしないと0を返すという呼び出し方に応用できます。
それを呼び出した後でexec_flagに代入、if文で判定し、その後のコマンドが
見つかりませんでしたという表示につなげています。

exec_flag = all.?(cmd);
if (exec_flag==1) continue;  //関数がヒットしたらここが実行されて、whileの先頭へ
puts ("Command %cmd% is not found\n");  //ヒットしなかったら結果を出力。
ということです。さらにスマートな書き方をするならば、
if (all.?(cmd)==1) continue;
puts ("Command %cmd% is not found\n");
という風に関数の返り値を直接比較対象に含めれば、変数を減らせる上に行数
を減らしてかつ、かっこよく書くことができます。
今後、使用する変数を減らすことは重要となってきますので、こういう記述には
いまのうちから慣れておくようにしてください。

・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・

さて、今回はこれで終了ですね。
実は今回まで、ターミナル作成に向けて努力してきましたが、これはnScriptを
ダウンロードしたときについてくる「簡易シェル」というもののサンプルを目指して
やってきました。

僕ははじめてこのサンプルをみたときに、あまりにも複雑すぎて理解できませんでした。
だから、自分でいま持ってる知識を使って組んでいくことでサンプルのターミナルに順番
に近づいていこうと考えたのです。

いまでは初期に比べたらかなり近づきました。
サンプルでは、今回やった引数検索の考え方を用いています。
ですが今の僕たちの知識では、残念ながらこのサンプルの外部スクリプトも作ることが
できません。まだ力不足なのです。サンプルでは文字列引数のところで「正規表現」と
いう考え方を用いています。ですからだめなのです。僕もまだわかっていませんw

しかも、です。
コマンドを受けとるところで、gets()ではなく、getchar()を用いています。
文字列として取得するのではなく、なんと一文字一文字取得しているのです。

どうですか?
わくわくしてきましたねー!

と、いうわけなので、次回からはまたいろいろな関数について学んでいきますが、
そっちがひと段落したら、また基本構造のほうに戻ってきて、そしてこのサンプル
に近づこうと思います。

みなさん、nScriptを極めますよ!!
ではがんばってください!

・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・

追記::
今回は特に難しい回です。毎度のごとくわからないことがあったらすぐに連絡して
くれれば、すぐにお答えします。
ちなみにPutiDevsのサイトのほうにお問い合わせボックスを設置しました。
掲示板のように利用できるようになっていますので、そちらもぜひ活用してください。
では。

7 コメント:

よつ さんのコメント...

おお、とうとうArgMatchさんが!
ArgMatchさんとは検索する側ではなくされる側だったのですね、ありがとうございます!

mikan さんのコメント...

めんどくさいですけど使えると便利な定義方ですよね!
引数もきちんと渡せますし。
しかしサンプルをみるとやはりいまやってることとは違う方法で引数の受け渡しもやってるみたいなんです。。

はっきり言って、まだわかっていません。が!
ちゃんとそこまで記事にしてからこの講座を完結させます。

ここでちょっと質問です。
次講座をやるとしたら、やはりBrain上で組めるスクリプトの解説のほうがいいですかね?
サイトのほうにリンクを張りましたが、C--ScriptEngineというものがありまして。
nScriptと比べられないくらい、難しいんです。

それでなかったらPineがPCで使ってるほかの言語の解説に移ろうと考えています。今のところ。

いかがでしょうか?

よつ さんのコメント...

うーん...
わがままを言ってしまうと自分的にはnSriptのようにBrain上でしたいのでC~をしていただきたいですね...

あと話は移ってしまいますが、向こうのサイトがfirefoxで表示できな..とか書いて試してみたらできましたwすいませんw

よつ さんのコメント...

あ、連投すみません
ArgMatchさんの検索って一部一致してると全て実行してしまうんですね...
たとえばrmdirを実行させるとrmとrmdir両方されたり...
これの対処法とかありませんかね?

よつ さんのコメント...

うーん...
わがままを言ってしまうと自分的にはnSriptのようにBrain上でしたいのでC~をしていただきたいですね...

あと話は移ってしまいますが、向こうのサイトがfirefoxで表示できな..とか書いて試してみたらできましたwすいませんw

あ、あとArgMatchさんの検索って一部一致してると全て実行してしまうんですね...
たとえばrmdirを実行させるとrmとrmdir両方されたり...
これの対処法とかありませんかね?

mikan さんのコメント...

既に両方のコマンドを実装済みなのが若干涙目ですが...w

僕もそれは解決できていません!
文字列を扱うときの「正規表現」を勉強すると、うまくいくそうです。

これからも頑張りましょう!w

よつ さんのコメント...

rm達を作れたのは習ったcdコマンドを元にしたからできただけですw
正規表現ですか...どこかに書いてあったきはしますが、全くなにかわかりません!w
よろしくお願いします←

コメントを投稿

Related Posts Plugin for WordPress, Blogger...

 
Design by Free WordPress Themes | Bloggerized by Lasantha - Premium Blogger Themes | Walgreens Printable Coupons