From: Jason Nielsen
Subject: Is the following behavior defined by the standard or implementation specific?
Date: 
Message-ID: <Pine.LNX.4.64.0707281235130.23181@janus>
I was wondering if the behavior of the following two (very simple) 
programs is defined by the standard or is implementation specific.  In 
SBCL using disassemble they seem to produce identical code but my quick 
perusal of the hyperspec didn't enlighten me.  Thanks.


(declaim (ftype (function (double-float double-float) double-float) sss))
(defun sss (x y) (+ x y))

(defun bbb (x y)
    (declare (type double-float x y))
    (the double-float (+ x y)))

From: Kent M Pitman
Subject: Re: Is the following behavior defined by the standard or implementation specific?
Date: 
Message-ID: <uodhwcmei.fsf@nhplace.com>
Jason Nielsen <···@cs.sfu.ca> writes:

> I was wondering if the behavior of the following two (very simple)
> programs is defined by the standard or is implementation specific.  In
> SBCL using disassemble they seem to produce identical code but my
> quick perusal of the hyperspec didn't enlighten me.  Thanks.
> 
> 
> (declaim (ftype (function (double-float double-float) double-float) sss))
> (defun sss (x y) (+ x y))
> 
> (defun bbb (x y)
>     (declare (type double-float x y))
>     (the double-float (+ x y)))

Behavior?  Somehow I think you're assuming that declarations are about
behavior.  Largely, they are not.  I'd say, informally, that one way
to look at it is this: They are mostly about you promising to only do
a subset of what you might otherwise do, in order to free the
implementation of requirements to implement additional behavior that
would have been required had you not made those declarations.

What the spec says, that I could think of, is:

 * SSS and BBB will add two numbers [because you used +].
 * You have promised in each case that you will never give them other
   than double floats.
 * You have promised in each case that the primary result will be a
   double float.  [The function + has no other return values, so that
   is probably all that matters. It's worth noting that if + could return
   additional values, you've made no promises about what their type might
   be.]

(I'm assuming all of the above is in the CL-USER package and that this isn't
a private, shadowed function + in some other package, etc.)

So, as I read it, the behavior is explicitly stated in the spec to be
"adds two double floats" if that's what you give it, and "undefined"
otherwise.  An implementation is not required to give you the same code,
but it's hardly surprising if it does.

Declarations in CL are about things you tell the compiler that it might or
might not know about already.  It is allowed to tell you that you are lying.
It is also allowed to take you at your word and rely on those statements in
order to produce faster code at the expense of error checking.  It is further
allowed to just ignore your declarations.

Declarations in CL are not like they were in Maclisp where you were
saying that the function is to be compiled in a special mode that can
only be called if the caller is informed of the declarations.

Declarations in CL are not like they are in C++ and other languages where
you can only say what the compiler can prove.

Declarations in CL are not like in some languages where declaring a type
is a kind of overloading.  In CL, you are not free to go and define other
definitions with different types; you're to use DEFMETHOD if you want that
behavior.

Why are you asking, though?  Is there some action you would take
differently if you got a different answer?  What other possible answers
had you expected?
From: Jason Nielsen
Subject: Re: Is the following behavior defined by the standard or implementation specific?
Date: 
Message-ID: <Pine.LNX.4.64.0707281356550.23181@janus>
>
> Why are you asking, though?  Is there some action you would take
> differently if you got a different answer?  What other possible answers
> had you expected?
>

I've been doing some numerical work in cl and for such things adding 
simple declarations makes my code quite a bit faster.  However, I was 
getting tired of adding declarations... and I find that how you declare 
types is somewhat inconsistent (defun, defclass, defstruct, let, etc.) so 
I decided to write some macros that would make my life easier.  Sort of a 
typed sub-set of common lisp for things where I would like to help the 
compiler along but with a syntax that is easier for me to remember.

Thanks,
Jason
From: Kent M Pitman
Subject: Re: Is the following behavior defined by the standard or implementation specific?
Date: 
Message-ID: <uk5skcjkj.fsf@nhplace.com>
Jason Nielsen <···@cs.sfu.ca> writes:

> >
> > Why are you asking, though?  Is there some action you would take
> > differently if you got a different answer?  What other possible answers
> > had you expected?
> >
> 
> I've been doing some numerical work in cl and for such things adding
> simple declarations makes my code quite a bit faster.  However, I was
> getting tired of adding declarations... and I find that how you
> declare types is somewhat inconsistent (defun, defclass, defstruct,
> let, etc.) so I decided to write some macros that would make my life
> easier.  Sort of a typed sub-set of common lisp for things where I
> would like to help the compiler along but with a syntax that is easier
> for me to remember.

