Should Isotopes Be Legal in MAP! (Keys, Values?)

In the pre-isotopic era, there was a concept that MAP! would not allow you to store nulls. Because null was the signal of not being in a map. Assigning a key null was a way of removing items from that map.

>> m: make map! [x 20]
== make map! [
    x 20

>> m.x
== 20

>> m.y
; null

>> m.x: null
; null

>> m
== make map! [

Additionally, NULL was not allowed as a key.

How Should This Change In The Isotopic Era?

I'll make the point that not allowing you to store isotopes as keys or values isn't a fundamental problem, because you can META a value to put it in, and then UNMETA it when taking it out.

You wind up with a fundamental issue that actions from a MAP! won't be run implicitly this way, and you can't put any falsey values in a map this way (because false is the ~false~ word isotope, and ~null~ isotopes are representations of not being in the map).

But that limitation can be a benefit. I already think of it as a benefit that you cannot run an action by doing access of items out of a block. e.g. block.1 could never run a function now (since blocks can't store isotopic actions). If that was true of map.key as well, that could be seen as a good thing... you'd have to APPLY or RUN a plain ACTION! (or QUASI-ACTION!).

>> m: make map! []

>> m.1: :append
** Error: Cannot put ACTION! isotope in map

>> m.1: ^append
== ~#[action! {append} [series value /part /dup /line]]~

>> m.1
== ~#[action! {append} [series value /part /dup /line]]~

>> run m.1 [a b c] [d e]
== [a b c [d e]]

>> apply m.1 [[a b c] [d e] /dup 2]
== [a b c [d e] [d e]

>> m.1/ [[a b c] [d e] /dup 2]
== [a b c [d e] [d e]

As with the peace of mind using BLOCK!, that seems like a good thing to me.

(I'm not entirely sure if RUN should allow QUASI-ACTION!s, or if you should have to UNQUASI it into a plain ACTION!. Forcing the canonization might make more sane, so that routines that want to exchange actions as currency would have one standard they spoke.)

I also think it's likely a good thing that false isotopes wouldn't be in the map, only quasi-false and the word false. So if you're putting logic into a map, you'd wind up writing if map.key = 'true [...] or if map.key = 'false [...] and save the if map.key and if not map.key for testing things being in the map.

This Would Widen The Gap With Objects

There have been questions about what the difference is between maps and objects, and this would be another: objects must be able to have members that are isotopes: action isotopes that can run implicitly, logic and null and other word isotopes, and I'm presuming splices and other stable forms as well.

It would mean a map has more in common with a block.

This doesn't strike me as being that much of a problem.

So I'm going to be going ahead with the premise that isotopes can't be stored in maps, as either keys or values. We'll see how it goes, but I think this is the right answer.

1 Like

Now that null is implemented as an isotopic word, this feature is broken by a "no isotopes" rule. So there would have to be an exception made just for null.

But... what if we didn't make an exception, and used void (which isn't "isotopic") to remove elements? We could still have the falsey null come back when items weren't found. The asymmetry seems consistent in the era of void-in-null out.

This would introduce a little bit of a "hassle", e.g. by forcing you to throw in a MAYBE:

>> m: make map! [key <initial>]
== make map! [key <initial>]

>> m.key
== <initial>

>> m.key: select [a 10 b 20] 'c
** Error: Can't put ~null~ isotopes in maps, use void to remove key

>> m.key: maybe select [a 10 b 20] 'c
; void

>> m.key
== ~null~  ; isotope

But it's probably a good hassle. "Did you really mean to unset this key?"

If you're sure, it's not any harder... you just say m.key: void instead of m.key: null. And it helps make the "you can't put isotopes in maps" rule universal... null just becomes the answer given back when nothing is there, kind of like how it's used in blocks. This doesn't get cognitively mixed up with giving the appearance you're actually storing an isotope.

You can also make keys the direct product of a conditional, like m.key: case [... [<whatever>]] and if no cases are taken there won't be an addition done.

1 Like