[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.lisp

ambiguous type declarations

Jim Newton

12/21/2015 8:45:00 AM

I have a question about http://clhs.lisp.se/Body/...
In particular the sentence: A symbol cannot be both the name of a type and the name of a declaration.

What does that mean?

Does it mean the following is illegal?

(declass ignore () ())

(define F (x)
(declare (ignore x))
x)

The problem is that to declare the type of a variable using DECLARE, the TYPE symbol
is unfortunately optional. I may use either of the following forms.

(define F (x)
(declare (type bignum x))
...)

or

(define F (x)
(declare (bignum x))
...)

So how can a code walker figure out that it is a type declaration?
I'm guessing that I only need to have a special case for
dynamic-extent, ignore, optimize, ftype, inline, special, ignorable, notinline, type

However, each CL implementations might have additional declarations it supports?

What is the correct way to resolve this ambiguity?

6 Answers

Marco Antoniotti

12/21/2015 12:59:00 PM

0

On Monday, December 21, 2015 at 9:44:47 AM UTC+1, Jim Newton wrote:
> I have a question about http://clhs.lisp.se/Body/...
> In particular the sentence: A symbol cannot be both the name of a type and the name of a declaration.
>
> What does that mean?
>
> Does it mean the following is illegal?
>
> (declass ignore () ())
>
> (define F (x)
> (declare (ignore x))
> x)
>
> The problem is that to declare the type of a variable using DECLARE, the TYPE symbol
> is unfortunately optional. I may use either of the following forms.
>
> (define F (x)
> (declare (type bignum x))
> ...)
>
> or
>
> (define F (x)
> (declare (bignum x))
> ...)
>
> So how can a code walker figure out that it is a type declaration?
> I'm guessing that I only need to have a special case for
> dynamic-extent, ignore, optimize, ftype, inline, special, ignorable, notinline, type
>
> However, each CL implementations might have additional declarations it supports?
>
> What is the correct way to resolve this ambiguity?

You can give priority to the IGNORE declaration and warn if the code walker can figure out that DECLARE names also a class.

Having said so, in CLAST (clast.sourceforge.net) I did not care about this case and, the IGNORE declaration is "preferred".

Besides, in LW you get a continuable error if you try to define a class named IGNORE.

Cheers
--
MA

Pascal J. Bourguignon

12/21/2015 1:38:00 PM

0

Jim Newton <jimka.issy@gmail.com> writes:

> I have a question about http://clhs.lisp.se/Body/...
> In particular the sentence: A symbol cannot be both the name of a type and the name of a declaration.
>
> What does that mean?

The important sentence is the following one.

Defining a symbol as the name of a class, structure, condition, or
type, when the symbol has been declared as a declaration name, or
vice versa, signals an error.

> Does it mean the following is illegal?

Yes.

> (declass ignore () ())

This should signal an error.


> (define F (x)
> (declare (ignore x))
> x)
>
> The problem is that to declare the type of a variable using DECLARE, the TYPE symbol
> is unfortunately optional.

It doesn't matter, since you cannot name a class CL:IGNORE.


> So how can a code walker figure out that it is a type declaration?

A code walker has to parse (and execute) all the code, like an
interpreter or a compiler would do, to learn about types and other
things. Or, often, it can just make some assumptions (ie. expect the
program is conforming).




> I'm guessing that I only need to have a special case for
> dynamic-extent, ignore, optimize, ftype, inline, special, ignorable, notinline, type

No. You have to deal with any random name.

(proclaim (list 'declaration
(let ((names (string-list-text-file-contents "/usr/share/dict/words")))
(intern (string-upcase (elt names (random (length names))))))))

> However, each CL implementations might have additional declarations it supports?

Yes, but foremost: any user program or library may create additional
declarations. (And therefore must not overload those symbols with a
type or class declaration).


> What is the correct way to resolve this ambiguity?

Do not use the fucking same symbol!


If you insist on the symbol name, you can use different packages:

(defpackage "MY-PROGRAM.DECLARATIONS"
(:use)
(:export "IGNORE"))

(declaim (declaration my-program.declarations:ignore))

(defpackage "MY-PROGRAM.MY-CLASSES"
(:use "CL")
(:shadow "IGNORE")
(:export "IGNORE"))

(in-package "MY-PROGRAM.MY-CLASSES")

(defclass ignore () ())

(defmethod m ((ignore ignore))
(declare (my-program.declarations:ignore ignore)
(cl:ignore ignore))
42)



--
__Pascal Bourguignon__ http://www.informat...
â??The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.� -- Carl Bass CEO Autodesk

Jim Newton

12/21/2015 4:05:00 PM

0

Hi Pascal, thanks for the answers, but perhaps you missed my point.
I am not trying to define classes consistent with declarations.
I'm trying to write a function that detects declarations in code which I didn't write.

Actually my code expands to a destructuring-bind form, given a destructuring lambda list, and a body (among other things).

Think of it as follows, given a destructuring-bind form which may have
declarations starting in its 2nd argument. I want to build a mapping from variable name
to type specifier.

(destructuring-bind (a b c d) value
(declare (type x A))
(declare (ignore x) (inline z))
(declare (x y z))

...)


When I encounter (declare (type x A)) then I know this is a type definition,
When I encounter (declare (ignore x) (inline z)) I know it is not a type def.
But when I encounter (declare (x y z)) I don't know what it is.

> A code walker has to parse (and execute) all the code, like an
> interpreter or a compiler would do, to learn about types and other
> things. Or, often, it can just make some assumptions (ie. expect the
> program is conforming).
>

If I could assume that the code up to this point has already been compiled and executed,
and thus if (declare (x ..)) is a type declaration then X is already a defined type,
then I could test for that. After all, it would be an error for restructuring-bind anyway
if not yet defined. Right?


Pascal J. Bourguignon

12/21/2015 5:03:00 PM

0

Jim Newton <jimka.issy@gmail.com> writes:

> Hi Pascal, thanks for the answers, but perhaps you missed my point.
> I am not trying to define classes consistent with declarations.
> I'm trying to write a function that detects declarations in code which
> I didn't write.

Did I mention that a code walker may needs a global view?
You should have code walked an expression like:

(declaim (declaration foo))

or:

(eval-when (:compile-toplevel :load-toplevel :execute)
(proclaim '(declaration foo)))

which is what the declaim form expands to, and you could have processed
it, noting that FOO is a declaration.

In the case of classes, you can find if a symbol names a class with:

(find-class 'foo nil) ; errorp bound to nil to get a predicate result.

However there's no conforming way to determine if a symbol denotes a
type. You could have expected that (subtypep 'foo 't) would tell, but
actually, if foo is not a type (eg. if it's a declaration), then it's
not conforming to call (subtypep 'foo 't) since you must pass only type
specifiers there.

Notably, sbcl assumes that all symbols denote types:

[pjb@kuiper localhost:10.0 ~]$ sbcl --no-userinit
This is SBCL 1.2.4.debian, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbc....

SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses. See the CREDITS and COPYING files in the
distribution for more information.
* (declaim (declaration foo))

* (typep 42 'foo)

debugger invoked on a SIMPLE-ERROR in thread
#<THREAD "main thread" RUNNING {10039CE633}>:
unknown type specifier: FOO

Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.

restarts (invokable by number or by possibly-abbreviated name):
0: [ABORT] Exit debugger, returning to top level.

(SB-KERNEL::%%TYPEP 42 #<SB-KERNEL:UNKNOWN-TYPE FOO> T)
0] 0

* (typep 42 'bar)

debugger invoked on a SIMPLE-ERROR in thread
#<THREAD "main thread" RUNNING {10039CE633}>:
unknown type specifier: BAR

Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.

restarts (invokable by number or by possibly-abbreviated name):
0: [ABORT] Exit debugger, returning to top level.

(SB-KERNEL::%%TYPEP 42 #<SB-KERNEL:UNKNOWN-TYPE BAR> T)
0] 0

* (subtypep 'foo 't)

T
T
* (subtypep 'bar 't)

T
T
*

Notably, notice how sbcl is sure that foo is a type, when it has been
declared as a declaration, and therefore can definitely not be a type!


Once again, the winner is clisp, the only implementation to correctly
signal an error in that case, with an accessit for ecl which returns an
honest answer:

[pjb@kuiper localhost:10.0 ~]$ clall -r '(declaim (declaration foo))' '(subtypep (quote foo) t)'

Clozure Common Lisp --> NIL
Clozure Common Lisp --> T, T

CLISP --> NIL
CLISP SUBTYPEP: invalid type specification FOO

CMU Common Lisp --> NIL
CMU Common Lisp --> T, T

ECL --> NIL
ECL --> NIL, NIL

SBCL --> No value.
SBCL --> T, T


So either you will have to depend on implementation dependant features
to detect if a symbol has been declared as a type or a declaration, or
you have to code walk globally and interpret the deftype and declaim
declaration forms yourself.

Or, you can just assume.

After all, few programs define their own declarations; apart from the
standard declarations, you can assume that it's a type.


> Actually my code expands to a destructuring-bind form, given a
> destructuring lambda list, and a body (among other things).
>
> Think of it as follows, given a destructuring-bind form which may have
> declarations starting in its 2nd argument. I want to build a mapping from variable name
> to type specifier.
>
> (destructuring-bind (a b c d) value
> (declare (type x A))
> (declare (ignore x) (inline z))
> (declare (x y z))
>
> ...)
>
>
> When I encounter (declare (type x A)) then I know this is a type definition,
> When I encounter (declare (ignore x) (inline z)) I know it is not a type def.
> But when I encounter (declare (x y z)) I don't know what it is.

Yep.

You can (find-class 'x nil), but in the negative, you need to have seen
a deftype or a declaim declaration for x.


>> A code walker has to parse (and execute) all the code, like an
>> interpreter or a compiler would do, to learn about types and other
>> things. Or, often, it can just make some assumptions (ie. expect the
>> program is conforming).
>>
>
> If I could assume that the code up to this point has already been compiled and executed,
> and thus if (declare (x ..)) is a type declaration then X is already a defined type,
> then I could test for that. After all, it would be an error for restructuring-bind anyway
> if not yet defined. Right?

Yes. However,

http://www.lispworks.com/documentation/HyperSpec/Body...

In general, an implementation is free to ignore declaration
specifiers except for the declaration, notinline, safety, and
special declaration specifiers.

and in the rest of the text (cf. eg. clhs declaration), only warnings
are mentionned about unknown declarations.



So, you could just ignore the declaration too.

--
__Pascal Bourguignon__ http://www.informat...
â??The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.� -- Carl Bass CEO Autodesk

William James

12/21/2015 5:06:00 PM

0

Pascal J. Bourguignon wrote:

> Jim Newton writes:
>
> > I have a question about http://clhs.lisp.se/Body/...
> > In particular the sentence: A
> > symbol cannot be both the name
> > of a type and the name of a
> > declaration.
> >
> > What does that mean?
>
> The important sentence is the following one.
>
> Defining a symbol as the name of a class, structure, condition, or
> type, when the symbol has been declared as a declaration name, or
> vice versa, signals an error.
>
> > Does it mean the following is illegal?
>
> Yes.
>
> > (declass ignore () ())
>
> This should signal an error.
>
>
> > (define F (x)
> > (declare (ignore x))
> > x)
> >
> > The problem is that to declare the type
> > of a variable using DECLARE, the TYPE
> > symbol is unfortunately optional.
>
> It doesn't matter, since you cannot name a class CL:IGNORE.
>
>
> > So how can a code walker figure out that it is a type declaration?
>
> A code walker has to parse (and execute) all the code, like an
> interpreter or a compiler would do, to learn about types and other
> things. Or, often, it can just make some assumptions (ie. expect the
> program is conforming).
>
>
>
>
> > I'm guessing that I only need to have a special case for
> > dynamic-extent, ignore, optimize, ftype, inline, special,
> > ignorable, notinline, type
>
> No. You have to deal with any random name.
>
> (proclaim (list 'declaration
> (let ((names (string-list-text-file-contents "/usr/share/dict/words")))
> (intern (string-upcase (elt names (random (length names))))))))
>
> > However, each CL implementations might
> > have additional declarations it
> > supports?
>
> Yes, but foremost: any user program or library may create additional
> declarations. (And therefore must not overload those symbols with a
> type or class declaration).
>
>
> > What is the correct way to resolve this ambiguity?
>
> Do not use the fucking same symbol!

MatzLisp (Ruby):

"What is the correct way to resolve this ambiguity?
Do not use the fucking same symbol!".
upcase.split("").values_at(68,84,65,6,45,68,69,6).join
===>
"CL SUCKS"

--
I would hesitate to describe America as a nation at all in 1997, because it is
something very different: a polyethnic federation administered by a single
ruling class.... [T]he accumulated rot in America has now reached a point
where the pillars of society itself are failing. --- Ambrose Evans-Pritchard

William James

4/23/2016 6:20:00 AM

0

WJ wrote:

> Pascal J. Bourguignon wrote:
>
> > Jim Newton writes:
> >
> > > I have a question about http://clhs.lisp.se/Body/...
> > > In particular the sentence: A
> > > symbol cannot be both the name
> > > of a type and the name of a
> > > declaration.
> > >
> > > What does that mean?
> >
> > The important sentence is the following one.
> >
> > Defining a symbol as the name of a class, structure, condition, or
> > type, when the symbol has been declared as a declaration name, or
> > vice versa, signals an error.
> >
> > > Does it mean the following is illegal?
> >
> > Yes.
> >
> > > (declass ignore () ())
> >
> > This should signal an error.
> >
> >
> > > (define F (x)
> > > (declare (ignore x))
> > > x)
> > >
> > > The problem is that to declare the type
> > > of a variable using DECLARE, the TYPE
> > > symbol is unfortunately optional.
> >
> > It doesn't matter, since you cannot name a class CL:IGNORE.
> >
> >
> > > So how can a code walker figure out that it is a type declaration?
> >
> > A code walker has to parse (and execute) all the code, like an
> > interpreter or a compiler would do, to learn about types and other
> > things. Or, often, it can just make some assumptions (ie. expect the
> > program is conforming).
> >
> >
> >
> >
> > > I'm guessing that I only need to have a special case for
> > > dynamic-extent, ignore, optimize, ftype, inline, special,
> > > ignorable, notinline, type
> >
> > No. You have to deal with any random name.
> >
> > (proclaim (list 'declaration
> > (let ((names (string-list-text-file-contents "/usr/share/dict/words")))
> > (intern (string-upcase (elt names (random (length names))))))))
> >
> > > However, each CL implementations might
> > > have additional declarations it
> > > supports?
> >
> > Yes, but foremost: any user program or library may create additional
> > declarations. (And therefore must not overload those symbols with a
> > type or class declaration).
> >
> >
> > > What is the correct way to resolve this ambiguity?
> >
> > Do not use the fucking same symbol!
>
> MatzLisp (Ruby):
>
> "What is the correct way to resolve this ambiguity?
> Do not use the fucking same symbol!".
> upcase.split("").values_at(68,84,65,6,45,68,69,6).join
> ===>
> "CL SUCKS"

OCaml:

#load "str.cma";;

"What is the correct way to resolve this ambiguity?
Do not use the fucking same symbol!"
|> Str.split (Str.regexp "W.*the \\|or.*so\\|ve.*\\|D.* u\\|e.*f\\|ing \\|am.*")
|> String.concat ""
|> String.uppercase
|> print_endline;;

CL
SUCKS

--
Here Levy is in effect saying: Jewish ethnocentrism is the opposite of
ethnocentrism. Hence, Jewish ethnocentrism is supremely good, whereas every
other ethnocentrism is supremely bad.
theoccidentalobserver.net/2016/02/bernard-henri-levy-on-wars-and-anti-nationalism-its-judaism-stupid