From: Christophe Rhodes
Subject: FUNCTION types
Date: 
Message-ID: <sqpu2owk5d.fsf@cam.ac.uk>
I'm confused about function types and the relationship between
them. Consider the two types

(function (fixnum fixnum) fixnum)

and

(function (real integer) t).

What do they actually mean? My na�ve interpretation (from a brief read
of Body/t_fn.htm in your local friendly hyperspec) is that the first
type contains the set of all functions that accept two fixnum
arguments and return a fixnum result, and the second the set of all
functions that accept a real and an integer argument and return a
value.

According to this, I would submit that 

(subtypep '(function (fixnum fixnum) fixnum)
          '(function (real integer) t))
-> T, T [ or possibly NIL, NIL ]

as all functions that accept two fixnum arguments and return a fixnum
value are to be found in the latter set.

However, there's an alternative interpretation that seems likely; if
the second set actually contains all functions that will return a
value for all (real, integer) argument pairs, then the two types are
actually disjoint, and the subtypep should return NIL, T [ or possibly
NIL, NIL ].

Discussion (in FUNCTION-TYPE-ARGUMENT-TYPE-SEMANTICS,
Issues/iss176_w.htm) seems to imply that the function types should be
treated much as in my first interpretation, so that we can see if two
function types are compatible by seeing if one is a subtype of the
other, though of course the issue writeup does also say that the
notion of subtype does not make much sense; the issue writeup is not
part of the specification, I know.

Current practice seems a little confused, too:

ACL (Linux 6.1 Trial):
CL-USER(4): (subtypep '(function (fixnum fixnum) fixnum) '(function (real integer) t))
NIL, NIL
CL-USER(5): (subtypep '(function (real integer) t) '(function (fixnum fixnum) fixnum))
NIL, NIL

CMUCL (Debian 3.0.8):
* (subtypep '(function (fixnum fixnum) fixnum) '(function (real integer) t))
T, T
* (subtypep '(function (real integer) t) '(function (fixnum fixnum) fixnum))
T, T

CLISP (2.27):
[1]> (subtypep '(function (fixnum fixnum) fixnum) '(function (real integer) t))
NIL, T
[2]> (subtypep '(function (real integer) t) '(function (fixnum fixnum) fixnum))
NIL, T

ACL's behaviour is consistent with ANSI by my reading, without a
doubt. CLISP's is consistent if you take my second interpretation, I
think; CMUCL's seems to be a pre-ANSI interpretation (I believe that
CLtL said that all function types were equivalent, though I don't have
a reference to hand). Any guidance appreciated.

