[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.lisp

defparameter defvar

SergioBG BG

7/15/2015 5:28:00 PM

Is not lisp somewhat redundant? with defparameter and defvar.
I understand that defvar is for variables that only can be started once

CL-USER> (defvar var 2)
VAR
CL-USER> var
2
CL-USER> (defvar var 3)
VAR
CL-USER> var
2
CL-USER> (setf var 3)
3
CL-USER> var
3

CL-USER> (defparameter var1 2)
VAR1
CL-USER> var1
2
CL-USER> (defparameter var1 3)
VAR1
CL-USER> var1
3

But why defvar and defparameter? if far as I understand are the same.
what I do not understand about them?
8 Answers

Matthew Carter

7/15/2015 5:36:00 PM

0

SergioBG BG <sergiobgar@gmail.com> writes:

> Is not lisp somewhat redundant? with defparameter and defvar.
> I understand that defvar is for variables that only can be started once
>
> CL-USER> (defvar var 2)
> VAR
> CL-USER> var
> 2
> CL-USER> (defvar var 3)
> VAR
> CL-USER> var
> 2
> CL-USER> (setf var 3)
> 3
> CL-USER> var
> 3
>
> CL-USER> (defparameter var1 2)
> VAR1
> CL-USER> var1
> 2
> CL-USER> (defparameter var1 3)
> VAR1
> CL-USER> var1
> 3
>
> But why defvar and defparameter? if far as I understand are the same.
> what I do not understand about them?

After you call defvar, a subsequent call to it will not update the
value, whlie defparameter will.

Then you have defconstant, which is immune to modification by a
subsequent call to defconstant, as well as setf.

So, the breakdown:

defvar: Can set once via defvar, change with setf

defparameter: Can set multiple times with defparameter or setf

defconstant: Can set once via defconstant, no change with setf




--
Matthew Carter (m@ahungry.com)
http://a...

SergioBG BG

7/15/2015 6:01:00 PM

0

El miércoles, 15 de julio de 2015, 19:36:27 (UTC+2), Matthew Carter escribió:
> SergioBG BG <sergiobgar@gmail.com> writes:
>
> > Is not lisp somewhat redundant? with defparameter and defvar.
> > I understand that defvar is for variables that only can be started once
> >
> > CL-USER> (defvar var 2)
> > VAR
> > CL-USER> var
> > 2
> > CL-USER> (defvar var 3)
> > VAR
> > CL-USER> var
> > 2
> > CL-USER> (setf var 3)
> > 3
> > CL-USER> var
> > 3
> >
> > CL-USER> (defparameter var1 2)
> > VAR1
> > CL-USER> var1
> > 2
> > CL-USER> (defparameter var1 3)
> > VAR1
> > CL-USER> var1
> > 3
> >
> > But why defvar and defparameter? if far as I understand are the same.
> > what I do not understand about them?
>
> After you call defvar, a subsequent call to it will not update the
> value, whlie defparameter will.
>
> Then you have defconstant, which is immune to modification by a
> subsequent call to defconstant, as well as setf.
>
> So, the breakdown:
>
> defvar: Can set once via defvar, change with setf
>
> defparameter: Can set multiple times with defparameter or setf
>
> defconstant: Can set once via defconstant, no change with setf
>
>
>
>
> --
> Matthew Carter (m@ahungry.com)
> http://a...

Then defvar and defparameter are almost the same,
both they define variables and are mutable.

taruss

7/15/2015 7:03:00 PM

0

On Wednesday, July 15, 2015 at 11:00:38 AM UTC-7, SergioBG BG wrote:
> El miércoles, 15 de julio de 2015, 19:36:27 (UTC+2), Matthew Carter escribió:
> > SergioBG BG <sergiobgar@gmail.com> writes:
> >
> > > Is not lisp somewhat redundant? with defparameter and defvar.
> > > I understand that defvar is for variables that only can be started once
> > >
> > > CL-USER> (defvar var 2)
> > > VAR
> > > CL-USER> var
> > > 2
> > > CL-USER> (defvar var 3)
> > > VAR
> > > CL-USER> var
> > > 2
> > > CL-USER> (setf var 3)
> > > 3
> > > CL-USER> var
> > > 3
> > >
> > > CL-USER> (defparameter var1 2)
> > > VAR1
> > > CL-USER> var1
> > > 2
> > > CL-USER> (defparameter var1 3)
> > > VAR1
> > > CL-USER> var1
> > > 3
> > >
> > > But why defvar and defparameter? if far as I understand are the same.
> > > what I do not understand about them?
> >
> > After you call defvar, a subsequent call to it will not update the
> > value, whlie defparameter will.
> >
> > Then you have defconstant, which is immune to modification by a
> > subsequent call to defconstant, as well as setf.
> >
> > So, the breakdown:
> >
> > defvar: Can set once via defvar, change with setf
> >
> > defparameter: Can set multiple times with defparameter or setf
> >
> > defconstant: Can set once via defconstant, no change with setf
--
> > Matthew Carter (m@ahungry.com)
> > http://a...
>
> Then defvar and defparameter are almost the same,
> both they define variables and are mutable.

The main reason for the difference is that it lets you control the effects of
reloading files. Since you can dynamically load files into running lisp
programs -- for example, to update the code.

But perhaps there are global variables in the program that contain some state
derived from the running program. The question is whether you want that state
to be preserved when you reload the file defining the variable or if you want
the value of that variable reset to its starting value. That is precisely the
difference that you get from using DEFVAR vs DEFPARAMETER.

Didier Verna

7/15/2015 7:04:00 PM

0

Matthew Carter <m@ahungry.com> wrote:

> So, the breakdown:
>
> defvar: Can set once via defvar, change with setf
> defparameter: Can set multiple times with defparameter or setf
> defconstant: Can set once via defconstant, no change with setf

Bottom line: user DEFVAR for defining user-level parameters, use
DEFPARAMETER for defining constants, don't use DEFCONSTANT; it's
useless.

--
My new Jazz CD entitled "Roots and Leaves" is out!
Check it out: http://didierverna.com/records/roots-and-...

Lisp, Jazz, Aïkido: http://www.didier...

james

7/28/2015 6:25:00 AM

0

On Thursday, July 16, 2015 at 3:04:25 AM UTC+8, Didier Verna wrote:
> Matthew Carter <m@ahungry.com> wrote:
>
> > So, the breakdown:
> >
> > defvar: Can set once via defvar, change with setf
> > defparameter: Can set multiple times with defparameter or setf
> > defconstant: Can set once via defconstant, no change with setf
>
> Bottom line: user DEFVAR for defining user-level parameters, use
> DEFPARAMETER for defining constants, don't use DEFCONSTANT; it's
> useless.
>
> --
> My new Jazz CD entitled "Roots and Leaves" is out!
> Check it out: http://didierverna.com/records/roots-and-...
>
> Lisp, Jazz, Aïkido: http://www.didier...

Could you explain why defconstant is useless?

Kaz Kylheku

7/28/2015 1:31:00 PM

0

On 2015-07-28, james <dinglei2008@gmail.com> wrote:
> On Thursday, July 16, 2015 at 3:04:25 AM UTC+8, Didier Verna wrote:
>> Matthew Carter <m@ahungry.com> wrote:
>>
>> > So, the breakdown:
>> >
>> > defvar: Can set once via defvar, change with setf
>> > defparameter: Can set multiple times with defparameter or setf
>> > defconstant: Can set once via defconstant, no change with setf
>>
>> Bottom line: user DEFVAR for defining user-level parameters, use
>> DEFPARAMETER for defining constants, don't use DEFCONSTANT; it's
>> useless.
>>
>> --
>> My new Jazz CD entitled "Roots and Leaves" is out!
>> Check it out: http://didierverna.com/records/roots-and-...
>>
>> Lisp, Jazz, Aïkido: http://www.didier...
>
> Could you explain why defconstant is useless?

defconstant isn't useless; it's for optimizing.

A variable defined with defconstant (yes ANSI Lisp calls these
"constant variables", oxymoronically) is declared to the compiler
as unchanging. In exchange, it can inline the value.

Pascal J. Bourguignon

7/28/2015 4:09:00 PM

0

james <dinglei2008@gmail.com> writes:

> On Thursday, July 16, 2015 at 3:04:25 AM UTC+8, Didier Verna wrote:
>> Matthew Carter <m@ahungry.com> wrote:
>>
>> > So, the breakdown:
>> >
>> > defvar: Can set once via defvar, change with setf
>> > defparameter: Can set multiple times with defparameter or setf
>> > defconstant: Can set once via defconstant, no change with setf
>>
>> Bottom line: user DEFVAR for defining user-level parameters, use
>> DEFPARAMETER for defining constants, don't use DEFCONSTANT; it's
>> useless.
>
> Could you explain why defconstant is useless?

It is obvious. Why do I have to state the obvious all the time?


It says to the compiler that the value of the constant can be inlined.

Some old processors had instructions containing immediate value. So the
processors didn't have to access the memory to have the immediate value,
because it was stored in the instruction code that was already loaded.

Unfortunately, those immediate values are in general small, since they
have to be stored inside a single instruction code! Usually you have
8-bit values, sometimes 16-bit. On CISC processors, immediate values
could even be a whole word (eg. 32-bit).

But on more modern processors, such as RISC, immediate values are even
more restricted, often there's no whole word immediate values, so to
load a register with a constant value you have to use several
instructions loading different parts of the registers.

So this is really not useful; it's easier to just store those literal
value in the memory, at a given address, and to load them by derefering
this address.


When this inlining is performed for defconstant, a COPY of the value is
made in each immediate instruction where it is used. Therefore if you
wanted to change the constant value, you would have to recompile all the
code where it is referenced.

On the other hand, when you keep the literal stored in memory (in a
"variable"), then you can update this memory without recompiling the
code that uses it.


Finally, other objects than fixnums and characters are bigger than what
can be stored in an immediate value, so they have to be stored in memory
anyways, just like variables.

Well, we could imagine a language allowing to define a small structure
that could be held in an immediate value. But since copies of the
structure would be made in each instruction where it's used, when you
mutate a slot of the structure in one place, you would have to recompile
all the code that use the structure since now that slot has a different
value that should be replicated in each immediate copies. (Or
alternatively, storing the slot would try to write to several places in
the code, which is quite inefficient, and impossible when the code is
stored in read-only memory, and you would need to maintain a list of
those places since you can add or remove code in a lisp program at
run-time).

This is the reason why defconstant says:

The consequences are undefined if there are any bindings of the
variable named by name at the time defconstant is executed or if the
value is not EQL to the value of initial-value.

Notice that defconstant doesn't say that the value is immutable. If
that was the case, just declaring a single defconstant could lock up
your whole image.

(defconstant true 'true)

If true was to be immutable then (symbol-package 'true) would have to
be, and therefore (package-use-list (symbol-package 'true)) and
therefore all the symbols of all the packages accessible from true and
all their values, etc.


So if you write:

(defconstant +p+ (make-point :x 1 :y 2)

You can still do:

(setf (point-x +p+) 0)

The only difference is that if the point has been copied into the code
as immediate value, now (setf (point-x +p+) 0) must modify all those
copies of the code.

Obviously, implementations won't generate immediate values for such a
big object, so there won't be any difference, in the code generated for
the references to the variable, between a constant variable and a global
variable. Therefore the "optimization" argument is not valid.


Also, how do you ensure that when you re-evaluate a (defconstant +p+ â?¦)
form, you give the EXACT SAME OBJECT as the point bound above?


The only valid defconstant form after a defconstant is:

(defconstant +p+ +p+)

unless the value is a character, a number or a symbol, because for these
types you can have two copies of the same character or two copies of the
same numbers that will be EQL, and those objects are IMMUTABLE. (A
symbol has mutable attributes, but its name and its identity are
immutable, so they're good enough for this).

(eql 3 3)
(eql #\a #\a)
(eql 'hi 'hi)

So it doesn't matter that copies are made, because you cannot mutate
them (and you cannot copy a symbol, you can only create another symbol).

On the other hand, you could try to redefine the constant binding:

(defconstant +pi+ 3)
(defun f (r) (* 2 +pi+ r)
(defconstant +pi+ 3.14)
(f 1)

But this is not conforming, because now F might be compiled with an
immediate value for +pi+ of 3, or it could refer to the current value
bound to +pi+ which is 3.14 now. So the result of (F 1) could be
different on different implementation, therefore this code is not
conforming by definition.

This is why:

1- defconstant binding other values than characters, numbers and symbols
(which are the only immutable values in lisp) is useless, because the
expected optimizations cannot be implemented for mutable values.

2- defconstant cannot change the binding, so when you are developping
interactively, this is not a good thing. This limits drastically the
applicability of constants. You cannot use them for buffer sizes,
because you will want to change them to adapt the performance on your
memory or time constants of your protocols. You cannot use them for
foreign C constants, because those constants change depending on the
target platform, so you will have to have different values when
running on a different system. You cannot use them for physical
constants since they are periodically redefined, and often are not
even constant, but just of a value that depends on other parameters
that you are not currently able to change. (for example, speed of
light was not know to its full precision so every few years it would
change depending on new measurements, UNTIL we decided to DEFINE the
meter in function of the speed of light, so now the value of the
speed of light in the vacuum is a constant, but actually:

1- speed of light varies depending on the medium,

2- the value of the speed of light itself would depend on the
units used, so if you change the units, you may have to change
the value.

3- and while we assume it is constant in this universe, we may
suddently want to simulate a different universe where the value
is different, hence defconstant totally inappropriated.


In conclusion, there are very few cases where defconstant can be useful,
and one is hard pressed finding one.

For example in numerical algorithms, you might have literal constants in
some expressions. But would you define a constant variable to hold
them, or would you keep them as literals? Probably the later.

For example, it's not because you have twice the value 42 in two
expressions that you should (defconstant +coef+ 42) and use
+fourty-two+. Perhaps the two 42 were coincidential, and if a change
occur in one expression, the new constant will have to be 24 in that
expressions but still 42 in the other. So there was no reason to link
both literals to the same +coef+ variables.


Notice that even PI, which is defined to be a constant in CL, poses some
problem in clisp, because it has long-floats of user-specified
precision, so when you change the precision of your long-float, you get
a new binding to PI expressed to the new precision. (This is a
non-conforming extension, it would have been preferable to keep a fixed
value for CL:PI and to provide a EXT:PI variable). But this is to
demonstrate that defconstant is really not that useful.


There is perhaps one usage, but you will see it's a bad usage. You could
use constant variables to name indices in a vector to implement some
kind of structures:

(defconstant +x+ 0)
(defconstant +y+ 1)

(let ((p1 (vector 0 0))
(p2 (vector 10 -3)))
(setf (aref p1 +x+) 1
(aref p1 +y+) 2)
(incf (aref p1 +x+) (aref p2 +x+))
(incf (aref p1 +y+) (aref p2 +y+)))

Here, it is good to use a constant variable, since this shows that the 0
in (aref p1 0) is the same as the 0 in (aref p2 0), and hopefully, you
won't find a reason why it would be better to store y before x in the
vector (notice that in MacOS, Quickdraw HAD a very GOOD reason to store
y before x in its POINT structures!!!).

But you will agree that it is actually very bad, and you should better
write:

(defstruct (point (:type vector)) x y)
(let ((p1 (make-point :x 0 :y 0))
(p2 (make-point :x 10 :y -3)))
(setf (point-x p1) 1
(point-y p1) 2)
(incf (point-x p1) (point-x p2))
(incf (point-y p1) (point-y p2)))

and a compiler worth its bit will actually generate exactly the same
code from both sources! And compilers a little worse, will actually
generate more efficient code for structure accessors than for vectors
slots, so the gain in optimizing *x* vs. +x+ is ludicruous, when you can
get an even better optimization with point-x!


--
__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

Kaz Kylheku

7/28/2015 5:45:00 PM

0

On 2015-07-28, Pascal J. Bourguignon <pjb@informatimago.com> wrote:
> But on more modern processors, such as RISC, immediate values are even
> more restricted, often there's no whole word immediate values, so to
> load a register with a constant value you have to use several
> instructions loading different parts of the registers.

That depends on the value! Loading a small integer value can be more efficient.
Anyway, that isn't the point. The point is that these instructions don't need
any context to retrieve the value, other than the instruction pointer.
A dynamic variable has context. Its value depends on which scope you are
in, in what thread.

> So this is really not useful; it's easier to just store those literal
> value in the memory, at a given address, and to load them by derefering
> this address.

If it is understood that this memory will not change, then it is effectively
a constant, and defconstant could use this mechanism.

Do not confuse "literal constant" with "machine language immediate operand".