Hi Ladislav,

I did some investigation of the datatype test functions, such as
NUMBER? and BLOCK? I found they always return a logic value, no
matter what type of argument they have - even if it's UNSET! or
ERROR! I put together a number of functions testing for what you
called "predicate types". Here's an example from huh.r . This
merely excludes the most numerous datatypes, so HUH can print out
the names of all the blocks, strings, numbers etc, so that you
can check whether some function is leaking into the global context
(due to spelling error or whatever).

data?: func [
    {returns TRUE for all data types except unset,
    any-function and datatype}
    value [any-type!]
][
    all [
        value? 'value
        not any-function? :value
        not datatype? :value
    ]
]

(Actually this is a streamlined version inspired by your post.)

In these functions you have to use [any-type!] in the header so that the
function will accept any value at all. Then it's important to check whether
the argument has a value. Otherwise, if the argument is unset anything else
you try to do with it will cause an error. Then it's a good idea to use
the get-word form of the argument until you're sure it's not an
ANY-FUNCTION! PAREN! SET-WORD! PATH! SET-PATH! - all these will produce
errors too. Then finally, if you want to look at the argument with anything
except another datatype test function, you have to be sure it's not an
ERROR!

Your NONZERO? could be done this way:

nonzero?: func [
    {returns TRUE if not zero, but belongs to a type that has zeros}
    value [any-type!]
][
    all [
        value? 'value
        any [                ; all the types that have zero values
            number? :value
            char? :value
            money? :value
            time? :value
            tuple? :value
        ]
        not zero? value
    ]
]

I put it into a standard format, so that it will return true with the
following function:

type-tester?: func [
    {Returns TRUE if VALUE is a datatype test function}
    value [any-type!]
][
    all [
        value? 'value
        any-function? :value
        find/only third :value reduce [any-type!]
        not find third :value lit-word!
        string? first third :value
        found? find first third :value "Returns TRUE"
    ]
]

>> huh * type-tester?

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

@@ function!
data?         nonzero?      not?          type-tester?


Catch you later,
Eric


==== You wrote:

3) Predicate Types vs. Pseudotypes

Pseudotypes are something added for the sake of conciseness, I
think.They can be simulated through Predicate Types as follows:

num?: func [x [any-type!]] [
    any [integer? x decimal? x]
]

Predicate types are normally weak, as can be seen here from 1),
but you can have predicate types like:

nonzero?: func [x [any-type!]] [
    all [number? x not zero? x]
]

, which may be of some use.

So, to finish this part: the Rebol typesystem is strong, the
organic approach should take that into account together with the
stress on the internal representation.

Bye 4 now

Reply via email to