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