
1. 変数について

saphireの変数には

    1.ローカル変数
    2.グローバル変数
    3.環境変数
    4.配列
    5.ハッシュ

の５つがあります。
ローカル変数、グローバル変数、環境変数はテキスト一行を格納します。

> ls / | var a  # ローカル変数aにls /の出力から最初の一行を格納
> ls / | global a # グローバル変数aにls /の出力から最初の一行を格納
> ls / | export a # 環境変数aにls /の出力から最初の一行を格納

> ls / | global a b # グローバル変数aに一行目 bに二行目を格納

格納したテキストはvar 変数名などとすると取り出せます

> global a
bin

> global a b
bin
etc

> global a b | global b a    # グローバル変数aとbで格納したデータの交換

> print a | global -p a | global b # グローバル変数aとbにデータを格納

配列はテキスト全体を格納します。

> ls / | ary a  # 配列aにls /の出力全体を格納
> ls / | ary_add a # 追記

格納したテキストはary 変数名とすると取り出せます

> ary a
bin
var
....

またインデックスを使って

> ary a 0
bin

と格納している順番の数値を使ってデータを取り出すことができます。

複数のインデックスでデータをとりたい場合はlinesを使います

> ary a | lines 0 0 0 1 
bin
bin
bin
etc

範囲指定でとりたい場合は

> ary a | lines 0..1
bin
etc

です。

配列にデータを追記するときはary_addを使います

> ls | ary a; ls | ary_add a   # 配列aにlsの出力２つ分が入る

ハッシュはテキストの偶数行をキーとして格納して奇数行をアイテムとして格納します。キーを使ってアイテムを取り出すことができます。

> print keyi1\nitem1\nkey2\nitem2 | hash a
> hash a key1
item1
> hahs a key2
item2

ハッシュにデータを追記するときはhash_addを使います。

> print key1\nitem1\nkey2\nitem2 | hash a
> print key3\nitem3 | hash_add a
> hash a key1
item1
> hash a key2
item2
> hash a key3
item3

hash 変数名とすると格納されたデータを全て取り出せます

> hash a
key2
item2
key3
item3
key1             # 順番は格納した順とは限らない
item1

これとlinesを使ってキーのみやアイテムのみを取り出すことができます

> hash a | lines \*2
key1
key2
key3

> hash a | lines \*2+1
item1
item2
item3

ローカル変数はスタックフレームを使った変数で

    1. 関数が呼ばれたとき
    2. スクリプトがloadされたとき

にスタックフレームが新たに作られ、その後に作ったローカル変数は

    1. 関数が終わるとき
    2. loadされたスクリプトが終わるとき

に自動的に消えます。

> vim a.sa
def fun { 
    print a | var a 
    var a | pomch    # 関数の中ではaは使える
}
fun
var a | pomch # var a の寿命はfunのなかだけなのでaは空

またコマンドラインで新たにコマンドを入力するときにスタックフレームは全て初期化されます。

> print a | var a   # a の寿命はこのコマンドラインの中でだけ
> var a | pomch     # aは空なので何も出力されない

ハッシュや配列やグローバル変数は

sweep 変数名 変数名、、、

sweep # 全部のハッシュや配列、グローバル変数が消されます。

で消されるまで寿命があります。
ローカル変数のように使うことはできません。

> ls / | global a   # binをグローバル変数aに格納
> global a | pomch
bin
> sweep a
> global a | pomch


環境変数は
sweepで消すことができません。
またsaphireから起動したプロセスでも生きています。
アプリケーションの設定として環境変数はよく使われます。
export -aで複数行のテキストを格納できます

> ls / | export -a a   # aにls / の出力全てが格納される

ローカル変数は初期化せずに使うことができます。
初期化しない場合空の文字列が出力されます。-nオプションをつけると0で
初期化されます。

> var a | add aaa | var a; var a | pomch
aaa

> var -n a | + 3 | var a; var a | pomch
3

あとローカル変数は
++
--
というコマンドで+1, -1することができます。
この場合も初期化する必要がありません。

> ++ a; var a | pomch
1

