[[スクリプト開発]] に戻る

* スクリプト開発のTips集 [#c42c2819]
このページでは,SquirrelでSimutransのスクリプトを開発するにあたってのハマリポイントなどを解説していきます.&br;
間違っている情報があればどんどん訂正お願いしますです.

** インスタンスの比較 [#lc997447]
(確認; 2021年3月 OTRPv29_5)
[[halt_list_x():http://dwachs.github.io/simutrans-sqapi-doc/classhalt__list__x.html]]や, [[player_x.get_line_list():http://dwachs.github.io/simutrans-sqapi-doc/classplayer__x.html#a6659200cdd3054aee15257106737c21f]] で得られるインスタンス列は,毎回中身が異なるようです.すなわち,get_xxx_list()で得られるインスタンスでは,演算子==によるオブジェクト比較が使えません.

get_halt_list()で得られるhalt_x オブジェクトの比較には==を用いず,nameで比較するのが良いと考えられます.

** filter,map関数について [#a1ada227]
(確認; 2021年3月 OTRPv29_5)

Squirrelには[[array.filter():http://www.squirrel-lang.org/squirreldoc/reference/language/builtin_functions.html?highlight=filter#array.filter]]関数や, array.map()関数が用意されていますが,これらの使用は以下の理由から推奨されません.

- get_xxx_list()で得られるxxx_list_xオブジェクトはarrayではないので,filterやmapも利用できない.
- array.filter()やarray.map()ではループ処理中のyieldが行われず,大きなサイズ(概ね要素数1000以上)のarrayに適用すると実行命令数制限にひっかかってしまう.

実際の開発ではarrayもxxx_list_xオブジェクトも同様に扱いたい場合が多いと思いますので,以下のようにfilterおよびmap関数を定義してあげるのがいいでしょう.

 function _step_generator(iteratable) {
   foreach (obj in iteratable) {
     yield obj
   }
 }
 
 function filter(array, func) {
   local new_array = []
   foreach (obj in _step_generator(array)) {
     if(func(obj)) {
       new_array.append(obj)
     }
   }
   return new_array
 } 
 
 function map(array, func) {
   local new_array = []
   foreach (obj in _step_generator(array)) {
     new_array.append(func(obj))
   }
   return new_array
 }

使用するときは以下のようになります.
 // 容量1000人以上以上の停留所一覧を返す
 funtion get_big_halt() {
   return filter(halt_list_x(), ((@h) h.get_capacity(good_desc_x.passenger)>=1000)
 }