Note: This message contains a lot of tedious observations on how MAKE works,
but there are some items of more general interest following.

Hi Elan,

Sorry I've had to delay responding. You wrote:

>That's the problem. type? any-string! indeed returns datatype! However,
>any-string! is not a datatype!. As you point out later, it's a
>pseudo-type!. Therefore, it's a mistake when type? returns datatype! as
>any-string's type. Type? should report that any-string! is a pseudotype!,
>right?
>
>>
>>I <<think>> what happens here is that any-type! is not a fundamental
>>datatype,
>
>never heard of a fundamental datatype. According to make's help text it
>doesn't require a FUNDAMENTAL datatype, but a datatype. Perhaps make's
>attempt to use any-string! as a datatype! fails, and therefore ...
>eventually, REBOL reports the error.

I got the term fundamental datatype from the REBOL help file valabout.html:

    Fundamental Datatypes
  Following are the fundamental datatypes of REBOL. These are the scalar,
  and constructed values. These datatypes are divided into scalars and
  series.

The next section in this file begins:

    Datatype Classifications
  In addition to the types listed above, some REBOL datatypes are
  pseudotypes. Pseudotypes identify a subset of datatypes. For example,
  the number!  pseudotype identifies the integer! and decimal! datatypes:

I think it's clear here that pseudotypes are treated as a kind of datatype.
Unfortunately there seems to be no provision as yet in REBOL's built-in
metalanguage for pseudotype.

Also, MAKE, in its interface, does not require any particular datatype; both
arguments are specified as any-type!, which means that any errors will occur
internally, during whatever processing MAKE performs.

>> ? make
Constructs and returns a new value.
Arguments:
    type -- The datatype or example value. (any-type)
    spec -- The attributes of the new value. (any-type)

Here's an example of (what I'd call) an interface function error:

>> length? 3
** Script Error: length? expected series argument of type: series port tuple.
** Where: length? 3

Note the word "expected" - this error happens, I take it, before LENGTH? ever
gets called.

Here's the error message from MAKE:

>> make any-string! "any-strings, anyone?"
** Script Error: Cannot use make on datatype! value.
** Where: make any-string! "any-strings, anyone?"

This seems to be an error message peculiar to MAKE, and I interpret it to
mean that MAKE "attempted" to make a new datatype, and failed. As I pointed
out before, MAKE will accept a TYPE argument of any type. I speculated in my
previous message that if the TYPE argument is a fundamental datatype! (as
explained in the REBOL documentation) it will attempt to make a data instance
of that type. If that argument is not a fundamental datatype!, it will
attempt to make a data instance of the same type. Here are some more amusing
examples:

>> make false true
== true
>> make false 0
== false
>> make false 1
== true

I have to revise my speculation. It appears that MAKE has a list of datatype!s
that it will use as datatype!s, and if the TYPE argument is not in that list,
it will attempt to use the TYPE argument as an example value. Notice:

>> make op! ">>"
** Script Error: Cannot use make on datatype! value.
** Where: make op! ">>"

Here op! wasn't in MAKE's list of make-able types (although it is a
fundamental datatype!), so it tried to use op! as an example value, and op!
is, of course, a datatype!.

>> make :+ ">>"
** Script Error: Cannot use make on op! value.
** Where: make :+ ">>"

Here MAKE attempted to use the + operator as an example value, and since its
datatype, op!, is non-make-able, an error occurs.


There are a couple of other reasons for regarding pseudotypes as datatype!s.
Pseudotypes work just the same with as other datatype!s in function
specifications, and they also work the same with FIND:

>> find [21 "string" 22] string!
== ["string" 22]
>> find [21 "string" 22] any-string!
== ["string" 22]
>> find [21 "string" 22] series!
== ["string" 22]


Hope this clears up a little of the datatype!s mystery.

Conclusion: pseudotypes are datatype!s, they just aren't make-able.


          ***** SPECIAL BONUS FOR DATATYPE ENTHUSIASTS *****

The datatype hierarchy in the documentation is a bit off. Here is my
corrected version.

any-type
    any-function
        action
        function
        native
        op
    any-word
        get-word
        lit-word
        refinement
        set-word
        word
    bitset
    char
    date
    error
    logic
    money
    none
    number
        integer
        decimal
    object
    port
    series
        any-block
            block
            list
            lit-path
            hash
            paren
            path
            set-path
        any-string
            binary
            email
            file
            issue
            string
            tag
            url
    symbol
    time
    tuple
    unset

If you don't believe some of this, you can check:

>> any-block? first [this/is/a/set-path:]
== true

I couldn't believe this at first, but since all the path values can be made
from blocks, it does make sense.

Here is a function I sent to the list before to print out all the types a
piece of data belongs to:

show-all-types: func [
    {print out all relevant datatypes for a value}
    value [any-type!]
    /local typelist valuelist to-do
][
    foreach [type list] reduce [
        unset!     "unset!"
        datatype!  "datatype!"
        action!    "any-function! action!"
        op!        "any-function! op!"
    ][
        if type = type? get/any 'value [print ["any-type!" list]  exit]
    ]
    alltypes: []
    if tail? alltypes [
        foreach word first system/words [
            if datatype? get/any word: in system/words word [
                append alltypes get word
            ]
        ]
    ]
    typelist: copy []
    valuelist: head insert/only copy [] :value
    foreach type alltypes [
        if find valuelist type [
            append typelist mold type
        ]
    ]
    print typelist
]

          ***** EXPLANATION OF REBOL PROGRAMMING TRICK *****

Here's a use for the confusing self-modifying REBOL code feature.
SHOW-ALL-TYPES makes a list of datatype!s by iterating through all of the
words. We don't want to do this everytime, so we initialize ALLTYPES this way:

    alltypes: []

The second time this function is run, ALLTYPES is initialized to a complete
list of all the datatype!s. Unfortunately, four of these types won't work
properly with FIND, so I had to provide special processing for them.

See ya,
Eric

Reply via email to