I see. In Maclisp, ages ago, +$ was + for floats.  You could follow that
naming lead and do something vaguely like:

 (declaim (inline +$))
 (defun +$ (x y)
   (locally (declare (type double-float x y)
                     (optimize (speed 3) (safety 0) (debug 0)
                               (compilation-speed 0) (space 0)))
     (the double-float (+ x y))))

I generally don't like doing such declarations globally, but in cases
like this where one is just trying to do a simple operation that you
have typechecked in advance, I think it's nicely localized and much
easier to feel is safe than if you're declaring those options around
operations where you don't know the effect.

Incidentally, I can't recall offhand exactly where, but there are
cases where I've thought the DYNAMIC-EXTENT declaration might be
useful in presenting some boxing if compilers were smart enough to
catch the idiom.  I avoid floats where possible, but as I recall,
a lot of double problems can be due to boxing and not so much due to
actual type operations per se.
From: ········@tochka.ru
Subject: Re: Is the following behavior defined by the standard or implementation specific?
Date: 
Message-ID: <1185683093.094954.32880@g4g2000hsf.googlegroups.com>
On Jul 28, 11:44 pm, Jason Nielsen <····@cs.sfu.ca> wrote:
> (declaim (ftype (function (double-float double-float) double-float) sss))
> (defun sss (x y) (+ x y))
>
> (defun bbb (x y)
>     (declare (type double-float x y))
>     (the double-float (+ x y)))

Bodies of the functions are the same, but their callers are
compiled differently. With the global declaration every caller
knows, that the function succeeds only when the arguments are
DOUBLE-FLOATs, and the result of the call always is of the same
type. Without the declaration the type of the function is known
only in the functions defined in the same file as BBB and only
when the file is processed by COMPILE-FILE.
From: Thomas F. Burdick
Subject: Re: Is the following behavior defined by the standard or implementation specific?
Date: 
Message-ID: <1185700941.801310.90300@l70g2000hse.googlegroups.com>
Jason Nielsen wrote:
> I was wondering if the behavior of the following two (very simple)
> programs is defined by the standard or is implementation specific.  In
> SBCL using disassemble they seem to produce identical code but my quick
> perusal of the hyperspec didn't enlighten me.  Thanks.
>
>
> (declaim (ftype (function (double-float double-float) double-float) sss))
> (defun sss (x y) (+ x y))
>
> (defun bbb (x y)
>     (declare (type double-float x y))
>     (the double-float (+ x y)))

As was mentioned by another poster, one difference is in callers to
the functions.  What you've told the compiler about SSS is that not
only the type of the function that you defined below; you also told it
that if you ever redefine the function that function will also have
the type you declaimed.   This can affect the compilation of functions
which call SSS, and (in the case of SBCL) elicit warnings from the
compiler if you try to redefine SSS incompatibly, eg:

  (defun sss (x y)
    (declare (single-float x y))
    ;; Adding two floats results in a float, which the type inferencer
knows, so there's no
    ;; need for a THE here.
    (+ x y))

As Kent already mentioned, the standard doesn't define any behavior
associated with type declarations, and in fact existing
implementations take quite different views as to what they mean.  The
two extremes are SBCL on the one hand, which when compiling safe code
strictly and precisely enforces all declarations as though they had
been assertions, and unless you turn safety down to 0 will continue to
enforce them, only omitting range checks for numbers; Allegro on the
other hand treats type declarations as promises you've made to the
compiler, and if you compile optimizing for speed, it will happily
believe your promises, giving you 0 as the result of (car x) where x
is not the cons you promised, but a string.

Obviously the SBCL interpretation encourages more frequent use of type
declarations; you want to be sure you're not lying when using type
declarations in Allegro.  On the other hand, senselessly inserting
type declarations everywhere throughout your code can in certain
situations slow things down with SBCL, if it can't remove some of the
generated assertions.

One last note: you might be interested in the sb-ext:*derive-function-
types* switch in SBCL.  It gives a slightly different and non-ANSI
behavior to type declarations: it more or less declaims the ftype that
the compiler is able to inference whenever you define a function.  So
you can write code like:

  (defun sss (x y)
    (declare (double-float x y))
    (+ x y))

And it would have the same effect as the ftype declaration you gave
above.
From: Pascal Costanza
Subject: Re: Is the following behavior defined by the standard or implementation specific?
Date: 
Message-ID: <5h36c2F3g0tbnU1@mid.individual.net>
Thomas F. Burdick wrote:

