Should ANY-VALUE! Include Isotopes?

So if you don't put any type restrictions on a parameter, it will allow isotopes:

 >> foo: func [x] [probe x]

>> foo null
~null~  ; isotope

And right now, that is a synonym for ANY-VALUE!.

 >> foo: func [x [any-value!]] [probe x]

>> foo null
~null~  ; isotope

But what if you want to exclude isotopes? We could have a name for the typeset excluding isotopes (perhaps ANY-CELL!). Or we could say that ANY-VALUE! doesn't include isotopes by default, and so you have to write [any-value! isotope!] if you want them... or just include the specific ones you intend (like [null! any-value!].

Right now I'm going the route of saying ANY-CELL! is the narrower set of values that do not include isotopes. Is there a better term for saying something can be put into an array vs. not?

"10 is an integer! which is legal to use as a cell, while ~null~ isotopes are not legal as cells, but can be variable values"

It seems shorter and cleaner than ANY-REIFIED! or something like that. I don't know any better options.

1 Like

Let me point out that it seems best if typechecking applies to the unescaped form. So if you have a ^META argument which says it can accept a something unstable like a PACK!, that is written as func [^arg [integer! pack!]], not func [^arg [quoted-integer! quasi-pack!]].

As such, isotope! would have a different meaning for meta and non-meta parameters. This suggests needing a distinction between stable-isotope! and any-isotope! :frowning:

This raises a question about the meaning of func [^arg [any-value!]]. Does that encompass unstable isotopes as well as stable ones?

A term that could subsume stable isotopes and array elements could be ANY-STABLE!, which would then leave ANY-VALUE! exclusively for things you can put in an array. But I think this runs against the natural usage of the term "value"... if you ask "what is the value of the variable" and something like a ~true~ isotope is legitimate for a variable to hold, that's the variable's value. I'd also say an object contains "keys" and "values".

But since a variable cannot hold things like a PACK! (block isotope) or a RAISED! (error isotope), it is probably best to avoid saying they are "values". They're unstable isotopes. What happens to an unstable isotope is that if they're not in the type checking of a ^META parameter, they decay... e.g. a pack will decay to its first item, and a raised will decay to causing an "untrappable" failure (exempting special functions like sys.util.rescue).

This points to the idea that if you want to take only things that go in BLOCK!s/GROUP!s, those need a name. At the instant of writing I've called those ANY-CELL!

Implementation Naming Issue: Cell Datatype is Superset

In the mechanical implementation itself, I used the name Cell as the base class of Value... not vice versa. In OOP terms, this suggests all values are cells...but not all cells are values.

The distinction this was intended to draw was the difference between something that has all the information needed for binding (e.g. a variable's value) and a raw array element that can be imaged multiple times and places with different bindings.

This gives you partial type coverage--as a routine for writing an isotope can take the address of a Value, which prevents accidentally writing them into a block! or group!. While writing something like an integer! can take the address of a Cell and work for either. However, reading routines like testing to see if a value contains an isotope takes a cell.

So the naming doesn't line up with ANY-CELL! meaning ANY-ARRAY-ITEM!. I don't feel like going into the code and giving another name to the base class, like Element. And I don't like the idea of the implementation using the word "cell" to mean something different than what a user of the language would say it means.

Perhaps Element is a good name for things you can put in array slots, retaining Cell for the universal base class that applies to Element and Value?

I haven't needed in the implementation to specifically call out "Elements" distinctly from "Cells". If I used my imagination I could probably think up some restrictions...for instance that you can't do pointer math on Cells without casting them to Element. But really the core issue in the implementation has been that you are restricted from doing variable lookup on cells without combining them with "specifiers" to make "values".

I think I'm happier with ANY-ELEMENT! or ELEMENT!. This suggests maybe ANY-CELL! or CELL! could--in compliance with the implementation--subsume unstable isotopes.

I'm scratching my head over the usefulness of an Element subclass in the implementation itself (beyond the exposed typeset). One of the problems is that Rebol guts are based on using common array routines for objects and function frames...and so even common-sense-sounding ideas like "you can't just increment a pointer to a variable to get to another variable" are subverted all over the place.

I'll have to keep thinking on it, but at least there's a bit of progress with the "element" term. So append would accept [void! element! splice!]... with void resulting in a no-op, element adding a single item, and splice adding an array itemwise.

1 Like