aiscript
aiscript copied to clipboard
連想配列
オブジェクトとは異なり、任意の値をキーにできる
構文案
let obj = {
a: 42
}
let map = &{
1: 42
"adfadgf": "sdfgsfgsfg"
obj: "hoge"
}
<: map[obj] // "hoge"
オブジェクト廃止して連想配列だけにするのはどうかな
jsの場合は元々Objectがあって後から、似たような機能を持つMapが出てきた。 多分これは、互換性の面で置き換えできないという理由があったと思う。 廃止できるなら、どちらかに統一したほうが良い気がする。
両方必要な理由がある?
オブジェクトを書くときにキーをいちいちクオートで囲まなければいけないのが面倒というのがある
オブジェクトを書くときにキーをいちいちクオートで囲まなければいけないのが面倒というのがある
面倒という以外にも、AiScriptはJavaScriptで書かれたオブジェクトをそのままコピペ可能にしたいという理念が一応ある
それなら任意の値をキーに設定する構文をJSの計算プロパティ名に合わせたほうが良さそう?(/ω・\)チラッ https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Object_initializer#:~:text=%E8%A8%88%E7%AE%97%E3%83%97%E3%83%AD%E3%83%91%E3%83%86%E3%82%A3%E5%90%8D
こんなふうな構文です
&{
hoge: 1234 // hogeはキー名として設定される
[obj]: ... // objは変数として評価され、中に入っている値がキーに設定される
[1 + 1]: ... // [ ... ] で囲まれたキーは式として評価される
}
- 配列やオブジェクト、連想配列をキーにする場合はdeep-equalでマッチ判定する?
- 関数がキーになった場合どうマッチする?
- JSON.parseの引数にされたら弾く?
配列やオブジェクト、連想配列をキーにする場合はdeep-equalでマッチ判定する?
そうね
関数がキーになった場合どうマッチする?
これも↑と同様にdeep-equal判定で良さそう
JSON.parseの引数にされたら弾く?
弾くことはせず、JSON化できないキー/値は除外する感じになりそう
キーワードだけどの&
以外にもmap
やtable
、dictionary
なども考えられそう
配列やオブジェクト、連想配列をキーにする場合はdeep-equalでマッチ判定する?
そうね
参照が一致するかでも良さそうな?a == b
deep-equalやると、パフォーマンスコストが結構ありそうかも (イメージだけど)
参照が一致するかでも良さそうな?
参照一致の連想配列は用途が考えづらいと思う deep-equalであればコストを差し置いても使いたい場面がいくらかある
個人的には普通の比較もdeep-equalに変えたい 参照一致の使い道がわからん
用途で考えるとそうかも..
@syuilo :eyes:
deep-eqalで比較したい
キーワードはdicとかどうかしら
deep-equalだと循環してスタックオーバーフローするとか起こる?その辺は大丈夫?
let a=[]
a[0]=a
Json:stringify(a) //Maximum stack size exceeded
これみたいなやつですね 参照一致ならdeep-equalでも一致なのでdeep-equalでの比較の前に参照の比較を挟んでおくとよさそう?
deep-equalでも参照の比較は行われるみたいです。 もう少し複雑な問題かも
function deepEqual(a: Value, b: Value) {
if (a.type !== b.type) return false;
if (a.value === b.value) return true;
if (['arr', 'obj', 'fn'].includes(a.type)) 各子要素を比較;
else return false;
}
比較自体はこれでなんとかなる気がしますがそういう話ではなく?
somedic[someobj]
が面倒になりそうという問題はありますね
Ison:stringifyを用意して文字列化してからMapに突っ込むのが楽そう?
配列やオブジェクト、連想配列をキーにする場合はdeep-equalでマッチ判定する?
普通のdeep-equalの実装だと双方のキー(オブジェクトや配列)がそれぞれ同じように循環参照しているとスタックオーバーフローする問題があります。(無限に再帰してマッチするかが確定しないため)
const x = { n: null };
x.n = x;
const y = { n: null };
y.n = y;
deepEqual(x, y);
deep-equalの実装をしてみたので、これで解決できるかも? この実装だとそれまでに出てきた参照を覚えておくので、同じ参照が出てきた時点で循環してることを検出できます。 https://github.com/aiscript-dev/aiscript/commit/e91af8de66d2e350b0a3405b6123eb91bb8d499c
https://github.com/aiscript-dev/aiscript/commit/e91af8de66d2e350b0a3405b6123eb91bb8d499c
何故かequal([1], [2])
がtrueになるみたいです…何で…?
バグ修正しました これの影響だったかも?
https://github.com/aiscript-dev/aiscript/blob/e91af8de66d2e350b0a3405b6123eb91bb8d499c/src/equal.ts#L14 この部分でrefsAを使っていますが、この中に自分自身も含まれているため常に-1以外を返すようになってました。正しくは、自分自身を含む前の状態であるprevRefsAです。
deep-equalについては多分これでOKそうです https://github.com/aiscript-dev/aiscript/pull/460