[net.lang] Proc types

aglew@ccvaxa.UUCP (07/13/86)

The discussion about how to implement pointers to functions with enumerated
classes in Ada got me to thinking...

I really like pointers to functions. Don't take them away. Of course, I want
full specification of argument types, even varargs...

However, sometimes a pointer to a whole class of functions is too loose.
It would be nice to be able to constrain it further. Eg. instead of all
int(int)s, only to particular int(int) functions (that you know maintain
the necessary invariant?...)

You can do this with a type declaration for those particular int(int)s you
will permit, but (1) types proliferate, and it can be damned hard to invent
a meaningful name for a type that you're using on an ad-hoc basis, 
and (2) this may constrain sharing functions between modules that might
require a different type-name. Also (3) it violates a rule that I am fond of
in language design: if you can bind something to a symbol, then it should be
possible to replace uses of that symbol by some literal.

So, what I'm looking for in this situation is something like
(veuillez excusez my mixture of langages)

    VAR p: POINTER TO int(int) FROM { func1, func2, func3 ... }

or 

    TYPE p = POINTER TO int(int) SATISFYING constraint;

where you might declare that you have satisfied the constraint at the
procedure body:

    PROCEDURE func1(int a) RETURNS int SATISFIES constraint;


In many ways this is like the problem of specifying non-contiguous 
subsets of the integers as types.


Has anyone seen languages that do something like this?


Andy "Krazy" Glew. Gould CSD-Urbana.    USEnet:  ihnp4!uiucdcs!ccvaxa!aglew
1101 E. University, Urbana, IL 61801    ARPAnet: aglew@gswd-vms

bs@alice.UUCP (07/14/86)

> Andy "Krazy" Glew writes:

> I really like pointers to functions. Don't take them away. Of course, I want
> full specification of argument types, even varargs...

ofcourse, try C++: 

	int printf(char* ...);
	int (*printfct)(char* ...) = &printf;
	(*printfct)("x = %d\n", x);
	(*printfct)("%s = %d\n", "x", x);

> However, sometimes a pointer to a whole class of functions is too loose.
> It would be nice to be able to constrain it further.

The inheritance mechanism of languages like C++ can be used to express a
limited, but regular and quite power full form of ``restriction'' in this
context:

	int fct(base* p)
	{	// "fct" perform operations on a "base"
		// but will accept arguments of any type derived from "base"
	}

for example:

	struct base {
		// ...
		f();
		g();
	};

	struct derived : base {
		// "derived" inherits base's members including f() and g()
		// ...
		h();
	};

	derived d = ...
	base b = ...
	fct(&d);	// coerce the derived* to a base*
	fct(&b);

fct() above can use base::f() and base::g(), but not derived::h().
If base::f() and base::g() were declared "virtual" derived could provide
its own implemntations of them for fct() to use.

Since type checking for pointers to functions is identical to the checking
of functions this feature again applies to pointers to functions (but note
that virtual functions takes care of many cases where one would otherwise
use pointers to functions directly):

	int (*p)(base*) = &fct;
	(*f)(&d);
	(*f)(&b);

sher@rochester.UUCP (07/14/86)

This is in response to an article that requested an ability to have
types that pointed to a particular set of proceedures.  I would think
an even more useful artifact would be a type constructor that took
a set of elements of a particular type and had a type that only allowed
those elements.  Many languages now allow such for integers.  Thus
Now we have type constructors of the form:
array [a..b] of type
record of { t1 , t2 , t3 ... }
function from { t1 , t2 , t3 ...} to type

and variants thereof with various protections such as classes and
what not.  I suggest another type constructor:
enumeration from type of { e1 , e2 , e3 ...}

where ei is an element of type.  Thus you could have the pascal like
enumeration from int of { 1 , 5 , 7 , 12 }

or interestingly
enumeration from char * of { "GOOD" , "BAD" , "INDIFFERENT" }

or
enumeration from real of { 1.34273 , 123408.24398 , 23408 }

or
enumeration from int * ( int * x ) of { qsort , slowsort , merge }

Does any language have such a feature.  I think the semantics should be
non controversial.  The implementation however may cause some problem.

-David

-- 
-David Sher
sher@rochester
seismo!rochester!sher

franka@mmintl.UUCP (07/15/86)

In article <800016@ccvaxa> aglew@ccvaxa.UUCP writes:
>    PROCEDURE func1(int a) RETURNS int SATISFIES constraint;
>
>
>In many ways this is like the problem of specifying non-contiguous 
>subsets of the integers as types.

Ideally, this would be integrated with the optimization processing of the
compiler.  E.g., if I write:

PROCEDURE f(int a, int b) RETURNS int SATISFIES f(a,f(b,c))=f(f(a,b),c);

then the compiler would feel free to reorganize f(a,f(b,c)) encountered
in the program.

Frank Adams                           ihnp4!philabs!pwa-b!mmintl!franka
Multimate International    52 Oakland Ave North    E. Hartford, CT 06108

throopw@dg_rtp.UUCP (07/16/86)

>> aglew@ccvaxa.UUCP
>> So, what I'm looking for in this situation is something like
>>     VAR p: POINTER TO int(int) FROM { func1, func2, func3 ... }
>> or 
>>     TYPE p = POINTER TO int(int) SATISFYING constraint;
>> where you might declare that you have satisfied the constraint at the
>> procedure body:
>>     PROCEDURE func1(int a) RETURNS int SATISFIES constraint;

The two aren't really equivalent, in that in the first case the
enumeration must be known at type construction time, while in the second
case it need not.  The idea of a contract is sometimes used to satisfy
the second notion:

Declaring the contract and a procedure that obeys it is like so:

    PROCEDURE p_type( READ ONLY a1: INTEGER, READ WRITE a2: INTEGER );
        PROPERTIES CONTRACT;
    END PROCEDURE p_type;
    PROCEDURE p OBEYS CONTRACT;
        NOTHING;
    END PROCEDURE p;

and you can use it like so:

    VARIABLE p_ptr: POINTER TO p_type;
    p_ptr := POINTER(p);
    p( 1, 2 );  p_ptr@( 1, 2 );

> sher@rochester.UUCP (David Sher)
> Thus you could have the pascal like
> enumeration from int of { 1 , 5 , 7 , 12 }
> or interestingly
> enumeration from char * of { "GOOD" , "BAD" , "INDIFFERENT" }
> or
> enumeration from real of { 1.34273 , 123408.24398 , 23408 }
> or
> enumeration from int * ( int * x ) of { qsort , slowsort , merge }
> Does any language have such a feature.

Common Lisp.  This is the first of the options Andy talked about above.
In common lisp, an enumerated type simply specifies values that objects
of the type may take.  It can even be heterogenous, somewhat like
unions, but more convenient, so that you can declare a single type that
can have the value of integers from 5 to 7, procedures p or q, or the
complex number sqrt(-1).  Assuming you would want such a bizarre type,
of course.

--
A language that doesn't affect the way you think about programming, is
not worth knowing.
                                        --- Alan J. Perlis
-- 
Wayne Throop      <the-known-world>!mcnc!rti-sel!dg_rtp!throopw