Tenho uma classe na qual quero que alguns slots sejam nulos quando o objeto for criado, mas eles devem ser configuráveis apenas com objetos de um determinado tipo. Algo como:
(defclass Something ()
((foo :initarg :foo
:type (or character 'nil)
:initform nil
:accessor something-foo)))
Se eu disser apenas :type character
, ou :type (or character nil)
, então o SBCL reclama por NIL
não ser do tipo de caractere declarado. Se eu disser :type (or character 'nil)
, então parece que ele aceita caracteres e o tipo de símbolo, já que qualquer símbolo parece ser:
CL-USER> (defvar *foo* (make-instance 'Something))
*FOO*
CL-USER> (setf (something-foo *foo*) 'test)
TEST
CL-USER> (something-foo *foo*)
TEST
Existe uma maneira de afirmar que um slot é nulo ou possui o tipo fornecido? Ou devo simplesmente omitir o especificador de tipo e afirmar o tipo no método acessador ou escritor?
Editar:
Depois de pensar um pouco, talvez a expressão seja: :type character
deixe-o desvinculado e verifique se o slot está vinculado ou não, em vez de verificar se é nulo ou não nulo?
NIL
é o tipo vazio, não contém nenhum valor (como o conjunto vazio em matemática).O tipo que contém o valor
NIL
éNULL
. Então o que você quer éLembre-se: tipos dentro de um tipo composto não são avaliados, então você não precisa e também não pode citá-los.
Que tipo tem o objeto
NIL
?Então,
nil
é do tiponull
?Então,
nil
é do tipo(or character null)
?Em vez disso,
null
também podemos usar o tipo(eql nil)
. Este tipo descreve o conjunto exato do objetonil
. Podemos usá-lo em nossa expressão de tipo:Também podemos usar um
member
tipo em nossa expressão de tipo, ondenil
é do tipo(member nil)
:Assim, os tipos compostos
(member nil)
e(eql nil)
descrevem os mesmos objetos que o especificador de tipo atômico padronizadonull
. Qualquer um deles pode ser usado no seu tipo de slot, enquanto eu preferiria usar o tipo mais simples, aqui o tipoNULL
.