Should DATATYPE! be killed off (in favor of @integer, @word, etc?)

Datatypes have a couple of problems. One is that there's no clear representation for them literally:

rebol2>> word? first [integer!]
== true

rebol2>> type? 10
== integer!

rebol2>> word? type? 10
== false

So we're on the cusp of having to use some notation for datatypes like #[datatype! "integer!"] -or- perhaps see them as being expressed through an existing type. We also face the question of extensibility of types...and it's hard to think of a better extensibility mechanism to use than the existing symbol engine that is behind ANY-WORD!.

Yet making them WORD! is not very desirable. We are used to writing things like make object! [...]. And we don't want MAKE to have to quote its argument. Hence, OBJECT! would have to evaluate to something.

We could say object!: 'object! but that seems like it would get into some ugly situations.

What about the new @WORDs?

What if @object! (or @object) could act as a datatype, as well as an ANY-WORD!?

It has the advantage of being inert in the evaluator:

if @integer = type of 1 [print "Sanity prevails..."]

You wouldn't have to worry about quoting it if you were using the actual type's symbolic name, vs. an alias:

switch type of first ['''1] [
    lit '''@integer [
        print "You can do this..."

Redbol compatibility could still work:

integer!: @integer

Though you'd need to do a little extra to work with quoting such names. But Ren-C is designed for it:

switch type of first ['''1] compose [
    lit '''(integer!) [
        print "You can do this..."

So the main question would be, how often is it that you have a slot that might want an @word -or- a datatype? How frequent is that need for polymorphism?

When I look at the landscape of problems, it seems to me that an evaluator-inert type that has an intrinsic extensibility like this would be pretty much ideal for denoting a datatype. No construction syntax, just good ol' reliable behavior.

Anyone have any particularly good arguments against the idea?

Thus Parse usage would be:

parse [1 2 3][some @integer]

Would that preclude any other potential usage for symbols in Parse?

Great minds think alike.

Yes, and PARSE is probably not the only example of a dialect where having a distinct otherwise-unused notion of DATATYPE! could come in handy, where the slot could be either symbol or datatype.

Would that mean:

parse [1 @integer 3] [some @integer]

would be successful?

(UPDATE: I think @integer! is probably wiser, to line up with the datatype name...since they are both ANY-WORD!s in this system, it makes sense to make them easy to compare. This possibly would give us a long-desired feature for datatype and word-of-datatype comparison equivalence)

In the context of the discussion, no.

@integer!, being interpreted as a datatype for purposes of the dialect, would be a parse instruction for integer matching.


parse [1 @integer! 3] [@integer! '@integer! @integer!]

Would reach the end of the series (truthy).

We would presume that integer! would be a WORD! that evaluated to @integer! . So you could still say:

parse [1 @integer! 3] [integer! '@integer! integer!]

It would work by the same general theory that any WORD! which is used in a PARSE rule that's not a keyword is fetched to be the associated rule.

Should DATATYPE! be killed off (in favor of @integer, @word, etc?)

Something to think about with this question is regarding a more OBJECT!-like notion of what a datatype is, where that object might have various descriptive properties (like the numeric limits of a type, or precision, or other characteristics).

If "types" are ANY-CONTEXT!, then they can do this. But if they are simple @word!-s, then you'd have to go through a lookup (at minimum) to get an object that matches the descriptor.

This may point us to a notion of a difference between the kind of a value, and the type of a value. The kind would be something more mechanical regarding the cell structure (like to say that something is an OBJECT!). Whereas the "type" could be richer.

>> book!: make object! [author: title: _]

>> item1: make book! [author: "Aldous Huxley" title: "Brave New World"]

>> item2: make book! [author: "George Orwell" title: "1984"]

>> kind of item1
== @object!

>> object! = kind of item1
== #[true]

>> type of item1
== make object! [author: _ title: _]

>> (type of item1) = (type of item2)
== #[true]

Hence it may be that these wordlike things are only suitable for the kinds. But this is very speculative. We're talking about features and concepts that were never designed (!), yet people would probably like to see fleshed out somehow.

While demoing some of the quoting in the conference, it was clear that dealing with that is going to be a bit of a puzzle for some minds--and so we should do everything we can to make it more obvious.

But... using quoted types to reflect quoting on values has some counter-intuitive properties in evaluative contexts, e.g. with the now evaluative SWITCH...

 switch (type of first ['''foo]) [
     ''''@word [
         print "...needing four quotes here strikes me as non-obvious."
     lit '''@word [
          print "...and needing LIT undermines datatype as inert @WORD!"

This led me to a concept I outlined in chat that we make use of the somewhat superfluous-seeming member of the new inert @ family, the @[...] blocks...

 >> type of first ['''foo]
 == @['''word]

If we use this particular part in the box as a datatype! replacement, we get the opportunity for richer structure. @[matrix 20x20]. And if we let the quoting level be carried on the first element of the type, we also get a fair amount of leverage from that.

Of course we can still keep our shorthands, perhaps adding more:

 integer!: @[integer]
 integerQ!: @['integer]

And it frees up @(...), @word, @some/path for other applications in dialects, because only the @[relatively unloved "new-lit-block"] would be taken (and only in cases where that dialect had reason to be dealing in datatypes).

Seems like an exciting idea to me!

1 Like

I'm still liking this direction. There are a few implications to notice.

One is that TYPE OF is coming back with something more granular than just QUOTED! for things that have quote levels. This preserves the historical (and desirable) behavior. Consider that we likely want:

rebol2> (type? first ['x]) = (type? first [x])
== false

rebol2> (type? first ['x]) = (type? first ['x/y])
== false

If the type of 'x were simply @quoted, then though the former would be false, the second would be true. This suggests a different operation that would say that 'x and 'x/y were both instances of QUOTED!.

But TYPE OF returning an ANY-ARRAY! has the properties we're looking for. It's a distinct type from BLOCK! that is nonetheless irreducible, we can do comparison, and symbolic manipulation via QUOTED and UNQUOTED.

 >> unquoted @['integer]
 == @[integer]

 >> (quoted integer!) = type of first ['10]
 == #[true]

Yet the fact that sometimes we might want to know something is QUOTED! and not care about the specifics raises a bigger point: that there are various depths of patterns to match in "types".

This already existed before arbitrary quoting: e.g. ["a" 10] and [<b> 20 #foo] are both BLOCK!s, but if you were expecting a two element block with a TEXT! and an INTEGER! then they are effectively not matching types. It's the precedent of LIT-WORD! and LIT-PATH! that forced having to have a solution for quoting. But people have wanted something for this as well.