Christophe
-- 
Jesus College, Cambridge, CB5 8BL                           +44 1223 510 299
http://www-jcsu.jesus.cam.ac.uk/~csr21/                  (defun pling-dollar 
(str schar arg) (first (last +))) (make-dispatch-macro-character #\! t)
(set-dispatch-macro-character #\! #\$ #'pling-dollar)

From: Kent M Pitman
Subject: Re: FUNCTION types
Date: 
Message-ID: <sfwzo1sju1i.fsf@shell01.TheWorld.com>
Christophe Rhodes <·····@cam.ac.uk> writes:

> I'm confused about function types and the relationship between
> them. Consider the two types
> 
> (function (fixnum fixnum) fixnum)
> 
> and
> 
> (function (real integer) t).
> 
> What do they actually mean? My na�ve interpretation (from a brief read
> of Body/t_fn.htm in your local friendly hyperspec) is that the first
> type contains the set of all functions that accept two fixnum
> arguments and return a fixnum result, and the second the set of all
> functions that accept a real and an integer argument and return a
> value.
> 
> According to this, I would submit that 
> 
> (subtypep '(function (fixnum fixnum) fixnum)
>           '(function (real integer) t))
> -> T, T [ or possibly NIL, NIL ]
> 
> as all functions that accept two fixnum arguments and return a fixnum
> value are to be found in the latter set.
> 
> However, there's an alternative interpretation that seems likely; if
> the second set actually contains all functions that will return a
> value for all (real, integer) argument pairs, then the two types are
> actually disjoint, and the subtypep should return NIL, T [ or possibly
> NIL, NIL ].

I think we're moving away from this.

Long ago, in Maclisp, before CL was a glint in Steele's eye, we used
to have a special kind of function called a "number called" function.
It had two entry points: one for when you knew you were calling it
with args of the right type and one for when you didn't.  There was a
lot of ceremony abou this.  If you didn't know you had a number-called
function, the compiler had to heap-cons a stack value, then call the
function at the general entry point, which would push an extra stack
frame that would expect a register result and would copy that result
to the heap and return it to the real caller.  In that environment, it
was EXTREMELY important not to declare something as taking and
returning numbers that didn't, because if you did, you were basically
going to get bad code because you would pass args in registers to a
function that wasn't expecting it. It caused lots of problems.

I think Common Lisp intends type declarations to be descriptive but
not semantic.  Yes, in arrays an element-type is semantic, but it is
also not a declaration.  And yes, in arrays there's a lot of upgrading
and typep kind of acknowledges all of thise, but we've also put a
vocabulary of types and tests into your (the programmer's) hand to
allow you to navigate it.  You have no such vocabulary for inquiring
of functions, and so I personally think it's not reasonable for
implementations to take important semantic liberties with this kind of
partitioning because you couldn't detect it (well), and would be
affected by it a lot.

> Discussion (in FUNCTION-TYPE-ARGUMENT-TYPE-SEMANTICS,
> Issues/iss176_w.htm) seems to imply that the function types should be
> treated much as in my first interpretation, so that we can see if two
> function types are compatible by seeing if one is a subtype of the
> other, though of course the issue writeup does also say that the
> notion of subtype does not make much sense; the issue writeup is not
> part of the specification, I know.
> 
> Current practice seems a little confused, too:
> 
> ACL (Linux 6.1 Trial):
> CL-USER(4): (subtypep '(function (fixnum fixnum) fixnum) '(function (real integer) t))
> NIL, NIL
> CL-USER(5): (subtypep '(function (real integer) t) '(function (fixnum fixnum) fixnum))
> NIL, NIL

Second argument of NIL means "I don't know."  So these results are consistent.

 
> CMUCL (Debian 3.0.8):
> * (subtypep '(function (fixnum fixnum) fixnum) '(function (real integer) t))
> T, T
> * (subtypep '(function (real integer) t) '(function (fixnum fixnum) fixnum))
> T, T
 
This says the two are type-equivalent, which seems fair as long as it
returns T, T for all functions.

> CLISP (2.27):
> [1]> (subtypep '(function (fixnum fixnum) fixnum) '(function (real integer) t))
> NIL, T
> [2]> (subtypep '(function (real integer) t) '(function (fixnum fixnum) fixnum))
> NIL, T

I'm skeptical of this interpretation but would want to hear what the CLISP
people think before taking a stronger stand.
 
> ACL's behaviour is consistent with ANSI by my reading, without a
> doubt.

Yes.

> CLISP's is consistent if you take my second interpretation, I
> think;

Might just be a simple bug.  Did you ask them?

> CMUCL's seems to be a pre-ANSI interpretation (I believe that
> CLtL said that all function types were equivalent, though I don't have
> a reference to hand).

And aren't all function types equivalent?

This gets a little into the question of whether

 (defun foo (x)
   (check-type x fixnum)
   x)

counts as (function (fixnum) fixnum).  In some sense, it takes any
type of argument.  My 1990 conditions paper 
 http://world.std.com/~pitman/Papers/Exceptional-Situations-1990.html
touches on this confusion a tiny bit, and this issue comes up a lot in
the CMU CL type expansion model.

> Any guidance appreciated.

Guidance?  Don't use these types with TYPEP or SUBTYPEP.  Seriously, I
never do and have never missed them.

If you are intent on using them, what are you using them for? Maybe
there's another way.
From: Christophe Rhodes
Subject: Re: FUNCTION types
Date: 
Message-ID: <sqk7swwfug.fsf@cam.ac.uk>
Kent M Pitman <······@world.std.com> writes:

> Christophe Rhodes <·····@cam.ac.uk> writes:
> 
> > I'm confused about function types and the relationship between
> > them. Consider the two types
> > 
> > (function (fixnum fixnum) fixnum)
> > 
> > and
> > 
> > (function (real integer) t).
> >
> > [snippety]
> >
> > CLISP (2.27):
> > [1]> (subtypep '(function (fixnum fixnum) fixnum) '(function (real integer) t))
> > NIL, T
> > [2]> (subtypep '(function (real integer) t) '(function (fixnum fixnum) fixnum))
> > NIL, T
> 
> I'm skeptical of this interpretation but would want to hear what the CLISP
> people think before taking a stronger stand.

> > CLISP's is consistent if you take my second interpretation, I
> > think;
> 
> Might just be a simple bug.  Did you ask them?

I haven't yet. The reason I'm asking here is that it's not yet clear
to me that this is entirely a bug. :-)
 
> > CMUCL's seems to be a pre-ANSI interpretation (I believe that
> > CLtL said that all function types were equivalent, though I don't have
> > a reference to hand).
> 
> And aren't all function types equivalent?

I don't know. I would say not, because
(defun foo (x)
  (declare (type (function (integer) integer) x))
  ... (funcall #'x 2.5))
can have different semantics from
(defun foo (x)
  (declare (type (function (real) integer) x))
  ... (funcall #'x 2.5))

I haven't seen anywhere in CLHS that says that the list forms of
function are all equivalent; indeed, since the list form of function
is on the list of things that subtypep is allowed to be unsure about
(return NIL for second argument) I'd say that function types are
allowed to be distinct.

> This gets a little into the question of whether
> 
>  (defun foo (x)
>    (check-type x fixnum)
>    x)
> 
> counts as (function (fixnum) fixnum).  In some sense, it takes any
> type of argument.  My 1990 conditions paper 
>  http://world.std.com/~pitman/Papers/Exceptional-Situations-1990.html
> touches on this confusion a tiny bit, and this issue comes up a lot in
> the CMU CL type expansion model.
> 
> > Any guidance appreciated.
> 
> Guidance?  Don't use these types with TYPEP or SUBTYPEP.  Seriously, I
> never do and have never missed them.
> 
> If you are intent on using them, what are you using them for? Maybe
> there's another way.

Well, I'm involved in the implementation of SBCL, the CMUCL
derivative; as you know, type inference is a good deal of what the
compiler in these implementations does. In a sense, what I'd like to
know is if I am "allowed" to interpret the CLHS as permitting

(subtypep '(function (fixnum fixnum) fixnum) '(function (real integer) t))
-> T, T
(subtypep '(function (real integer) t) '(function (fixnum fixnum) fixnum))
-> NIL, T

by virtue of my first interpretation, as this would simplify some
internal type deriving logic.

I don't plan to do this kind of type testing in user code :)

Christophe
-- 
Jesus College, Cambridge, CB5 8BL                           +44 1223 510 299
http://www-jcsu.jesus.cam.ac.uk/~csr21/                  (defun pling-dollar 
(str schar arg) (first (last +))) (make-dispatch-macro-character #\! t)
(set-dispatch-macro-character #\! #\$ #'pling-dollar)
From: Kent M Pitman
Subject: Re: FUNCTION types
Date: 
Message-ID: <sfwr8n49x6b.fsf@shell01.TheWorld.com>
Christophe Rhodes <·····@cam.ac.uk> writes:

> Kent M Pitman <······@world.std.com> writes:
...
> > And aren't all function types equivalent?
> 
> I don't know. I would say not, because
> (defun foo (x)
>   (declare (type (function (integer) integer) x))
>   ... (funcall #'x 2.5))
> can have different semantics from
> (defun foo (x)
>   (declare (type (function (real) integer) x))
>   ... (funcall #'x 2.5))

I disagree.  Semantics here is not formal semantics, but text
definition semantics.  The definition of a function is mostly that it
returns t for functionp and that it works as a first argument for
funcall.  The difference you are discussing is an efficiency
difference that occurs in the world where the promise you have made is
true; if the promise you have made is not true, you do not have a
valid program.  And as such, the semantic effect in the valid program
case is unaffected by the declaration.
 
So the question becomes: what promise have you made.  And the answer
is that you've promised this is a function with a given type
signature, not a function that, when created, knew it had a particular
type signature and was created with that knowledge in mind.  I claim
you have no way of making the stronger claim that you want to make.

> I haven't seen anywhere in CLHS that says that the list forms of
> function are all equivalent; indeed, since the list form of function
> is on the list of things that subtypep is allowed to be unsure about
> (return NIL for second argument) I'd say that function types are
> allowed to be distinct.

From the CLHS dictionary entry on the FUNCTION class:

  Compound Type Specifier Description:

  The list form of the function type-specifier can be used only for
  declaration and not for discrimination. 

This is another way, IMO, of saying "there is intended to be no
semantic difference; only a potential efficiency difference" of using
these declarations.

> > > Any guidance appreciated.
> > 
> > Guidance?  Don't use these types with TYPEP or SUBTYPEP.  Seriously, I
> > never do and have never missed them.
> > 
> > If you are intent on using them, what are you using them for? Maybe
> > there's another way.
> 
> Well, I'm involved in the implementation of SBCL, the CMUCL
> derivative; as you know, type inference is a good deal of what the
> compiler in these implementations does. In a sense, what I'd like to
> know is if I am "allowed" to interpret the CLHS as permitting
> 
> (subtypep '(function (fixnum fixnum) fixnum) '(function (real integer) t))
> -> T, T
> (subtypep '(function (real integer) t) '(function (fixnum fixnum) fixnum))
> -> NIL, T
> 
> by virtue of my first interpretation, as this would simplify some
> internal type deriving logic.

I personally don't think so.  I think what you can infer is only 
that the individual argument types are promised to be of the 
indicated types, but you can't infer that the function is cast in 
a particular form to receive such arguments.  But that's just me.

I take the opposite stance from what you appear to.  I think you need
specific verbiage that entitles you to an optimization that would preclude
an otherwise reasonable program.  That is, I am anti-optimization in my
politics.  I do not think that optimizations come first and language semantics
second.  I think that this is a language whose very core is about generality,
and that that is what distinguishes it up front from most other languages.
And into that language, we have allowed certain kinds of statements to allow
optimizations that are needed for efficiency, but that you can't just say
"I have an optimization I want to apply, can I abuse this or that syntax
to mean that this is a good place to put it".  I think you are stuck saying
"unless the language offered me a place to put it, I can't put it there 
(without doing some heavy-duty symbolic execution and/or closed-world analysis
that would allow you to infer what isolated statements can't)."

I somehow expect to get beaten up about my newly consed term
"anti-optimization" but I use the term perhaps to provoke discusson if there
is any to be had.  I'm not really against optimizing things.  I just don't
think it's the core of what makes CL valuable to me, and in general I find
the desire for people to do that to be the enemy of most things I value in
terms of stability, portability, etc.  As machines become faster and faster,
I hope we can finally stop obsessing about trivial optimizations and focus
on things that add flexibility instead.  Flexibility and speed have been
traditional enemies, but in a world full of computers that are "fast enough",
flexibility should win, at least over tiny O(1) optimizations, which it looks
to me like this thing  you're looking at is...  Am I missing something?

> I don't plan to do this kind of type testing in user code :)

That makes me feel a little better.
From: Erik Naggum
Subject: Re: FUNCTION types
Date: 
Message-ID: <3223996816584348@naggum.net>
* Christophe Rhodes
> I don't know. I would say not, because
> (defun foo (x)
>   (declare (type (function (integer) integer) x))
>   ... (funcall #'x 2.5))
> can have different semantics from
> (defun foo (x)
>   (declare (type (function (real) integer) x))
>   ... (funcall #'x 2.5))

* Kent M Pitman
| I disagree.  Semantics here is not formal semantics, but text definition
| semantics.  The definition of a function is mostly that it returns t for
| functionp and that it works as a first argument for funcall.  The
| difference you are discussing is an efficiency difference that occurs in
| the world where the promise you have made is true; if the promise you
| have made is not true, you do not have a valid program.  And as such, the
| semantic effect in the valid program case is unaffected by the
| declaration.

  It seems intuitive to me that validity of a program is a semantic issue.
  That is, when the former of Christophe's examples is compiled, it should
  signal an error because the compiler can determine that the promise is a
  lie.  This is the usual definition of "semantics".

  As for all this function type stuff, it appears to me that most of what
  we want to know about the function types should fall out from something
  like (typep #'foo '(function (fixnum fixnum) boolean)), but a quick look
  at typep dispells any hope of this working: It is in fact an _error_ to
  use typep to query an object for its function type.  End of story.  :)

| I somehow expect to get beaten up about my newly consed term
| "anti-optimization" but I use the term perhaps to provoke discusson if
| there is any to be had.

  You might enjoy <url http://www.pgh.net/~newcomer/optimization.htm>.

///                                                             2002-03-01
-- 
  In a fight against something, the fight has value, victory has none.
  In a fight for something, the fight is a loss, victory merely relief.
From: Larry Clapp
Subject: Re: FUNCTION types
Date: 
Message-ID: <i8146a.bg7.ln@rabbit.ddts.net>
In article <················@naggum.net>, Erik Naggum wrote:
>   You might enjoy <url http://www.pgh.net/~newcomer/optimization.htm>.

<aol>
    I dunno if he did, but I sure did.  Thanks!
</aol>

-- Larry
From: Pierpaolo BERNARDI
Subject: Re: FUNCTION types
Date: 
Message-ID: <MqMf8.26421$_u5.775923@news1.tin.it>
"Christophe Rhodes" <·····@cam.ac.uk> ha scritto nel messaggio
···················@cam.ac.uk...
> I'm confused about function types and the relationship between
> them. Consider the two types
>
> (function (fixnum fixnum) fixnum)
>
> and
>
> (function (real integer) t).
>
> What do they actually mean? My na�ve interpretation (from a brief read
> of Body/t_fn.htm in your local friendly hyperspec) is that the first
> type contains the set of all functions that accept two fixnum

... that can *only* accept two fixnum.

> arguments and return a fixnum result, and the second the set of all
> functions that accept a real and an integer argument and return a
> value.

... that can *only* accept a real and an integer.

> According to this, I would submit that
>
> (subtypep '(function (fixnum fixnum) fixnum)
>           '(function (real integer) t))
> -> T, T [ or possibly NIL, NIL ]
>
> as all functions that accept two fixnum arguments and return a fixnum
> value are to be found in the latter set.

Correct values are NIL T.  Issue 176 is worded very clearly.
Perhaps is also correct (but suboptimal), NIL NIL, I don't
have time to check now.

> However, there's an alternative interpretation that seems likely; if
> the second set actually contains all functions that will return a
> value for all (real, integer) argument pairs, then the two types are
> actually disjoint, and the subtypep should return NIL, T [ or possibly
> NIL, NIL ].
>
> Discussion (in FUNCTION-TYPE-ARGUMENT-TYPE-SEMANTICS,
> Issues/iss176_w.htm) seems to imply that the function types should be
> treated much as in my first interpretation, so that we can see if two
> function types are compatible by seeing if one is a subtype of the
> other, though of course the issue writeup does also say that the
> notion of subtype does not make much sense; the issue writeup is not
> part of the specification, I know.

Do we have the same HyperSpec?  Issue 176 is very clearly worded
to imply the opposite of you first interpretation:

    "...a declaration of the form

        (ftype (function (arg0-type arg1-type ...) val-type) f))

    implies that any call of the form (f arg0 arg1 ...) within the scope of
    the declaration can be treated as if it were

      (the val-type (f (the arg0-type arg0) (the arg1-type arg1) ...))

    That is, it is an error for any of the arguments not to be of the
specified
    types or the result not to be of the specified type. (In particular,
    If any argument is not of the correct type,  the result is not
guaranteed
    to be of the specified type.)"


Your second interpretation, even if it makes you predict the
correct values, is foreign to CL.

P.
From: Christophe Rhodes
Subject: Re: FUNCTION types
Date: 
Message-ID: <sqd6yowcfn.fsf@cam.ac.uk>
"Pierpaolo BERNARDI" <··················@hotmail.com> writes:

> "Christophe Rhodes" <·····@cam.ac.uk> ha scritto nel messaggio
> ···················@cam.ac.uk...
> > I'm confused about function types and the relationship between
> > them. Consider the two types
> >
> > (function (fixnum fixnum) fixnum)
> >
> > and
> >
> > (function (real integer) t).
> > According to this, I would submit that
> >
> > (subtypep '(function (fixnum fixnum) fixnum)
> >           '(function (real integer) t))
> > -> T, T [ or possibly NIL, NIL ]
> >
> > as all functions that accept two fixnum arguments and return a fixnum
> > value are to be found in the latter set.
> 
> Correct values are NIL T.  Issue 176 is worded very clearly.
> Perhaps is also correct (but suboptimal), NIL NIL, I don't
> have time to check now.
> 
> > However, there's an alternative interpretation that seems likely; if
> > the second set actually contains all functions that will return a
> > value for all (real, integer) argument pairs, then the two types are
> > actually disjoint, and the subtypep should return NIL, T [ or possibly
> > NIL, NIL ].
> 
> Do we have the same HyperSpec?  Issue 176 is very clearly worded
> to imply the opposite of you first interpretation:
> 
>     "...a declaration of the form
> 
>         (ftype (function (arg0-type arg1-type ...) val-type) f))
> 
>     implies that any call of the form (f arg0 arg1 ...) within the scope of
>     the declaration can be treated as if it were
> 
>       (the val-type (f (the arg0-type arg0) (the arg1-type arg1) ...))
> 
>     That is, it is an error for any of the arguments not to be of the
> specified
>     types or the result not to be of the specified type. (In particular,
>     If any argument is not of the correct type,  the result is not
> guaranteed
>     to be of the specified type.)"

Um, yes, that's the bit I'm using to generate my interpretation.

Consider the two calls

(the fixnum (f (the fixnum arg0) (the fixnum arg1)))
(the t (f (the real arg0) (the integer arg1)))

The set of all fs that will "work" in the first call is a proper subset
of all fs that "work" in the second call, as fixnum is a subtype of
integer, real, and t; hence the first function type is a subtype of
the second subtype.

> Your second interpretation, even if it makes you predict the
> correct values, is foreign to CL.

Good. I'm glad we agree somewhere -- I don't like my second
interpretation either. But I think that your reasoning in deriving
NIL, T as the answer is closer to my second interpretation than you
might like.

I should perhaps note that the motivation behind this is not some
strange micro-optimization, but rather to catch user error by
reasoning about intersections and unions of declared function types.

Christophe
-- 
Jesus College, Cambridge, CB5 8BL                           +44 1223 510 299
http://www-jcsu.jesus.cam.ac.uk/~csr21/                  (defun pling-dollar 
(str schar arg) (first (last +))) (make-dispatch-macro-character #\! t)
(set-dispatch-macro-character #\! #\$ #'pling-dollar)
From: Pierpaolo BERNARDI
Subject: Re: FUNCTION types
Date: 
Message-ID: <U7Of8.26956$_u5.781879@news1.tin.it>
"Christophe Rhodes" <·····@cam.ac.uk> ha scritto nel messaggio
···················@cam.ac.uk...
> "Pierpaolo BERNARDI" <··················@hotmail.com> writes:
>
> > "Christophe Rhodes" <·····@cam.ac.uk> ha scritto nel messaggio
> > ···················@cam.ac.uk...
> > > I'm confused about function types and the relationship between
> > > them. Consider the two types
> > >
> > > (function (fixnum fixnum) fixnum)
> > >
> > > and
> > >
> > > (function (real integer) t).
> > > According to this, I would submit that
> > >
> > > (subtypep '(function (fixnum fixnum) fixnum)
> > >           '(function (real integer) t))
> > > -> T, T [ or possibly NIL, NIL ]
> > >
> > > as all functions that accept two fixnum arguments and return a fixnum
> > > value are to be found in the latter set.

> Um, yes, that's the bit I'm using to generate my interpretation.

Given this reply and Kent's previous one, I am not anymore sure
about _my_ interpretation.

I think my intuition has been misguided by a false analogy with
array type declarations.  Oh well.

BTW, here's Lispworks 4.2:

CL-USER 24 > (subtypep '(function (fixnum fixnum) fixnum)
                       '(function (real integer) t))
NIL
T

Cheers,
P.
From: Pekka P. Pirinen
Subject: Re: FUNCTION types
Date: 
Message-ID: <uwuwpcxde.fsf@globalgraphics.com>
Christophe Rhodes <·····@cam.ac.uk> writes:
> However, there's an alternative interpretation that seems likely; if
> the second set actually contains all functions that will return a
> value for all (real, integer) argument pairs, then the two types are
> actually disjoint, and the subtypep should return NIL, T [ or possibly
> NIL, NIL ].

That's a total function on REAL*INTEGER, and if the committee had
intended it to mean total functions, they'd have said so.  And
provided another declaration, since many useful functions are not
total.  (What Kent is talking about, different kinds of function
objects/entrypoints for different argument types, is a red herring.)

It should return T, T, or NIL, NIL (it's explicitly allowed for
compound FUNCTION specs).

Notwithstanding bugs in LW :-(.  The current bug has been there since
mid-1998, but nobody's noticed as it replaced a more serious one.  We
never coded up the algebra of FUNCTION subtypes, which is why there
aren't many test cases either.  It's not too hard to do in the LW
implementation, though.  I'll file a bug report.
-- 
Pekka P. Pirinen, Global Graphics Software
"You're always going to build a prototype -- the only question
is whether you're going to deliver it to the customer."
  - Bob Martin, Bellcore
From: Christophe Rhodes
Subject: Re: FUNCTION types
Date: 
Message-ID: <sq4rjtebd9.fsf@cam.ac.uk>
···············@globalgraphics.com (Pekka P. Pirinen) writes:

> Christophe Rhodes <·····@cam.ac.uk> writes:
> > However, there's an alternative interpretation that seems likely; if
> > the second set actually contains all functions that will return a
> > value for all (real, integer) argument pairs, then the two types are
> > actually disjoint, and the subtypep should return NIL, T [ or possibly
> > NIL, NIL ].
> 
> That's a total function on REAL*INTEGER, and if the committee had
> intended it to mean total functions, they'd have said so.  And
> provided another declaration, since many useful functions are not
> total.  (What Kent is talking about, different kinds of function
> objects/entrypoints for different argument types, is a red herring.)
> 
> It should return T, T, or NIL, NIL (it's explicitly allowed for
> compound FUNCTION specs).

Oh good. Can I check that you're agreeing with my view that

(subtypep '(function (real integer) t) '(function (fixnum fixnum) fixnum))

is allowed to return NIL, T by the spec (note that I am not asking
whether user code can depend on it returning NIL, T as I agree that
NIL, NIL is also permissible, and by Kent's reasoning T, T is a
possible return value also, so it's probably not completely
_disallowed_)?

Thanks,

Christophe
-- 
Jesus College, Cambridge, CB5 8BL                           +44 1223 510 299
http://www-jcsu.jesus.cam.ac.uk/~csr21/                  (defun pling-dollar 
(str schar arg) (first (last +))) (make-dispatch-macro-character #\! t)
(set-dispatch-macro-character #\! #\$ #'pling-dollar)
From: Pekka P. Pirinen
Subject: Re: FUNCTION types
Date: 
Message-ID: <ug0349v0i.fsf@globalgraphics.com>
Christophe Rhodes <·····@cam.ac.uk> writes:
> Oh good. Can I check that you're agreeing with my view that
> 
> (subtypep '(function (real integer) t) '(function (fixnum fixnum) fixnum))
> 
> is allowed to return NIL, T by the spec

Yes, I agree.  What's not clear is whether you can use them with
SUBTYPEP at all, since they're not for "discrimination".  At least
(SUBTYPEP '(EQL <fn>) '(FUNCTION (FOO) BAR)) is discrimination.

> (note that I am not asking whether user code can depend on it
> returning NIL, T as I agree that NIL, NIL is also permissible, and
> by Kent's reasoning T, T is a possible return value also

I think he's mistaken about that.  Firstly, it's misleading to
consider whether you could call a (FUNCTION (NUMBER) T) with a symbol;
That would depend on the compiler and optimization settings.
Secondly, the default assumption is that there's only one semantics
for a type, so semantics of SUBTYPEP agree with the semantics of
declarations.  For arrays, this is explicitly adjusted by the spec,
but then it also provides tools for determining how array types
behave.  So if SUBTYPEP says types are equivalent, they must be so for
declarations.  And those two types are not.
-- 
Pekka P. Pirinen
A definition tells you something about the way words are used, 
not about the way the universe is put together.
  - Simon van Dongen <sgvd_pi.net>
From: Christophe Rhodes
Subject: Re: FUNCTION types
Date: 
Message-ID: <sq6640e1yn.fsf@cam.ac.uk>
···············@globalgraphics.com (Pekka P. Pirinen) writes:

> Christophe Rhodes <·····@cam.ac.uk> writes:
> > Oh good. Can I check that you're agreeing with my view that
> > 
> > (subtypep '(function (real integer) t) '(function (fixnum fixnum) fixnum))
> > 
> > is allowed to return NIL, T by the spec
> 
> Yes, I agree.  What's not clear is whether you can use them with
> SUBTYPEP at all, since they're not for "discrimination".  At least
> (SUBTYPEP '(EQL <fn>) '(FUNCTION (FOO) BAR)) is discrimination.

Yeah. My reading of that sentence (in .../Body/t_fn.htm) was that
users are not allowed to rely on the answer to TYPEP and SUBTYPEP
queries, not that implementations were required to catch it and tell
the user off. But I could have been missing something, and at least in
some respects it would be nice to issue a warning or style warning
somewhere in safe code.

> > (note that I am not asking whether user code can depend on it
> > returning NIL, T as I agree that NIL, NIL is also permissible, and
> > by Kent's reasoning T, T is a possible return value also
> 
> I think he's mistaken about that.  Firstly, it's misleading to
> consider whether you could call a (FUNCTION (NUMBER) T) with a symbol;
> That would depend on the compiler and optimization settings.
> Secondly, the default assumption is that there's only one semantics
> for a type, so semantics of SUBTYPEP agree with the semantics of
> declarations.  For arrays, this is explicitly adjusted by the spec,
> but then it also provides tools for determining how array types
> behave.  So if SUBTYPEP says types are equivalent, they must be so for
> declarations.  And those two types are not.

Well, I think that you and I are in agreement, anyway.  I haven't
heard anything that expressly _forbids_ an implementation from taking
my interpretation, so I may just go off and see if I can put it into
practice, and report back if I come up against any more snags...

Christophe
-- 
Jesus College, Cambridge, CB5 8BL                           +44 1223 510 299
http://www-jcsu.jesus.cam.ac.uk/~csr21/                  (defun pling-dollar 
(str schar arg) (first (last +))) (make-dispatch-macro-character #\! t)
(set-dispatch-macro-character #\! #\$ #'pling-dollar)