Giraffe+ 0.5.41.569
前リリースからの変化
- 関数のパターンマッチングを拡張した
- 関数のパターンマッチングを実行するBlock.applyを定義
- selfとスロットを共有するコンテキストを作るObject.to_Context(Context = local)を定義
- 数値にincとdecを定義した
- Container.collectを考え直した
- key/DeleteFileOrData(WithoutRecycleBin)を登録アイテムのキャッシュに対応させた
- key/RenameFile2を登録アイテムのキャッシュに対応させた
- "false.? []"がfalseを返してなかったのを修正
- Range.=を定義
- オブジェクトのスロットの参照を設定するObject.set_slotを定義
関数のパターンマッチングを拡張した
配列とペアを分解(destructuring)できるようにしました。
単に、Map.eachした場合にいちいちfirstとsecondを扱うのが鬱陶しかったのと、
Object.slot.each& `key.=> value[ Cout.<< key.<< \\n ] Cout.flush
関数型言語にありがちなことをやりたかっただけです。
map: `f {x xs.@}[ {f(x) recur(f$ xs).@} ].| `f {}[ {} ] map(`n[n.* 2] {1 2 3}) //{2 4 6}
配列({})は、Array、もしくはbeginとendがArrayのイテレータを返すもの(Context.argや上記のxs)が対象になります。
ペア(=>)は、firstとsecondを持つもの全てです。
再帰的に処理されるので、複雑なのもいけます。
`{1 2}.=> 3[true].|`*[false].invoke({1 2}.=> 3) `{1 2}.=> {3 x.@}[true].|`*[false].invoke({1 2}.=> {3 4 5}) //x == {4 5} `{1.=> 2 3 x.@}[true].|`*[false].invoke({1.=> 2 3}) //x == {}
ついでに、型の指定を"シンボル(型名)"で簡単に出来るようにしておきました。
f: `n(Int)[ 0 ].| `s(String)[ 1 ] f(0) //0 f('') //1
constの指定は出来ません。
関数のパターンマッチングを実行するBlock.applyを定義
[x y z].apply(1 2 3)
でカレントコンテキストにx y zが1 2 3にdefされます。
selfとスロットを共有するコンテキストを作るObject.to_Context(Context = local)を定義
戻り値のコンテキストは、selfとスロットを共有し、引数(デフォルトでカレント)のコンテキストを親とします。
例えば、
o: Object.clone [ x: 1 y: 2 z: 3 ].eval(o.to_Context)
とすることでo.x o.y o.zが1 2 3にdefされる、などということができます。
to_Context無しの場合、ブロック内でコンテキストが必要になることが出来ません。
数値にincとdecを定義した
incはインクリメントdecはデクリメントです。以前からあった++と--はinc!とdec!のシノニムになりました。
incと+の違いは、戻り値の型が同じになる点です。Char.+ 1はIntが返ります。これはC++の仕様と一致させています。
足す値は、引数がある場合はそれを、無ければ1になります。inc!は+=のデフォルト引数が1になる版と考えて問題ありません。
Container.collectを考え直した
今までのContainer.collectはContainer.mapになり、Container.collectは少し違う動作になりました。
Map.collectが出来なかったので少し考えてみました。
collectはMapを返すものではない、そして、selfを戻り値で変更する似たようなものもいる、ということで、Container.collectはArrayを返すとし、新たにselfと同じ型のコンテナを返すContainer.mapを作ることにしました。
Container.mapがいままでのContainer.collectに対応しますが、Map等への対応のため、引数のメソッドの戻り値をself.map_set(iterator, value)で代入するようにしました。
std::mapを基にするものは、map_setを'iterator->second = value'とすることで、対応しました。
std::vectorを基にするものは、'*iterator = value'します。
その他は、Container.map_setにより'iterator.deref.= value'をevalする感じになります。
Mapをselfに"値をインクリメントする関数"をcollectとmapに適用する例:
Map.new(0.=> 1 2.=> 3).collect& `key.=> value[ value.inc ] //{2 4}
Map.new(0.=> 1 2.=> 3).map& `key.=> value[ value.inc ] //Map(0.=> 2 2.=> 4)
Container.collectの動作の変更点は、戻り値が常にArrayになること、continueやbreakをするとその分の値は戻り値に追加されないようになったことです。
文字列'12345'をselfに"偶数に1を加え5以上の値が出たら終わる関数"をcollectとmapに適用する例:
'12345'.collect& `n[ n.% 2.? [continue] n.> \4.? [break] n.inc ] //{\3 \5}
'12345'.map& `n[ n.% 2.? [continue] n.> \4.? [break] n.inc ] //'13355'
ついでに、引数に他のコンテナを追加した場合に関数型言語で言うzipとして動作するようにもしておきました。
'12345'.collect& '54321', `x y[ x.max(y) ] //{\5 \4 \3 \4 \5}
'12345'.map& '54321', `x y[ x.max(y) ] //'54345'
key/DeleteFileOrData(WithoutRecycleBin)を登録アイテムのキャッシュに対応させた
登録アイテムをキャッシュしてるときにキャッシュのデータも削除するようにしました。
ついでにBefore, AfterFileManipulationを呼んでいたのを、Before, AfterFileDeletionを呼ぶようにしました。
AfterFileDeletionは、削除が出来たかどうかを示すためにOnEditChange()を呼びます。関数の戻り値では判断できないためです。
key/RenameFile2を登録アイテムのキャッシュに対応させた
リネームに成功した文字列が登録アイテムのキャッシュにもあればそちらも変更するようにしました。
RenameFileはダイアログを呼ぶ関数が新しい名前を教えてくれないのでどうしようもないです。登録アイテムの追加も同じです。
"false.? []"がfalseを返してなかったのを修正
Object.ifの戻り値は最後に評価した値としておきながら、x.?[]でxがfalseの場合にxを返してませんでした。
Range.=を定義
self.begin == arg.begin, self.end == arg.endとなります。
オブジェクトのスロットの参照を設定するObject.set_slotを定義
引数のスロットを自分のスロットとしてポインタを保持します。
これにより、スロットを共有するということが可能になります。
x: Object.clone y: Object.clone y.set_slot(x.slot) y.share: 1 x.share.flush //1