From: David Bakhash
Subject: Re: can `nil' be of type `integer' ?
Date: 
Message-ID: <cxjg1f0yi8k.fsf@engc.bu.edu>
Marco Antoniotti <·······@galileo.parades.rm.cnr.it> writes:

> Anyway, the way I handle these situations is like this
> 
> (defstruct person
>    (age nil :type (or null fixnum)))
> 
> In this way you can use 'nil' as the 'missing' or 'uninitialized'
> value. Another way would to write

this is *exactly* what I'm gonna do.  `nil' is very useful for me,
because, in the case I was dealing with, there was no number that was
fitting to put.  I wanted a way to say "I have not filled in this slot 
yet".  Thanks!  I forgot you can specify types with `or'.  thanks,
marco.

dave

From: Howard R. Stearns
Subject: Re: can `nil' be of type `integer' ?
Date: 
Message-ID: <35D32815.9C70A532@elwood.com>
David Bakhash wrote:
> 
> Marco Antoniotti <·······@galileo.parades.rm.cnr.it> writes:
> 
> > Anyway, the way I handle these situations is like this
> >
> > (defstruct person
> >    (age nil :type (or null fixnum)))
> >
> > In this way you can use 'nil' as the 'missing' or 'uninitialized'
> > value. Another way would to write
> 
> this is *exactly* what I'm gonna do.  `nil' is very useful for me,
> because, in the case I was dealing with, there was no number that was
> fitting to put.  I wanted a way to say "I have not filled in this slot
> yet".  Thanks!  I forgot you can specify types with `or'.  thanks,
> marco.
> 
> dave

Wait!!!

If you are using the :type specification for safety (and are
correspondingly compling EVERYTHING with (optimize safety)), then (or
null fixnum) is fine.

On the other hand, if you are using the :type specification in the hopes
of getting better performance, it is unlikely that a compiler will
recognize (or null fixnum) specially and store the age as a machine
'int' and use only untyped machine arithmetic operations on it.  

(In the particular case of (or null fixnum) as opposed to any other OR
such as (or symbol fixnum), I think a compiler COULD reasonably generate
efficient code, but I've never heard of any that do.  Does anyone know
otherwise?)

You might consider leaving things as (age nil :type fixnum).  This IS
LEGAL as long as all instances of PERSON are actually created with a
fixnum age.  (eg. using the default constructor, one must always supply
the :age argument.)  From the HyperSpec:

"Each slot-initform supplied for a defstruct component, when used by the
constructor function for an otherwise
unsupplied component, is re-evaluated on every call to the constructor
function. The slot-initform is not evaluated
unless it is needed in the creation of a particular structure instance.
If it is never needed, there can be no
type-mismatch error, even if the type of the slot is specified; no
warning should be issued in this case. For example,
in the following sequence, only the last call is an error. 

 (defstruct person (name 007 :type string)) 
 (make-person :name "James")
 (make-person)

It is as if the slot-initforms were used as initialization forms for the
keyword parameters of the constructor
function."

Actually, I think there is a whole in the above spec.  Consider the
code:

(let ((x 3))
  (declare (type fixnum x))
  (when (never-happens) (setq x nil)))

I would think that a compiler is justified in issuing a compile-time
warning for this code (unless the compiler can probe that path will not
be taken).  It further seems to me that allowing/requesting the compiler
to signal a warning here, but not in the defstruct case is asking a bit
much -- i.e. the two situations are too much the same.
From: Marco Antoniotti
Subject: Re: can `nil' be of type `integer' ?
Date: 
Message-ID: <lw4svfstia.fsf@galileo.parades.rm.cnr.it>
"Howard R. Stearns" <······@elwood.com> writes:

> ... lots of good things.

I stand corrected.
-- 
Marco Antoniotti ===========================================
PARADES, Via San Pantaleo 66, I-00186 Rome, ITALY
tel. +39 - (0)6 - 68 80 79 23, fax. +39 - (0)6 - 68 80 79 26
http://www.parades.rm.cnr.it
From: Rick Campbell
Subject: Re: can `nil' be of type `integer' ?
Date: 
Message-ID: <87btpnfnme.fsf@germs.erols.com>
"Howard R. Stearns" <······@elwood.com> writes:
> David Bakhash wrote:
> > Marco Antoniotti <·······@galileo.parades.rm.cnr.it> writes:
> > > Anyway, the way I handle these situations is like this
> > >
> > > (defstruct person
> > >    (age nil :type (or null fixnum)))
> > >
> 
> On the other hand, if you are using the :type specification in the hopes
> of getting better performance, it is unlikely that a compiler will
> recognize (or null fixnum) specially and store the age as a machine
> 'int' and use only untyped machine arithmetic operations on it.  
> 
> (In the particular case of (or null fixnum) as opposed to any other OR
> such as (or symbol fixnum), I think a compiler COULD reasonably generate
> efficient code, but I've never heard of any that do.  Does anyone know
> otherwise?)

Actually CMUCL does type inferencing that allows optimization in
appropriate contexts, e. g.:

 (let ((age (person-age joe)))
   (when age
     ;; Compiler can infer (declare (fixnum age)) here
     ...))

One could normally argue that without checking the value of
most-positive-fixnum in your implementation that this using a fixnum
declaration is a bad idea -- (integer 0 150) as Marco suggested is
better -- but in this particular situation you should be pretty safe.

