RFC on support for user-defined "types"
[1/8] from: joel::neely::fedex::com at: 11-Jun-2002 10:34
IANARTE, but I suspect that the level of effort to allow users
to define additional DATATYPE! values might be non-trivial.
That assumption motivated me to wonder about whether there
could be some simpler enhancements that might still add value
to the development of reliable scripts, and led to the following
train of thought.
There are at least two obvious virtues to the ability to declare
data types for functional arguments:
1) Documentation -- the declarations make it easer for someone
who is reading the source for the function (or its HELP) to
understand what it expects/does.
2) Error handling -- an error in typing can be caught at the
point of the function invocation, rather than more deeply
(at some point where a type-inappropriate use is made of the
argument). This usually assists the process of finding,
understanding, and correcting the error.
It's nice to have the capability of detecting errors as early as
possible, and at the level of an expression that is most likely to
be recognizable (both as to location in the script and purpose).
AFAICT, the notation
somefunc: func [a [typex!] b [typey! typez!] ...] [
...
]
could be understood as an interpreter-mediated (and therefore
much faster, with more meaningful error messages) equivalent of
somefunc: func [a b ...] [
if not typex! = type? a [
;; complain about type of parameter a
]
if none? find reduce [typey! typez!] type? b [
;; complain about type of parameter b
]
...
]
A truly extensible language allows the programmer to define new
types as needed for a convenient "conceptual vocabulary" for
expressing the ideas of specific applications. Mainstream OO
languages usually handle this via the concept of "class", so that
each new class serves as a user-defined type. Argument checking
can include the notion of the class (or superclass) of which an
argument must be an instance.
Oooops! Wait! REBOL objects have no class!
This means that the best we currently can do for object arguments is
somefunc: func [a [object!] b [object!] ...] [
...
]
even when the programmer has specific kinds/flavors of objects in
mind as the function is designed.
However...
REBOL does make use of the idea that one can access an attribute
(e.g., invoke a method) of an object by name, so that any proposed
use of an object may very well have expectations about a (minimum)
set of attributes that the object should possess. To continue with
my hypothetical example, the programmer may expect to use an INVERT
method on the first parameter, and a MEMORIZE method on the second:
somefunc: func [a [object!] b [object!] ...] [
...blah blah blah...
... a/invert ...
... b/memorize ...
]
and it would be quite nice to be told
Excuse me, but you invoked SOMEFUNC with an inappropriate
object as its first argument!
instead of a message showing only some fragment of the innards of
SOMEFUNC that might be unclear as to purpose and hard to locate.
Therefore, I propose for discussion the idea of extending a function
specification to allow a block of words after an OBJECT! type
specifier, with the meaning that the corresponding argument would be
required possess all of the indicated words within its context.
In other words, we'd be specifying (a portion of) the *interface* that
an object should possess, rather than a (non-REBOL) notion of "class".
This would allow the above hypothetical function definition to be
written as:
somefunc: func [
a [object! [invert]]
b [object! [memorize]]
...
][
...blah blah blah...
... a/invert ...
... b/memorize ...
]
to document/enforce that the first argument must possess an INVERT
attribute/method and the second must have a MEMORIZE attribute/method,
with the checking to be done by the interpreter at the/each point of
function invocation (e.g., as type checking is done now).
Feedback, comments, etc. welcome as always!
-jn-
[2/8] from: greggirwin:mindspring at: 11-Jun-2002 10:53
Hi Joel,
<<
In other words, we'd be specifying (a portion of) the *interface* that
an object should possess, rather than a (non-REBOL) notion of "class".
This would allow the above hypothetical function definition to be
written as:
somefunc: func [
a [object! [invert]]
b [object! [memorize]]
...
][
...blah blah blah...
... a/invert ...
... b/memorize ...
]
to document/enforce that the first argument must possess an INVERT
attribute/method and the second must have a MEMORIZE attribute/method,
with the checking to be done by the interpreter at the/each point of
function invocation (e.g., as type checking is done now).
>>
What about specifying a prototype object instead of a block of words for an
anonymous object? I'm thinking that the list of words could get quite long
and perhaps be used in many places which might become burdensome.
Just my 2% of $1.00 :)
--Gregg
[3/8] from: ingo:2b1 at: 11-Jun-2002 19:40
Hi Joel,
Joel Neely wrote:
<..>
> somefunc: func [
> a [object! [invert]]
<<quoted lines omitted: 11>>
> Feedback, comments, etc. welcome as always!
> -jn-
That sounds very rebolious to me ... and a valuable addition, too!
As much as I'd like "a facility that would allow me to define lexical
syntax for a new data type, along with appropriate input/output
formatting rules" (to quote from your other post), I don't believe that
we'll see it (at least not before 4.0), but these object! tests seem to
be doable (INARTE and all, af course).
Kind regards,
Ingo
[4/8] from: ammon:rcslv at: 9-Jun-2002 18:03
Hi Gregg, Joel,
Either way would suite me fine,
somefunc: func [
a [object! [(first proto-a)]]
b [object! [(first proto-b)]]
...
][
...blah blah blah...
... a/invert ...
... b/memorize ...
]
;-)
Ammon
A short time ago, Gregg Irwin, sent an email stating:
[5/8] from: lmecir:mbox:vol:cz at: 11-Jun-2002 22:01
Hi Joel and Gregg,
Gregg's suggestion is absolutely straightforward, that is what prototypes
are for. My contribution is a function, that checks this:
compatible?: func [
prototype [object!]
object [object!]
] [
empty? exclude first prototype first object
]
Cheers
-L
----- Original Message -----
From: "Gregg Irwin"
Hi Joel,
<<
In other words, we'd be specifying (a portion of) the *interface* that
an object should possess, rather than a (non-REBOL) notion of "class".
This would allow the above hypothetical function definition to be
written as:
somefunc: func [
a [object! [invert]]
b [object! [memorize]]
...
][
...blah blah blah...
... a/invert ...
... b/memorize ...
]
to document/enforce that the first argument must possess an INVERT
attribute/method and the second must have a MEMORIZE attribute/method,
with the checking to be done by the interpreter at the/each point of
function invocation (e.g., as type checking is done now).
>>
What about specifying a prototype object instead of a block of words for an
anonymous object? I'm thinking that the list of words could get quite long
and perhaps be used in many places which might become burdensome.
Just my 2% of $1.00 :)
--Gregg
[6/8] from: g:santilli:tiscalinet:it at: 11-Jun-2002 23:05
Hi Gregg,
On Tuesday, June 11, 2002, 6:53:46 PM, you wrote:
GI> What about specifying a prototype object instead of a block of words for an
GI> anonymous object? I'm thinking that the list of words could get quite long
GI> and perhaps be used in many places which might become burdensome.
Given that:
>> an-object: context [a: 1 b: 2]
>> f: func compose/deep [a [1] b [(an-object)]] [print [a mold b]]
>> f 1 context [c: 1 d: 2]
1
make object! [
c: 1
d: 2
]
>> source f
f: func [a [integer!] b [object!]][print [a mold b]]
works this kind of change should not be that much a problem...
Regards,
Gabriele.
--
Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer
Amigan -- AGI L'Aquila -- REB: http://web.tiscali.it/rebol/index.r
[7/8] from: joel:neely:fedex at: 11-Jun-2002 17:33
Hi, Gregg,
Gregg Irwin wrote:
> What about specifying a prototype object instead of a block of
> words for an anonymous object? I'm thinking that the list of
> words could get quite long and perhaps be used in many places
> which might become burdensome.
>
Actually, I'd prefer to say "What about specifying a prototype object
*or* a block of words..." because I can think of specific examples
where each might be more convenient.
> Just my 2% of $1.00 :)
>
Just my 1% of $2.00 ;-)
-jn-
[8/8] from: ammon:rcslv at: 9-Jun-2002 23:19
Hi
A short time ago, Joel Neely, sent an email stating:
> Hi, Gregg,
> Gregg Irwin wrote:
<<quoted lines omitted: 5>>
> *or* a block of words..." because I can think of specific examples
> where each might be more convenient.
I thought that is what he was saying...
> > Just my 2% of $1.00 :)
>
> Just my 1% of $2.00 ;-)
>
Just my 4% of $0.50 ;-))
Enjoy!!
Ammon
Notes
- Quoted lines have been omitted from some messages.
View the message alone to see the lines that have been omitted