aiscript icon indicating copy to clipboard operation
aiscript copied to clipboard

連想配列

Open syuilo opened this issue 2 years ago • 24 comments

オブジェクトとは異なり、任意の値をキーにできる

構文案

let obj = {
  a: 42
}

let map = &{
  1: 42
  "adfadgf": "sdfgsfgsfg"
  obj: "hoge"
}

<: map[obj] // "hoge"

syuilo avatar Jan 05 '23 07:01 syuilo

オブジェクト廃止して連想配列だけにするのはどうかな

jsの場合は元々Objectがあって後から、似たような機能を持つMapが出てきた。 多分これは、互換性の面で置き換えできないという理由があったと思う。 廃止できるなら、どちらかに統一したほうが良い気がする。

両方必要な理由がある?

marihachi avatar Jan 06 '23 12:01 marihachi

オブジェクトを書くときにキーをいちいちクオートで囲まなければいけないのが面倒というのがある

syuilo avatar Jan 06 '23 20:01 syuilo

オブジェクトを書くときにキーをいちいちクオートで囲まなければいけないのが面倒というのがある

面倒という以外にも、AiScriptはJavaScriptで書かれたオブジェクトをそのままコピペ可能にしたいという理念が一応ある

syuilo avatar Jan 07 '23 02:01 syuilo

それなら任意の値をキーに設定する構文を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]: ... // [ ... ] で囲まれたキーは式として評価される
}

ikasoba avatar Sep 09 '23 11:09 ikasoba

  • 配列やオブジェクト、連想配列をキーにする場合はdeep-equalでマッチ判定する?
  • 関数がキーになった場合どうマッチする?
  • JSON.parseの引数にされたら弾く?

FineArchs avatar Sep 09 '23 12:09 FineArchs

配列やオブジェクト、連想配列をキーにする場合はdeep-equalでマッチ判定する?

そうね

関数がキーになった場合どうマッチする?

これも↑と同様にdeep-equal判定で良さそう

JSON.parseの引数にされたら弾く?

弾くことはせず、JSON化できないキー/値は除外する感じになりそう

syuilo avatar Sep 09 '23 12:09 syuilo

キーワードだけどの&以外にもmaptabledictionaryなども考えられそう

marihachi avatar Nov 05 '23 01:11 marihachi

配列やオブジェクト、連想配列をキーにする場合はdeep-equalでマッチ判定する?

そうね

参照が一致するかでも良さそうな?a == b deep-equalやると、パフォーマンスコストが結構ありそうかも (イメージだけど)

marihachi avatar Nov 05 '23 01:11 marihachi

参照が一致するかでも良さそうな?

参照一致の連想配列は用途が考えづらいと思う deep-equalであればコストを差し置いても使いたい場面がいくらかある

FineArchs avatar Nov 05 '23 01:11 FineArchs

個人的には普通の比較もdeep-equalに変えたい 参照一致の使い道がわからん

FineArchs avatar Nov 05 '23 01:11 FineArchs

用途で考えるとそうかも..

marihachi avatar Nov 05 '23 01:11 marihachi

@syuilo :eyes:

marihachi avatar Nov 06 '23 23:11 marihachi

deep-eqalで比較したい

syuilo avatar Nov 06 '23 23:11 syuilo

キーワードはdicとかどうかしら

syuilo avatar Nov 06 '23 23:11 syuilo

deep-equalだと循環してスタックオーバーフローするとか起こる?その辺は大丈夫?

marihachi avatar Nov 07 '23 00:11 marihachi

let a=[]
a[0]=a
Json:stringify(a) //Maximum stack size exceeded

これみたいなやつですね 参照一致ならdeep-equalでも一致なのでdeep-equalでの比較の前に参照の比較を挟んでおくとよさそう?

FineArchs avatar Nov 07 '23 02:11 FineArchs

deep-equalでも参照の比較は行われるみたいです。 もう少し複雑な問題かも

marihachi avatar Nov 07 '23 02:11 marihachi

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;
}

比較自体はこれでなんとかなる気がしますがそういう話ではなく?

FineArchs avatar Nov 07 '23 02:11 FineArchs

somedic[someobj]が面倒になりそうという問題はありますね Ison:stringifyを用意して文字列化してからMapに突っ込むのが楽そう?

FineArchs avatar Nov 07 '23 03:11 FineArchs

配列やオブジェクト、連想配列をキーにする場合はdeep-equalでマッチ判定する?

普通のdeep-equalの実装だと双方のキー(オブジェクトや配列)がそれぞれ同じように循環参照しているとスタックオーバーフローする問題があります。(無限に再帰してマッチするかが確定しないため)

const x = { n: null };
x.n = x;
const y = { n: null };
y.n = y;
deepEqual(x, y);

marihachi avatar Nov 07 '23 08:11 marihachi

deep-equalの実装をしてみたので、これで解決できるかも? この実装だとそれまでに出てきた参照を覚えておくので、同じ参照が出てきた時点で循環してることを検出できます。 https://github.com/aiscript-dev/aiscript/commit/e91af8de66d2e350b0a3405b6123eb91bb8d499c

marihachi avatar Nov 07 '23 08:11 marihachi

https://github.com/aiscript-dev/aiscript/commit/e91af8de66d2e350b0a3405b6123eb91bb8d499c

何故かequal([1], [2])がtrueになるみたいです…何で…?

FineArchs avatar Nov 07 '23 11:11 FineArchs

バグ修正しました これの影響だったかも?

https://github.com/aiscript-dev/aiscript/blob/e91af8de66d2e350b0a3405b6123eb91bb8d499c/src/equal.ts#L14 この部分でrefsAを使っていますが、この中に自分自身も含まれているため常に-1以外を返すようになってました。正しくは、自分自身を含む前の状態であるprevRefsAです。

marihachi avatar Nov 07 '23 12:11 marihachi

deep-equalについては多分これでOKそうです https://github.com/aiscript-dev/aiscript/pull/460

marihachi avatar Nov 07 '23 13:11 marihachi