--
Rick Campbell <········@cyberpass.net>
From: Raymond Toy
Subject: Re: can `nil' be of type `integer' ?
Date: 
Message-ID: <4nu33f8f9p.fsf@rtp.ericsson.se>
>>>>> "Rick" == Rick Campbell <····@lehman.com> writes:

    Rick> Actually CMUCL does type inferencing that allows optimization in
    Rick> appropriate contexts, e. g.:

    Rick>  (let ((age (person-age joe)))
    Rick>    (when age
    Rick>      ;; Compiler can infer (declare (fixnum age)) here
    Rick>      ...))

    Rick> One could normally argue that without checking the value of
    Rick> most-positive-fixnum in your implementation that this using a fixnum
    Rick> declaration is a bad idea -- (integer 0 150) as Marco suggested is
    Rick> better -- but in this particular situation you should be pretty safe.

But if you left age declared as a fixnum, and if you did any kind of
arithmetic on it, the compiler would have to call the generic
arithmetic functions.  With Marco's suggestions, the compiler could
know when to call the generic functions and when not to and that would 
help out on speed.

Ray
From: Tim Bradshaw
Subject: Re: can `nil' be of type `integer' ?
Date: 
Message-ID: <ey3n293ex7z.fsf@todday.aiai.ed.ac.uk>
* Howard R Stearns wrote:

> (In the particular case of (or null fixnum) as opposed to any other OR
> such as (or symbol fixnum), I think a compiler COULD reasonably generate
> efficient code, but I've never heard of any that do.  Does anyone know
> otherwise?)

I suspect CMUCL can do this, actually.  At least it should only need
to check a very slight amount.


> You might consider leaving things as (age nil :type fixnum).  This IS
> LEGAL as long as all instances of PERSON are actually created with a
> fixnum age.  (eg. using the default constructor, one must always supply
> the :age argument.)  From the HyperSpec:

When I do this sort of thing, I tend to write:

	(age (error "No age") :type ...)

which I think makes it a lot clearer that you have to provide an
initial value, and also prevents the nasty case of turning off enough
safety that the compiler interprets what is really NIL as some fixnum.

--tim
From: Jeff Dalton
Subject: Re: can `nil' be of type `integer' ?
Date: 
Message-ID: <x2soiudyqw.fsf@gairsay.aiai.ed.ac.uk>
"Howard R. Stearns" <······@elwood.com> writes:

> "Each slot-initform supplied for a defstruct component, when used by the
> constructor function for an otherwise
> unsupplied component, is re-evaluated on every call to the constructor
> function. The slot-initform is not evaluated
> unless it is needed in the creation of a particular structure instance.
> If it is never needed, there can be no
> type-mismatch error, even if the type of the slot is specified; no
> warning should be issued in this case. For example,
> in the following sequence, only the last call is an error. 

>  (defstruct person (name 007 :type string)) 
>  (make-person :name "James")
>  (make-person)

> It is as if the slot-initforms were used as initialization forms for the
> keyword parameters of the constructor function."

> Actually, I think there is a whole in the above spec.  Consider the
> code:

> (let ((x 3))
>   (declare (type fixnum x))
>   (when (never-happens) (setq x nil)))

> I would think that a compiler is justified in issuing a compile-time
> warning for this code (unless the compiler can probe that path will not
> be taken).  It further seems to me that allowing/requesting the compiler
> to signal a warning here, but not in the defstruct case is asking a bit
> much -- i.e. the two situations are too much the same.

All the compiler has to do re the defstruct case is never issue a
warning when checking the type of an initform against the type of a
slot.  It will therefore never issue a warning in the case where the
initform is never evaluated.

The spec might need some rewording, but I would still want it to
continue to tell compilers not to issue a warning in just because an
initform doesn't match the slot type.  The syntax requires an initform
in order to have a type specified.  But it will not always be easy to
have something of the right type just to shut up compiler warnings.
Programmers can probably work around the problem one way or another,
but they shouldn't have to do so.

However, there's a general question about compile-time errors and
warnings when code might not be evaluated.  In an interactive
implementation, the compiler may not be able to tell whether a
function defined at top level is every called, and in many
programs this will cover virtually all of the code.

-- jd
From: Marco Antoniotti
Subject: Re: can `nil' be of type `integer' ?
Date: 
Message-ID: <lwbtporrex.fsf@galileo.parades.rm.cnr.it>
David Bakhash <·····@bu.edu> writes:

> Marco Antoniotti <·······@galileo.parades.rm.cnr.it> writes:
> 
> > Anyway, the way I handle these situations is like this
> > 
> > (defstruct person
> >    (age nil :type (or null fixnum)))
> > 
> > In this way you can use 'nil' as the 'missing' or 'uninitialized'
> > value. Another way would to write
> 
> this is *exactly* what I'm gonna do.  `nil' is very useful for me,
> because, in the case I was dealing with, there was no number that was
> fitting to put.  I wanted a way to say "I have not filled in this slot 
> yet".  Thanks!  I forgot you can specify types with `or'.  thanks,
> marco.
> 

You are welcome.

Of course, you pay for this sort of things.

Every time you need to use the slot value you need to test for 'null-ness'.

-- 
Marco Antoniotti ===========================================
PARADES, Via San Pantaleo 66, I-00186 Rome, ITALY
tel. +39 - (0)6 - 68 80 79 23, fax. +39 - (0)6 - 68 80 79 26
http://www.parades.rm.cnr.it