In
(let ((x <expression>))
(declare (type <type> x))
...)
we have, of course, declared the type of the variable X; the
consequences of the value of <expression> not being of that type are
undefined. It may or may not be possible to determine that at compile
time.
On the other hand, in
(let ((x (the <type> <expression>)))
...)
we have not declared anything about the type of the variable X, but
only what the type of its initial value is. The language processor is
not obliged to infer anything about the type of X from that; and if it
does, the result will depend on what else is happening to X (as well
as on the implementation, of course). For example, in
(let ((x (the fixnum (g y))))
(h x)
(setq x (the double-float (u z)))
(v x)
(setq x (w s))
(mu x))
(OR FIXNUM DOUBLE-FLOAT) would have to be a subtype of the inferred
type of X, which will also depend on what is known about W's return
type and the type of MU's argument.
By the way, the THE form is redundant in (THE FIXNUM 2). Something
like (THE FIXNUM (+ I J)) would be more interesting.
---Vassil.
--
Vassil Nikolov <········@pobox.com>
(1) M(Gauss);
(2) M(a) if M(b) and declared(b, M(a)),
where M(x) := "x is a mathematician".
On Jun 26, 6:04 am, Vassil Nikolov <········@pobox.com> wrote:
> In
>
> (let ((x <expression>))
> (declare (type <type> x))
> ...)
>
> we have, of course, declared the type of the variable X; the
> consequences of the value of <expression> not being of that type are
> undefined. It may or may not be possible to determine that at compile
> time.
>
> On the other hand, in
>
> (let ((x (the <type> <expression>)))
> ...)
>
> we have not declared anything about the type of the variable X, but
> only what the type of its initial value is. The language processor is
> not obliged to infer anything about the type of X from that; and if it
> does, the result will depend on what else is happening to X (as well
> as on the implementation, of course).
Yeah, I'm trying to get to the type information the compiler is
finding. If I've understood how this works (or is supposed to work?),
it will "never" infer too optimistic or specific types -- at least not
"on its own". So if it can't be sure at all, it'll fall back to T. At
least I think that's what will and is supposed happen. :)
> For example, in
>
> (let ((x (the fixnum (g y))))
> (h x)
> (setq x (the double-float (u z)))
> (v x)
> (setq x (w s))
> (mu x))
>
> (OR FIXNUM DOUBLE-FLOAT) would have to be a subtype of the inferred
> type of X, which will also depend on what is known about W's return
> type and the type of MU's argument.
>
> By the way, the THE form is redundant in (THE FIXNUM 2). Something
> like (THE FIXNUM (+ I J)) would be more interesting.
Yeah, or perhaps:
AMX> (declaim (inline square))
; No value
AMX> (defun square (x)
(declare (fixnum x))
(the fixnum (* x x)))
SQUARE
AMX> (fun-info 'square)
(FUNCTION (FIXNUM) (VALUES (UNSIGNED-BYTE 29) &OPTIONAL))
AMX> (let* ((x 2)
(square-of-x (square x)))
(dbg-prin1 (lex-var-info 'x))
(dbg-prin1 (lex-var-info 'square-of-x))
(values x square-of-x))
(LEX-VAR-INFO 'X) => (INTEGER 2 2)
(LEX-VAR-INFO 'SQUARE-OF-X) => (INTEGER 4 4)
2
4
AMX>
..anyway, this is nice; it's great being able to dispatch at compile-
time even when I don't feel like adding (declare ..)'s "manually".
LEX-VAR-INFO is similar to the LEX-TYPE-INFO I posted above:
(defmacro lex-info (name kind &optional env)
`(when-let* ((sb-c:*lexenv* ,(or env sb-c:*lexenv*))
(lex-info (sb-c:lexenv-find ,name ,kind)))
(sb-kernel:type-specifier (sb-c::leaf-type lex-info))))
(defmacro lex-var-info (name &optional (env nil env-supplied-p))
(if env-supplied-p
`(lex-info ,name vars ,env)
`(lex-info ,name vars)))
(defun fun-info (name)
(sb-kernel:type-specifier (sb-c::info :function :type name)))
(defmacro dbg-prin1 (form &optional (stream t))
`(format ,stream "~S => ~S~%" ',form ,form))
On Fri, 26 Jun 2009 06:11:39 -0700 (PDT), Lars Rune N�stdal <···········@gmail.com> said:
AMX> (defun square (x)
> (declare (fixnum x))
> (the fixnum (* x x)))
By the way, the two declarations here are inconsistent, even though
the programmer may know that this is benign. Older dialects only
had FIXNUM, but in Common Lisp you can do better, e.g.
(defun square (x)
;; something like this must be true for (* X X) to be a fixnum:
(declare (type (integer -9999 9999) x))
(* x x)) ;hoping the compiler will infer the return type
And again, examples where the initial values of local variables are
not compile-time constants (but still of known subranges) are more
interesting.
> ..anyway, this is nice; it's great being able to dispatch at compile-
> time even when I don't feel like adding (declare ..)'s "manually".
Yes, it is great to have automatic type inference. It's not only
highly desirable for type declarations to be optional, but also to
be largely unnecessary.
---Vassil.
--
Vassil Nikolov <········@pobox.com>
(1) M(Gauss);
(2) M(a) if M(b) and declared(b, M(a)),
where M(x) := "x is a mathematician".
On Jun 27, 5:26 am, Vassil Nikolov <········@pobox.com> wrote:
> On Fri, 26 Jun 2009 06:11:39 -0700 (PDT), Lars Rune Nøstdal <···········@gmail.com> said:
> AMX> (defun square (x)
>
> > (declare (fixnum x))
> > (the fixnum (* x x)))
>
> By the way, the two declarations here are inconsistent, even though
> the programmer may know that this is benign. Older dialects only
> had FIXNUM, but in Common Lisp you can do better, e.g.
>
> (defun square (x)
> ;; something like this must be true for (* X X) to be a fixnum:
> (declare (type (integer -9999 9999) x))
> (* x x)) ;hoping the compiler will infer the return type
Hum, yeah. Can try that and see what happens:
AMX> (defun square (x)
(declare ((integer -9999 9999) x))
(* x x))
SQUARE
AMX> (fun-info 'square)
(FUNCTION ((INTEGER -9999 9999)) (VALUES (MOD 99980002) &OPTIONAL))
AMX>
> And again, examples where the initial values of local variables are
> not compile-time constants (but still of known subranges) are more
> interesting.
Yeah, related to that, I think, (return value) types do not seem to
propagate unless SQUARE is inlined:
AMX> (progn
(declaim (inline square))
(defun square (x)
(declare ((integer -9999 9999) x))
(* x x))
(declaim (notinline square)))
AMX> (fun-info 'square)
(FUNCTION ((INTEGER -9999 9999)) (VALUES (MOD 99980002) &OPTIONAL))
AMX> (let ((x (square 2)))
(dbg-prin1 (lex-var-info 'x))
x)
(LEX-VAR-INFO 'X) => T
4
AMX> (locally (declare (inline square))
(let ((x (square 2)))
(dbg-prin1 (lex-var-info 'x))
x))
(LEX-VAR-INFO 'X) => (INTEGER 4 4)
4
I'm not sure if it's possible to do anything with that. ..and my main
goal was getting info about return value types wrt. MAKE-INSTANCE
calls anyway, so. :)
> > ..anyway, this is nice; it's great being able to dispatch at compile-
> > time even when I don't feel like adding (declare ..)'s "manually".
>
> Yes, it is great to have automatic type inference. It's not only
> highly desirable for type declarations to be optional, but also to
> be largely unnecessary.
>
> ---Vassil.
>
> --
> Vassil Nikolov <········@pobox.com>
>
> (1) M(Gauss);
> (2) M(a) if M(b) and declared(b, M(a)),
> where M(x) := "x is a mathematician".
On Sat, 27 Jun 2009 04:57:10 -0700 (PDT), Lars Rune N�stdal <···········@gmail.com> said:
> ...
> (FUNCTION ((INTEGER -9999 9999)) (VALUES (MOD 99980002) &OPTIONAL))
Of course, you can also (have your program to) check whether
(SUBTYPEP '(MOD 99980002) #| or whatever the actual type is |# 'FIXNUM)
whenever (SUBTYPEP <that type> 'INTEGER) is true.
---Vassil.
--
Vassil Nikolov <········@pobox.com>
(1) M(Gauss);
(2) M(a) if M(b) and declared(b, M(a)),
where M(x) := "x is a mathematician".
Vassil Nikolov <········@pobox.com> writes:
> On Fri, 26 Jun 2009 06:11:39 -0700 (PDT), Lars Rune N�stdal <···········@gmail.com> said:
> AMX> (defun square (x)
>> (declare (fixnum x))
>> (the fixnum (* x x)))
>
> By the way, the two declarations here are inconsistent, even though
> the programmer may know that this is benign. Older dialects only
> had FIXNUM, but in Common Lisp you can do better, e.g.
>
> (defun square (x)
> ;; something like this must be true for (* X X) to be a fixnum:
> (declare (type (integer -9999 9999) x))
> (* x x)) ;hoping the compiler will infer the return type
Depending on the value of 'like'. MOST-POSITIVE-FIXNUM may be as low as 32767,
so (ISQRT MOST-POSITIVE-FIXNUM) may be as low as 181.
(defun square (x)
(declare (type (integer #.(- (isqrt (- most-negative-fixnum)))
#.(isqrt most-positive-fixnum))))
(the fixnum (* x x)))
--
__Pascal Bourguignon__