> Obviously the SBCL interpretation encourages more frequent use of type
> declarations; you want to be sure you're not lying when using type
> declarations in Allegro.  On the other hand, senselessly inserting
> type declarations everywhere throughout your code can in certain
> situations slow things down with SBCL, if it can't remove some of the
> generated assertions.

Shouldn't senseless insertions of type declarations be considered a form 
of premature optimization anyway?


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Thomas F. Burdick
Subject: Re: Is the following behavior defined by the standard or implementation specific?
Date: 
Message-ID: <1185726652.547861.234720@q75g2000hsh.googlegroups.com>
On Jul 29, 11:53 am, Pascal Costanza <····@p-cos.net> wrote:
> Thomas F. Burdick wrote:
> > Obviously the SBCL interpretation encourages more frequent use of type
> > declarations; you want to be sure you're not lying when using type
> > declarations in Allegro.  On the other hand, senselessly inserting
> > type declarations everywhere throughout your code can in certain
> > situations slow things down with SBCL, if it can't remove some of the
> > generated assertions.
>
> Shouldn't senseless insertions of type declarations be considered a form
> of premature optimization anyway?

Not necessarily premature, but definitely a bad idea.  It seems to be
one of the common foolish approaches that Lisp newbies have when
trying to speed up the inner loop of their image processing / dna
sequencing / whatever application.
From: Robert Uhl
Subject: Re: Is the following behavior defined by the standard or implementation specific?
Date: 
Message-ID: <m3abtdvq8g.fsf@latakia.dyndns.org>
"Thomas F. Burdick" <········@gmail.com> writes:
>
>> Shouldn't senseless insertions of type declarations be considered a
>> form of premature optimization anyway?
>
> Not necessarily premature, but definitely a bad idea.  It seems to be
> one of the common foolish approaches that Lisp newbies have when
> trying to speed up the inner loop of their image processing / dna
> sequencing / whatever application.

How would you approach speeding up the inner loop?  I spent some time a
few months back working on the SPOJ contest with Lisp, and while in some
cases it made sense to look at rolling my own string input and so forth,
normally it ended up being an exercise in declarations.

-- 
Robert Uhl <http://public.xdi.org/=ruhl>
If I had foreseen the use those people designed to make of their
victory, there would have been no surrender at Appomattox Courthouse; no
sir, not by me.  Had I foreseen these results of subjugation, I would
have preferred to die at Appomattox with my brave men, my sword in my
right hand.                                           --Robert E. Lee
From: Robert Uhl
Subject: Re: Is the following behavior defined by the standard or implementation specific?
Date: 
Message-ID: <m3ejipvqc0.fsf@latakia.dyndns.org>
"Thomas F. Burdick" <········@gmail.com> writes:
>
> One last note: you might be interested in the sb-ext:*derive-function-
> types* switch in SBCL.  It gives a slightly different and non-ANSI
> behavior to type declarations: it more or less declaims the ftype that
> the compiler is able to inference whenever you define a function.  So
> you can write code like:
>
>   (defun sss (x y)
>     (declare (double-float x y))
>     (+ x y))
>
> And it would have the same effect as the ftype declaration you gave
> above.

Ooooh--nice.  I'll have to play with that some.  I wonder if it'd also
do the warning-if-redefined-incompatibly bit.  That could actually be
pretty sweet.

-- 
Robert Uhl <http://public.xdi.org/=ruhl>
Even you automobilists can spot where this is going, right?  Mountain
bikes are the SUVs among bicycles.                  --Maarten Wiltink
From: John Thingstad
Subject: Re: Is the following behavior defined by the standard or implementation specific?
Date: 
Message-ID: <op.twag5wndpqzri1@pandora.upc.no>
P� Mon, 30 Jul 2007 17:55:27 +0200, skrev Robert Uhl  
<·········@NOSPAMgmail.com>:

> "Thomas F. Burdick" <········@gmail.com> writes:
>>
>> One last note: you might be interested in the sb-ext:*derive-function-
>> types* switch in SBCL.  It gives a slightly different and non-ANSI
>> behavior to type declarations: it more or less declaims the ftype that
>> the compiler is able to inference whenever you define a function.  So
>> you can write code like:
>>
>>   (defun sss (x y)
>>     (declare (double-float x y))
>>     (+ x y))
>>
>> And it would have the same effect as the ftype declaration you gave
>> above.
>
> Ooooh--nice.  I'll have to play with that some.  I wonder if it'd also
> do the warning-if-redefined-incompatibly bit.  That could actually be
> pretty sweet.
>

Erm wouldn't you need a (declaim (inline sss)) before it made much  
difference.
(Except on Allegro which inlines automatically)
Function calls are expensive in that you look up the address of the  
function then call it.