From: Matthew X. Economou
Subject: Enforcing type specifications
Date: 
Message-ID: <uabz7a0ap.fsf@irtnog.org>
Are type specifications in Common Lisp intended to enforce constraints
on the type of a place's value (whether that place is a slot, a
function's argument, a lexical or dynamic binding, etc.), or are type
specs used only for optimization (if those declarations are used at
all)?  For example, if I define the following class in clisp, I can
assign values to the slot that violate the type specification:

	[1]> (defclass test ()
	        ((mode :type (member :one :two :three)
	               :initform :one)))
	#<STANDARD-CLASS TEST>
	[2]> (setq test-instance (make-instance 'test))
	#<TEST #x10202FF5>
	[3]> (slot-value test-instance 'mode)
	:ONE
	[4]> (setf (slot-value test-instance 'mode) 1)
	1
	[5]> (slot-value test-instance 'mode)
        1

(I experienced identical behavior in SBCL and CMUCL.)  I would have
expected that, at the default safety and optimization settings, an
implementation would signal a type error when a value doesn't match a
place's type specification.

Could a implementation enforce type specifications and still be
conforming?  (From this behavior, I take it that portable code cannot
rely on type specifications and must include explicit type checks as
needed.)

In the case of classes and the slot-value accessor, how could one
portably augment slot-value such that it would include strict type
checks, or is one forced to create their own accessor function which
would include an explicit type check?

Best wishes,
Matthew

-- 
"Rogues are very keen in their profession, and know already much more
than we can teach them respecting their several kinds of roguery."
  - A. C. Hobbs in _Locks and Safes_ (1853)

From: Pascal Costanza
Subject: Re: Enforcing type specifications
Date: 
Message-ID: <543lquF1v0t7vU1@mid.individual.net>
Matthew X. Economou wrote:

> In the case of classes and the slot-value accessor, how could one
> portably augment slot-value such that it would include strict type
> checks, or is one forced to create their own accessor function which
> would include an explicit type check?

Kenny won't like this, but you can use the CLOS MOP for this:

(defclass enforced-types-class (standard-class)
   ())

(defmethod validate-superclass
   ((class enforced-types-class)
    (superclass standard-class))
   t)

(defmethod (setf slot-value-using-class) :before
   (new-value (class enforced-types-class) object slot)
   (assert (typep new-value (slot-definition-type slot)))

[Untested.]


Your classes have to be instances of that metaclass:

(defclass foo (...)
   (...)
   (:metaclass enforced-types-class))


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: Rainer Joswig
Subject: Re: Enforcing type specifications
Date: 
Message-ID: <joswig-732BEE.21021221022007@news-europe.giganews.com>
In article <·············@irtnog.org>,
 "Matthew X. Economou" <···············@irtnog.org> wrote:

> Are type specifications in Common Lisp intended to enforce constraints
> on the type of a place's value (whether that place is a slot, a
> function's argument, a lexical or dynamic binding, etc.), or are type
> specs used only for optimization (if those declarations are used at
> all)?  For example, if I define the following class in clisp, I can
> assign values to the slot that violate the type specification:
> 
> 	[1]> (defclass test ()
> 	        ((mode :type (member :one :two :three)
> 	               :initform :one)))
> 	#<STANDARD-CLASS TEST>
> 	[2]> (setq test-instance (make-instance 'test))
> 	#<TEST #x10202FF5>
> 	[3]> (slot-value test-instance 'mode)
> 	:ONE
> 	[4]> (setf (slot-value test-instance 'mode) 1)
> 	1
> 	[5]> (slot-value test-instance 'mode)
>         1
> 
> (I experienced identical behavior in SBCL and CMUCL.)  I would have
> expected that, at the default safety and optimization settings, an
> implementation would signal a type error when a value doesn't match a
> place's type specification.
> 
> Could a implementation enforce type specifications and still be
> conforming?  (From this behavior, I take it that portable code cannot
> rely on type specifications and must include explicit type checks as
> needed.)
> 

OpenMCL checks.

joswig$ openmcl
Welcome to OpenMCL Version 1.1-pre-070214 (DarwinX8664)!
? (defclass test ()
                ((mode :type (member :one :two :three)
                       :initform :one)))
#<STANDARD-CLASS TEST>
? (setq test-instance (make-instance 'test))
#<TEST #x300040D995FD>
? (slot-value test-instance 'mode)
:ONE
? (setf (slot-value test-instance 'mode) 1)
> Error: The value 1 can not be used to set the value of the slot MODE in #<TEST #x300040D995FD>, because it is not of type (MEMBER :ONE :TWO :THREE). 
> While executing: #<CCL::STANDARD-KERNEL-METHOD (SETF SLOT-VALUE-USING-CLASS) (T STANDARD-CLASS T STANDARD-EFFECTIVE-SLOT-DEFINITION)>, in process listener(1).
> Type :POP to abort, :R for a list of available restarts.
> Type :? for other options.
1 > 


In general most of the time Lisp systems won't check this.
Some (SBCL, CMUCL) may statically check during compilation
and give warnings.


> In the case of classes and the slot-value accessor, how could one
> portably augment slot-value such that it would include strict type
> checks, or is one forced to create their own accessor function which
> would include an explicit type check?
> 
> Best wishes,
> Matthew
From: Christian von Essen
Subject: Re: Enforcing type specifications
Date: 
Message-ID: <87tzxemy2m.fsf@think41.vehome.de>
"Matthew X. Economou" <···············@irtnog.org> writes:

> Are type specifications in Common Lisp intended to enforce constraints
> on the type of a place's value (whether that place is a slot, a
> function's argument, a lexical or dynamic binding, etc.), or are type
> specs used only for optimization (if those declarations are used at
> all)?  For example, if I define the following class in clisp, I can
> assign values to the slot that violate the type specification:
>
> 	[1]> (defclass test ()
> 	        ((mode :type (member :one :two :three)
> 	               :initform :one)))
> 	#<STANDARD-CLASS TEST>
> 	[2]> (setq test-instance (make-instance 'test))
> 	#<TEST #x10202FF5>
> 	[3]> (slot-value test-instance 'mode)
> 	:ONE
> 	[4]> (setf (slot-value test-instance 'mode) 1)
> 	1
> 	[5]> (slot-value test-instance 'mode)
>         1
>
> (I experienced identical behavior in SBCL and CMUCL.)  I would have
> expected that, at the default safety and optimization settings, an
> implementation would signal a type error when a value doesn't match a
> place's type specification.
>
> [...]
>
> Best wishes,
> Matthew

Hi,

for SBCLhttp://www.sbcl.org/manual/Declarations-as-Assertions.html#Declarations-as-Assertions
says the following:

"Full Type Checks
    All declarations are considered assertions to be checked at runtime,
    and all type checks are precise.

    Used when (>= safety (max speed space compilation-speed).
    The default compilation policy provides full type checks."

This seems to be the default policy.
    
Your example gives me (using SBCL 1.0):

CL-USER> (setf (slot-value *inst* 'mode) :four)

The value :FOUR is not of type (MEMBER :THREE :TWO :ONE).
   [Condition of type TYPE-ERROR]


   
Christian
From: Matthew X. Economou
Subject: Re: Enforcing type specifications
Date: 
Message-ID: <uzm74q0ll.fsf@irtnog.org>
>>>>> "Christian" == Christian von Essen <·········@mvonessen.de> writes:

    Christian> SBCL says the following:

    Christian> "Full Type Checks All declarations are considered
    Christian> assertions to be checked at runtime, and all type
    Christian> checks are precise.

    Christian> Your example gives me (using SBCL 1.0):

    CL-USER> (setf (slot-value *inst* 'mode) :four)

    Christian> The value :FOUR is not of type (MEMBER :THREE :TWO
    Christian> :ONE). [Condition of type TYPE-ERROR]

I tried my example program on SBCL under FreeBSD when I posted, but I
didn't receive that error.  Thanks for following up with a pointer to
the documentation.

Best wishes,
Matthew

-- 
"Rogues are very keen in their profession, and know already much more
than we can teach them respecting their several kinds of roguery."
  - A. C. Hobbs in _Locks and Safes_ (1853)