2. コマンド展開

    コマンド展開はコマンドの出力をコマンドラインや文に貼り付けるものです。

    > ls -al $(print main.c)
    は
    > ls -al main.c
    を実行するのと同じです。

    コマンド展開には全部で４種類あります

    1. $(コマンド)
    2. $$(コマンド)
    3. @(コマンド)
    4. @@(コマンド)

    1つ目の$(コマンド)はコマンドの実行結果をsaphireで使用される文字をクォートして貼り付けます。

    > ls -al $(print "*.c")
    は
    > ls -al \*.c
    となります。

    > ls -al $(print "main.c saphire.sa")
    は
    > ls -al main.c\ saphire.sa
    となります。

    2つ目の$$(コマンド)はコマンド結果をそのまま貼り付けます。

    > ls -al $$(print "*.c")
    は
    > ls -al *.c
    となります。

    > ls -al $$(print "main.c saphire.sa")
    は
    > ls -al main.c saphire.sa
    となります。

    3つ目の@(コマンド)はコマンド結果が一つの引数となります。

    > ls -al @(print "main.c saphire.sa")

    は

    ls -alにmain.c saphire.saという引数があることになります。

    @(コマンド), @@(コマンド)は実際にはコマンドラインに実行結果を展開しているわけでなく、結果を直接引数としているので高速です。$(コマンド), $$(コマンド)は他の言語で言うと一文が$(),$$()を展開されてからevalされているようなものですが、@(),@@()の場合は字句解析するときにちゃんと字句解析されてます。

    ゆえに big_file.txtが巨大なファイルだとすると

    > print $(cat big_file.txt)

    は$(cat big_file.txt)を展開してから実行するので、何時間も待たされることになりますが

    > print @(cat big_file.txt)

    はそう待たされることが無いでしょう。

    4つ目の@@(コマンド)はコマンド結果が複数行であった場合（saphireでは複数行のテキストは配列であると考えます)一つ一つの行をされぞれ一引数として実行します。(配列の要素一つ一つが一引数となる)

    > cp @(ls) /tmp
    lsの出力の内容がすべて一つの引数として展開されエラー

    > cp @@(ls) /tmp
    lsの出力の内容が一つずつ、一つの引数として展開されるのでOK

    > ls | ary a
    > cp @@(ary a) /tmp
    配列の一つ一つの要素が一つの引数としてcpに渡されるのでOK

3. コンテキストパイプ
    
    コンテキストに応じて入力から読み込みます。
    何度でも読み込むことができます。

    1. サブシェル

    パイプで渡されたデータから読み込みます。

    > puts aaa\nbbb\nccc | (| print; | print; | sub -g . X)
    aaa
    bbb
    ccc
    aaa
    bbb
    ccc
    XXX
    XXX
    XXX

    2. コマンドライントップ

    標準入力から読み込まれます。

    > | print; | print
    (標準入力から読み込まれて出力)

    3. 関数内

    関数に渡されたパイプのデータから読み込まれます。無いなら標準入力から。

    > def fun {
        | print
        | print
    }

    > print abc | fun
    abc
    abc

    > fun
    標準入力から読み込まれて出力される。

4 ブロック

    ブロックは中括弧で囲まれた複数のコマンドの塊です。
    ブロックはパーサーによってコンパイルされたものがコマンドに渡されます。
    特定の内部コマンドやユーザーコマンドがブロックを受け取ることができます。
    外部コマンドにブロックを渡しても無視されます。

    > eval { ls }
    main.c sub.c

    > print { ls }
    printはブロックを受け取れないので何も表示しない

    > echo { ls }
    外部コマンドはブロックを受け取れないので何も表示しない

    ユーザー関数でブロックを実行したい場合yeildを使います。

    > def fun { yeild 0; yield 1 }
    > fun { puts a } { puts b}
    a
    b

    yeildの引数の番号に対応したブロックがユーザーコマンドの中で実行されます。

    ブロックには引数が渡せます。引数はブロック開始のすぐ後にi
    
    : 変数名 変数名 ... :

    とすることで受け取れます。

    > def fun { yeild 0 data1 }
    > fun { :a: var a | pomch }
    data1

