On Mon, Mar 10, 2003 at 09:49:47AM -0500, Tom Lane wrote:
> Hannu Krosing <[EMAIL PROTECTED]> writes:
> > Joe Conway kirjutas E, 10.03.2003 kell 05:35:
> >> CREATE OR REPLACE FUNCTION array_push (anyarray, anyscalar)
> >> RETURNS anyarray
> 
> > could you make it
> > RETURNS typeof($1)
> 
> Not directly --- we have to fit the return-type info into an OID field.
> We could fake it by inventing one or more pseudotypes, "SAMEASPARAMn".
> 
> But I think I like better the notion of extending my bound-together-
> ANYARRAY-and-ANYELEMENT proposal,
> http://archives.postgresql.org/pgsql-hackers/2003-03/msg00319.php
> 
> Suppose that we do that, and then further say that ANYARRAY or
> ANYELEMENT appearing as the return type implies that the return type
> is actually the common element or array type.  Then we have such
> useful behaviors as:
> 
>       array_push(anyarray, anyelement) returns anyarray
>       array_pop(anyarray) returns anyelement
>       array_subscript(anyarray, int) yields anyelement
>       singleton_array(anyelement) yields anyarray
> 
> The last three cases cannot be handled by a SAMEASPARAM construct.

... typeof($1)[], or a ARRAYELEMSAMEASPARAM construct?



I'm really liking this discussion.  I know this is sort of "out there", but
I have found in languages like StandardML and Objective CAML that templatized-
type functions are _extremely_ useful.   These languages type systems are
amazingly powerful (the language syntax is another matter *sigh*).

I'm not necessarily suggesting implementing this, but I just want to feed the
debate a bit.  I view the type system of these guys as "the ideal", and would
be in ecstacy if PostgreSQL had it, but I realize implementing the thing would
prolly be far from practical.

First, there are templatized types.  Arrays in PostgreSQL are sort of a 
kludge of templatized types, but they would be defined like so:

type a' array = <some definition ...>

which means that you are describing an array of some type a' (the apostrophe
indicates a type variable).

You can also create other neat templatized types as an aside:

type a' Nullable = Null | Value of a'

Which means the expressions:
        Value 47 --> of type int Nullable
        Null --> of type a' Nullable (determined from context)

But then, you could also say:

        int array array

Or even:

        int Nullable array

Which is somthing you can't in PostgreSQL but would be very nice.  But then
you could say:

let invert_matrix m : a' array array -> a' array array = <code...>

let multiply x : a', y : a' -> a' = <code ...>

You could have more than one type variable in a templatized type or function,
true, but I've never really needed more than one.  I can imagine cases where
it would be useful, but just haven't needed one.

Plus:
        * get rid of horrible 'int4_' type hacks for array.
Minus:
        * can't use oid to represent exact type, rather a string of oids.
        * need second table to hold function type constraints when function
          is templatized.  (or could make it params "oid array array", aka
          oid[][]!) Reserve eight or ten oids for template parameter slots
          (in other words, for a' through j' or something).

Warning: I have been called the "type nazi" <g>

One other thing from StandardML that I have always wanted in PostgreSQL
(or anywhere else I program, for that matter)- record types. (Warning, this is
also very wishful thinking and "out there").

In ML/CAML, a record type is defined like so:

type myrecord = {
        x : int,
        y : int,
        s : string
        };

"myrecord" is actually just type alias, the canonical record definition is:

        {s:string, x:int, y:int}

... with the attributes in alphabetical order, because unless you are mucking
with pointers in C, it really doesn't matter what order they are in.  The
first advantage become very apparent:  Any two records with the same named
attributes of the same types are always of the same type.  In PostgreSQL,
this would mean that functions that operate on RECORD{x:int,y:int,s:string}
could operate on a record from any relation with those attributes.

Further, to make inheritance pretty much unnecesary, you could allow a
record with more attributes to satisfy a parameter or return value constraint.
In other words, you could call function foo(RECORD{x:int,y:int}) on a
RECORD{s:string,x:int,y:int}.

I've thought about this trick a lot.  In theory there is a possibility of
not getting what you want, but in practice it would almost never happen.  The
demostrative case would be calling distance_from_origin(RECORD{x:int,y:int})
on RECORD{x:int,y:int,z:int}, but in this case you need to make a 
distance_from_origin(RECORD{x:int,y:int,z:int}).

This way, you could make a function which operates on RECORD{oid:oid} which
could be called on any record from a table.  I've wanted to do this sort of
thing on several occasions- one application has notes which can be attached
to any row, sort of like PostgreSQL comments.  Another to keep track of what
user changed which fields.  Etc.

Alright.... heheh I didn't mean to ramble.  /ME gets head out of clouds
and goes back to practical work <g>

>
>                       regards, tom lane
> 
> ---------------------------(end of broadcast)---------------------------
> TIP 1: subscribe and unsubscribe commands go to [EMAIL PROTECTED]

---------------------------(end of broadcast)---------------------------
TIP 6: Have you searched our list archives?

http://archives.postgresql.org

Reply via email to