Discussion:
Where to prefer SETQ to SETF?
(too old to reply)
Udyant Wig
2020-02-17 16:19:46 UTC
Permalink
In what situations would SETQ be preferable to SETF?

Is there anything SETQ does that SETF does not?

Udyant Wig
--
We make our discoveries through our mistakes: we watch one another's
success: and where there is freedom to experiment there is hope to
improve.
-- Arthur Quiller-Couch
Kaz Kylheku
2020-02-18 00:54:55 UTC
Permalink
Post by Udyant Wig
In what situations would SETQ be preferable to SETF?
When there is an expectation that your code will be ported to a dialect
of Lisp that has only setq.

Or: the codebase heavily uses setq, and you'd like to make a change
without also introducing an off-topic stylistic change.
Post by Udyant Wig
Is there anything SETQ does that SETF does not?
Yes; (setq form val) is invalid if form isn't a symbol, and
implementations tend to diagnose that.

So that diagnostic is something that setq "does" that setf doesn't.
Stefan Monnier
2020-02-18 17:05:34 UTC
Permalink
Post by Udyant Wig
In what situations would SETQ be preferable to SETF?
Whenever your keyboard lacks an "F"?


Stefan
Paul Rubin
2020-02-22 10:37:59 UTC
Permalink
Post by Stefan Monnier
Post by Udyant Wig
In what situations would SETQ be preferable to SETF?
Whenever your keyboard lacks an "F"?
Pay respects to that keyboard by pressing... oh you can't.
Kaz Kylheku
2020-02-25 07:35:20 UTC
Permalink
Post by Stefan Monnier
Post by Udyant Wig
In what situations would SETQ be preferable to SETF?
Whenever your keyboard lacks an "F"?
That's quite a predicament; you need both to find the "FAQ".
His Kennyness
2020-03-09 06:50:44 UTC
Permalink
Post by Stefan Monnier
Post by Udyant Wig
In what situations would SETQ be preferable to SETF?
Whenever your keyboard lacks an "F"?
Stefan
Nonsense. Prefer SETQ when you are older than 60. Hth.

-hk
Stefan Monnier
2020-03-09 14:50:05 UTC
Permalink
Post by His Kennyness
Post by Stefan Monnier
Post by Udyant Wig
In what situations would SETQ be preferable to SETF?
Whenever your keyboard lacks an "F"?
Nonsense. Prefer SETQ when you are older than 60. Hth.
Users below 60 have a keyboard that doesn't lack the "F" key,
so you're just restating what I said,


S...

t***@google.com
2020-02-18 17:47:06 UTC
Permalink
Post by Udyant Wig
In what situations would SETQ be preferable to SETF?
Is there anything SETQ does that SETF does not?
A quick history of the forms.

In the beginning there was SET, which was an ordinary function. It evaluated
both of its arguments and assigned the 2nd value to the symbol produced by the
first value.
So, most of the time SET would be called like (SET 'var 30), with the first
value quoted.

This was considered annoyingly verbose, especially before the ' character was
introduced and you would have to write (SET (QUOTE VAR) 30).
So a special form (or possibly a macro) was introduced that quoted the first
argument, and thus SETQ was born.

Much later, additional data structures like arrays, structures, classes, etc.
were added to the language. But both SET and SETQ only operated on symbols.
So a more general macro, SETF, was added to handle the additional data
structures.
And having learned a lesson from this, SETF was made extensible, so that it
could be used to handle assigning values to anything.

So, SETQ is a bit of vestige of this development, retained mostly for backward
compatibility, and to keep the ancient lisp wizards happy. I would expect that
if the language were designed today, SETQ would not exist and SETF would be
used in its place. SET still has a very minor application for situations where
the variable that needs setting isn't fixed at program creation time:
(set (if (is-monday-p (today)) 'foo 'bar) 100)
But SET is limited to working only on the global value (value cell) of the
symbol. It doesn't affect non-special variables.(See Hyperspec for examples)
Stefan Monnier
2020-02-18 19:54:13 UTC
Permalink
Post by t***@google.com
(set (if (is-monday-p (today)) 'foo 'bar) 100)
Of course, you could write this as:

(setf (if (is-monday-p (today)) foo bar) 100)

[ Tho, IIRC, CL doesn't define `if` as a place by default, so you'd
first have to define that with define-setf-expander. ]
Post by t***@google.com
But SET is limited to working only on the global value (value cell) of the
symbol. It doesn't affect non-special variables.(See Hyperspec for examples)
The `setf` version above can be used on local, lexical vars, OTOH, and
can even use mixes like

(setf (if (is-monday-p (today)) foo (car bar)) 100)


-- Stefan
Madhu
2020-02-19 02:50:16 UTC
Permalink
* Stefan Monnier <jwvy2szfzdl.fsf-monnier+***@gnu.org> :
Wrote on Tue, 18 Feb 2020 14:54:13 -0500:

[all attributions maliciously snipped by Stefan]
Post by Stefan Monnier
Post by t***@google.com
(set (if (is-monday-p (today)) 'foo 'bar) 100)
(setf (if (is-monday-p (today)) foo bar) 100)
[ Tho, IIRC, CL doesn't define `if` as a place by default, so you'd
first have to define that with define-setf-expander. ]
Post by t***@google.com
But SET is limited to working only on the global value (value cell)
of the symbol. It doesn't affect non-special variables.(See Hyperspec
for examples)
The `setf` version above can be used on local, lexical vars, OTOH, and
can even use mixes like
(setf (if (is-monday-p (today)) foo (car bar)) 100)
DEFINE-SETF-EXPANDER is a sane and wellthought out (almost)
comprehensive mechanism which is consistent with the rest of common lisp
- it adheres to the code-data philosphy of common lisp - and so and
produces common lisp code which is debuggable and plays well with the
rest of common lisp.

This is in stark contrast Contrast this to your ill-designed GV
mechanism which uses opaque closures in its implementation and produces
an undebuggable mess - which cannot be directly implemented on top of
existing elisp all for the sake of supporting write-only code (with
opaque closures which are NOT CODE) which depends on your particular
implementation.
Stefan Monnier
2020-02-24 16:57:46 UTC
Permalink
[all attributions helpfully snipped by yours truly]
Post by Madhu
Post by Stefan Monnier
The `setf` version above can be used on local, lexical vars, OTOH, and
can even use mixes like
(setf (if (is-monday-p (today)) foo (car bar)) 100)
DEFINE-SETF-EXPANDER is a sane and wellthought out (almost)
comprehensive mechanism which is consistent with the rest of common lisp
I largely agree. But I'm not sure what this has to do with using `if`
as a generalized variable.
Post by Madhu
This is in stark contrast Contrast this to your ill-designed GV
Oh, you wanted to take the opportunity to advertize my replacement.
Thanks,


Stefan
Kaz Kylheku
2020-02-25 07:46:56 UTC
Permalink
Post by Stefan Monnier
Post by t***@google.com
(set (if (is-monday-p (today)) 'foo 'bar) 100)
(setf (if (is-monday-p (today)) foo bar) 100)
[ Tho, IIRC, CL doesn't define `if` as a place by default, so you'd
first have to define that with define-setf-expander. ]
The mighty CLISP does, out of the box, however.

[1]> (defvar a)
A
[2]> (defvar b)
B
[3]> (setf (if (evenp 3) a b) t)
T
[4]> a

*** - SYSTEM::READ-EVAL-PRINT: variable A has no value
The following restarts are available:
USE-VALUE :R1 Input a value to be used instead of A.
STORE-VALUE :R2 Input a new value for A.
ABORT :R3 Abort main loop
Break 1 [5]> :a
[6]> b
T
Stefan Monnier
2020-02-25 15:02:18 UTC
Permalink
Post by Kaz Kylheku
Post by Stefan Monnier
(setf (if (is-monday-p (today)) foo bar) 100)
[ Tho, IIRC, CL doesn't define `if` as a place by default, so you'd
first have to define that with define-setf-expander. ]
The mighty CLISP does, out of the box, however.
Great!

Interestingly, the expansion looks like:

[1]> (macroexpand '(push V (if E X1 X2)))
(LET* ((#:G2952 V))
(LET* ((#:COND-2949 E))
(LET* ((#:G2953 (IF #:COND-2949 X1 X2)))
(LET* ((#:NEW-2950 (CONS #:G2952 #:G2953)))
(IF #:COND-2949 (SETQ X1 #:NEW-2950) (SETQ X2 #:NEW-2950)))))) ;
T
[2]>

So the `if` test is performed twice rather than once (semantically, this
is fine, but in terms of performance it's a tiny bit disappointing,
unless the compiler later manages to optimize the second test away; tho
admittedly modern processors's branch predictors should very quickly
learn the correlation between the two tests so the second will (almost)
always be predicted perfectly).


Stefan
Kaz Kylheku
2020-02-26 07:43:43 UTC
Permalink
Post by Stefan Monnier
Post by Kaz Kylheku
Post by Stefan Monnier
(setf (if (is-monday-p (today)) foo bar) 100)
[ Tho, IIRC, CL doesn't define `if` as a place by default, so you'd
first have to define that with define-setf-expander. ]
The mighty CLISP does, out of the box, however.
Great!
[1]> (macroexpand '(push V (if E X1 X2)))
(LET* ((#:G2952 V))
(LET* ((#:COND-2949 E))
(LET* ((#:G2953 (IF #:COND-2949 X1 X2)))
(LET* ((#:NEW-2950 (CONS #:G2952 #:G2953)))
(IF #:COND-2949 (SETQ X1 #:NEW-2950) (SETQ X2 #:NEW-2950)))))) ;
T
[2]>
So the `if` test is performed twice rather than once (semantically, this
is fine, but in terms of performance it's a tiny bit disappointing,
I am not able to convince myself that it's easily possible for the
expander to use a one-size-fits-all template which evaluates the
condition once; i.e. to optimize this at a high level.

Obviously, that particular instance, we know it's possible because
the source construct could be rewritten without using the IF place,
by duplicating the push:

(if E (push V X1) (push V X2))

The above rearrangement tantalizingly hints at the possibility of making
that the expansion strategy: somehow generalizing this duplication of
the surrounding place operation.

(setf (if E X1 X2) V) -> (if E (setf X1 V) (setf X2 V))

How would that work for, say, ROTATEF:

(rotatef (if E X1 X2)
(if F Y1 y2)) -> (if E (if F (rotatef X1 Y1)
(rotatef X1 Y2))
(if F (rotatef X2 Y1)
(rotatef X2 Y2)))

The problem with this is that the actions do not appear to be synthetic
(by which I mean that a construct synthesizes some expansion of itself
based only on the pieces that it contains, without input from the
surroundning context). This concept does not appear to be implementable
by setf expanders or any other mechanism I know.

The crux is that places provide the access to the previous value and
store of the new value as orthogonal operations, whereas the place
operators provide a canned sequence of actions, like in the case of
push: access the place, cons a new item onto the value, store into the
place.

PUSH will necessarily emit code that just accesses the place once and
stores into it once according to a fixed template.

The setf expansion coming from the place cannot influence PUSH into
generating code that evalutes a condition and then branches into
multiple code paths, with independent loads and stores.

But let us think about this on a the following meta-level.

Suppose we introduce the notion of "conditional places". Some places can
denote multiple places based on a run-time condition. Those places can
*declare* that they do so by returning something in their setf expansion
(a sixth value or something) or in some other manner. They each indicate
the expressions (or perhaps temporary symbols) which contain the
variable(s) on which they are conditional.

Next, suppose we introduce the concept of an outer-most place operation:
a place mutating expression that is not embedded in any other
place-mutating expression. For instance:

(push (setf x 3) y)
^ ^
' `- not outer-most, but contained
'
`- outer-most

the processing of the conditional places is deferred to the outer-most
place operation. The expander iterates over all of the possible
combinations of the conditional variables, and generates copies of
the code in which the conditional places are substituted accordingly.

Suppose we allow for this: the user must understand that the conditional
variables are evaluated out-of-order.

Example:

(push A (B Q X Y Z))

Place B indicates that it is conditional. It has one conditional
variable Q. Further, the place indicates that Q takes on three values,
the keywords :foo, :bar and :xyzzy. (Any other value is in error.)
These values correspond to the places X, Y and Z.

First, the push macro generates the usual code like

(let ((#:g0 A)
(#:g1 <access B>))
(<store B> (cons #:g0 #:g1)))

Now, that being the outer-most place mutating form, the master-expander
kicks in to do a post processing pass. The code contains one conditional
place B, with a variable Q that takes on three values. This is
generated:

(let ((#:g2 Q)) ;; programmer accepts this documented out-of-order eval
(ecase #:g2
(:foo (let ((#:g0 A)
(#:g1 <access X>))
(<store X> (cons #:g0 #:g1))))
(:bar (let ((#:g0 A)
(#:g1 <access Y>))
(<store Y> (cons #:g0 #:g1))))
(:xyzzy (let ((#:g0 A)
(#:g1 <access Z>))
(<store Z> (cons #:g0 #:g1))))))

The <access B> and <store B> parts in the initial expansion are not fully
expanded until the final step. They pass through the bowels of PUSH
undigested, so to speak, and then they are traversed and substituted
to instantiate the different concrete places that they denote in the
different branches of the code. (This has to be iterated, since a
conditional place's constituent places can themselves be conditional.)

Here, since X is not a conditional place but an ordinary symbol,
<access X> converts to X, and (<store X> ...) converts to (setq X ...).

I don't see any nice way of doing this that doesn't produce a lot
of duplication for a compiler to have to optimize away. For instance,
in the above example, the binding of #:g0 A could be hoisted outside of
the ecase. We're not evaluating the conditions more than once, but we
have code bloat which is bad for caching.
Stefan Monnier
2020-02-26 17:35:55 UTC
Permalink
Post by Kaz Kylheku
Post by Stefan Monnier
[1]> (macroexpand '(push V (if E X1 X2)))
(LET* ((#:G2952 V))
(LET* ((#:COND-2949 E))
(LET* ((#:G2953 (IF #:COND-2949 X1 X2)))
(LET* ((#:NEW-2950 (CONS #:G2952 #:G2953)))
(IF #:COND-2949 (SETQ X1 #:NEW-2950) (SETQ X2 #:NEW-2950)))))) ;
T
[2]>
So the `if` test is performed twice rather than once (semantically, this
is fine, but in terms of performance it's a tiny bit disappointing,
I am not able to convince myself that it's easily possible for the
expander to use a one-size-fits-all template which evaluates the
condition once; i.e. to optimize this at a high level.
Indeed, there are tradeoffs. We could also expand to something like

(let ((get-set (if COND
(cons (lambda () X1) (lambda (V) (setq X1 V)))
(cons (lambda () X2) (lambda (V) (setq X2 V))))))
(funcall (cdr get-set) (cons (funcall (car get-set)))))

and then hope that the compiler does a good job with it, which requires
if-tail-splitting followed by some kind of constant folding and inlining.

The current Elisp code emits this kind of code (which the byte-compiler
then fails completely to optimize properly, so it's very inefficient)
but it also checks the size of the body of the `let` and if it's small
enough to be duplicated (as is the case for `push`), it emits something
more like:

(if COND (push V X1) (push V X2))
Post by Kaz Kylheku
Obviously, that particular instance, we know it's possible because
the source construct could be rewritten without using the IF place,
(if E (push V X1) (push V X2))
The above rearrangement tantalizingly hints at the possibility of making
that the expansion strategy: somehow generalizing this duplication of
the surrounding place operation.
(setf (if E X1 X2) V) -> (if E (setf X1 V) (setf X2 V))
(rotatef (if E X1 X2)
(if F Y1 y2))
Here Elisp's `if` place expander considers the body of the first `if` to
be too large for the rewrite, whereas the second is small enough:

ELISP> (macroexpand '(cl-rotatef (if E X1 X2) (if F Y1 y2)))
(let* ((gv
(if E (cons (lambda nil X1) (lambda (v0) (setq X1 v0)))
(cons (lambda nil X2) (lambda (v0) (setq X2 v0)))))
(--cl-rotatef-- (funcall (car gv))))
(progn
(funcall (cdr gv)
(if F (prog1 Y1 (setq Y1 --cl-rotatef--))
(prog1 y2 (setq y2 --cl-rotatef--))))
nil))
ELISP>

This will not run fast, given Elisp's naive byte-compiler and fairly
inefficient construction of closures.


Stefan
t***@google.com
2020-02-26 22:15:37 UTC
Permalink
Post by Kaz Kylheku
Post by Stefan Monnier
Post by Kaz Kylheku
Post by Stefan Monnier
(setf (if (is-monday-p (today)) foo bar) 100)
[ Tho, IIRC, CL doesn't define `if` as a place by default, so you'd
first have to define that with define-setf-expander. ]
The mighty CLISP does, out of the box, however.
Great!
[1]> (macroexpand '(push V (if E X1 X2)))
(LET* ((#:G2952 V))
(LET* ((#:COND-2949 E))
^^^^^^^^^^^^^
If condition evaluated once and stored.
Post by Kaz Kylheku
Post by Stefan Monnier
(LET* ((#:G2953 (IF #:COND-2949 X1 X2)))
^^^^^^^^^^^^^^^^^^^^
One of X1 or X2 evaluated and stored.
Post by Kaz Kylheku
Post by Stefan Monnier
(LET* ((#:NEW-2950 (CONS #:G2952 #:G2953)))
(IF #:COND-2949 (SETQ X1 #:NEW-2950) (SETQ X2 #:NEW-2950)))))) ;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Neither X1 nor X2 is evaluated here.
Post by Kaz Kylheku
Post by Stefan Monnier
T
[2]>
So the `if` test is performed twice rather than once (semantically, this
is fine, but in terms of performance it's a tiny bit disappointing,
I am not able to convince myself that it's easily possible for the
expander to use a one-size-fits-all template which evaluates the
condition once; i.e. to optimize this at a high level.
It's also important to differentiate between the IF test being performed
twice and the condition being evaluated twice.

In the code for PUSH as given above, it seems like there isn't really a problem
with multiple evaluation. But I suppose there could be an issue with some of
the arguments to the forms inside the IF being evaluated more than once. But
I'm not at all sure if that would only happen when a non-conditional SETF
expansion is encountered.
Stefan Monnier
2020-02-26 23:25:09 UTC
Permalink
Post by t***@google.com
It's also important to differentiate between the IF test being performed
twice and the condition being evaluated twice.
Indeed! The expansion is perfectly correct: the multiple evaluations
of the `if` will all behave identically and it's just an implementation
detail which will only affect performance and code size.
The issue is not one of semantics but of operational behavior.


Stefan
Madhu
2020-02-19 02:43:21 UTC
Permalink
This post might be inappropriate. Click to display it.
Barry Margolin
2020-02-19 16:45:10 UTC
Permalink
Post by Madhu
SETQ is for MODIFYING VARIABLES. The `variable' is a supremely
important concept in common lisp. There is important information
conveyed when you use SETQ to indicate you are modifying a variable and
not just any generalized place. There is no benefit in dropping this
distinction except as an appeal to retard programmers
Is this really so true? Are variables more important in CL than any
other language? Yet few languages have different syntax for assigning to
variables than any other location. E.g. in C-style languages you have

var = value;
array[index] = value;
struct.member = value;
*ptr = value;

They all just use the general structure

<destination> = <source>;

I agree with the previous poster -- SETQ and SET are legaciies of
earlier Lisps where SETF was an add-on.

And the same goes for RPLACA/RPLACD.

That said, since I've been programming Lisp for almost 40 years, it's an
ingrained habit to use SETQ for variables.
--
Barry Margolin, ***@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
Kaz Kylheku
2020-02-25 07:54:51 UTC
Permalink
Post by Barry Margolin
Post by Madhu
SETQ is for MODIFYING VARIABLES. The `variable' is a supremely
important concept in common lisp. There is important information
conveyed when you use SETQ to indicate you are modifying a variable and
not just any generalized place. There is no benefit in dropping this
distinction except as an appeal to retard programmers
Is this really so true?
SETQ will assign to arbitrary forms through a symbol macro:

(symbol-macrolet ((x (car c)))
(setq x 42))

SETQ is constrained to assigning to syntax that is a symbol
before expansion. That's not a very useful category.
Barry Margolin
2020-02-25 16:46:18 UTC
Permalink
Post by Kaz Kylheku
Post by Barry Margolin
Post by Madhu
SETQ is for MODIFYING VARIABLES. The `variable' is a supremely
important concept in common lisp. There is important information
conveyed when you use SETQ to indicate you are modifying a variable and
not just any generalized place. There is no benefit in dropping this
distinction except as an appeal to retard programmers
Is this really so true?
(symbol-macrolet ((x (car c)))
(setq x 42))
SETQ is constrained to assigning to syntax that is a symbol
before expansion. That's not a very useful category.
As I posted earlier, the whole idea of symbol macros is that their
macroness is hidden from view and you can use them as if they're
ordinary variables.
--
Barry Margolin, ***@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
Jeff Barnett
2020-02-19 21:14:11 UTC
Permalink
Post by Madhu
Post by t***@google.com
So, SETQ is a bit of vestige of this development, retained mostly for
backward compatibility, and to keep the ancient lisp wizards happy. I
would expect that if the language were designed today, SETQ would not
exist and SETF would be used in its place. SET still has a very minor
application for situations where the variable that needs setting isn't
fixed at program creation time: (set (if (is-monday-p (today)) 'foo
'bar) 100) But SET is limited to working only on the global value
(value cell) of the symbol. It doesn't affect non-special
variables.(See Hyperspec for examples)
This is an important distinction in Common Lisp, which outsiders who
have come to common lisp and now dominate the common lisp scene haven't
a clue about.
Common lisp has ENDP and NULL both do the same thing, but ENDP is
supposed to signal an error when it encounters something which is not a
proper list.
SETQ is for MODIFYING VARIABLES. The `variable' is a supremely
important concept in common lisp. There is important information
conveyed when you use SETQ to indicate you are modifying a variable and
not just any generalized place. There is no benefit in dropping this
distinction except as an appeal to retard programmers
The people who retardedly advocate for doing away with SETQ are the ones
who would also root to destroy the english language by doing away with
the distinction of using the articles `AN' and `A' in separate
situations. In other words, hitler.
It's been awhile but I think that SETQ can take a symbol macro name as
its first argument, expand it, and deal with that expansion by turning
the SET into an appropriate SETF. The point is that a symbol macro name
isn't a variable.
--
Jeff Barnett
Madhu
2020-02-20 02:19:23 UTC
Permalink
Post by Jeff Barnett
It's been awhile but I think that SETQ can take a symbol macro name as
its first argument, expand it, and deal with that expansion by turning
the SET into an appropriate SETF. The point is that a symbol macro
name isn't a variable.
You are right of course. But I don't believe it detracts from my point
and the motivation for keeping SETQ remains - it is used used to signal
an assignment of a value to a variable. Here is the text for SETQ from
the spec:

DESCRIPTION:

Assigns values to variables.

(setq var1 form1 var2 form2 ...) is the simple variable
assignment statement of Lisp. First form1 is evaluated and the
result is stored in the variable var1, then form2 is evaluated
and the result stored in var2, and so forth. setq may be used
for assignment of both lexical and dynamic variables.

If any var refers to a binding made by symbol-macrolet, then
that var is treated as if setf (not setq) had been used.

The last sentence is behaviour which was tacked on to to SETQ on top of
SETF - specifically to facilitate forms like

(with-slots (slot1) obj
(setq slot1 val))

instead of writing (setf (slot-value obj 'slot1) val)

The point is that within the WITH-SLOTS form one wishes to treat the
symbol SLOT1 as if it were a lexical VARIABLE. The fact is that
WITH-SLOTS expands SLOT1 to a symbol macro which defines a place, but
the point is to abstract that away by treating it as if it were a
VARIABLE.
Barry Margolin
2020-02-21 18:08:36 UTC
Permalink
Post by Jeff Barnett
Post by Madhu
Post by t***@google.com
So, SETQ is a bit of vestige of this development, retained mostly for
backward compatibility, and to keep the ancient lisp wizards happy. I
would expect that if the language were designed today, SETQ would not
exist and SETF would be used in its place. SET still has a very minor
application for situations where the variable that needs setting isn't
fixed at program creation time: (set (if (is-monday-p (today)) 'foo
'bar) 100) But SET is limited to working only on the global value
(value cell) of the symbol. It doesn't affect non-special
variables.(See Hyperspec for examples)
This is an important distinction in Common Lisp, which outsiders who
have come to common lisp and now dominate the common lisp scene haven't
a clue about.
Common lisp has ENDP and NULL both do the same thing, but ENDP is
supposed to signal an error when it encounters something which is not a
proper list.
SETQ is for MODIFYING VARIABLES. The `variable' is a supremely
important concept in common lisp. There is important information
conveyed when you use SETQ to indicate you are modifying a variable and
not just any generalized place. There is no benefit in dropping this
distinction except as an appeal to retard programmers
The people who retardedly advocate for doing away with SETQ are the ones
who would also root to destroy the english language by doing away with
the distinction of using the articles `AN' and `A' in separate
situations. In other words, hitler.
It's been awhile but I think that SETQ can take a symbol macro name as
its first argument, expand it, and deal with that expansion by turning
the SET into an appropriate SETF. The point is that a symbol macro name
isn't a variable.
The general point of symbol macros is that you use them as if they're
ordinary variables. Only the implementor is expected to be aware that
they're really macros.

So any principles that apply to variables normally apply to symbol
macros as well.
--
Barry Margolin, ***@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
Udyant Wig
2020-02-29 13:38:18 UTC
Permalink
Post by Madhu
SETQ is for MODIFYING VARIABLES. The `variable' is a supremely
important concept in common lisp. There is important information
conveyed when you use SETQ to indicate you are modifying a variable
and not just any generalized place. There is no benefit in dropping
this distinction except as an appeal to retard programmers
Could you elaborate on this?

I have mostly heard the opposing view that

1) For most intents and purposes, SETF subsumes the role of SETQ; and

2) code with SETF looks more 'modern'.

Udyant Wig
--
We make our discoveries through our mistakes: we watch one another's
success: and where there is freedom to experiment there is hope to
improve.
-- Arthur Quiller-Couch
Barry Margolin
2020-02-19 16:39:43 UTC
Permalink
This post might be inappropriate. Click to display it.
Stefan Monnier
2020-02-20 18:17:59 UTC
Permalink
Post by t***@google.com
So, SETQ is a bit of vestige of this development, retained mostly for backward
compatibility, and to keep the ancient lisp wizards happy.
Yes and no: something like `setq` is needed in the macroexpansion of
`(setf VAR VAL)`. But admittedly, it can be kept hidden as an
implementation detail.


Stefan
Barry Margolin
2020-02-21 18:10:42 UTC
Permalink
Post by Stefan Monnier
Post by t***@google.com
So, SETQ is a bit of vestige of this development, retained mostly for backward
compatibility, and to keep the ancient lisp wizards happy.
Yes and no: something like `setq` is needed in the macroexpansion of
`(setf VAR VAL)`. But admittedly, it can be kept hidden as an
implementation detail.
Theoretically, SETF could have been the primitive special operator,
rather than a macro. Being a macro is just another vestige of the
history.
--
Barry Margolin, ***@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
Stefan Monnier
2020-02-24 16:52:46 UTC
Permalink
Post by Barry Margolin
Theoretically, SETF could have been the primitive special operator,
rather than a macro. Being a macro is just another vestige of the
history.
I don't have a clear idea of how such a `setf` special form would be
implemented, so maybe it's a just a lack of creativity on my part, but
my gut feeling is that it would be more painful to make that work than
it is to macro-expand it.


Stefan
Barry Margolin
2020-02-25 16:41:44 UTC
Permalink
Post by Stefan Monnier
Post by Barry Margolin
Theoretically, SETF could have been the primitive special operator,
rather than a macro. Being a macro is just another vestige of the
history.
I don't have a clear idea of how such a `setf` special form would be
implemented, so maybe it's a just a lack of creativity on my part, but
my gut feeling is that it would be more painful to make that work than
it is to macro-expand it.
IIRC, the MDL dialect of Lisp had a SETF-like primitive. But I don't
remember if it was user-extendable, like CL's SETF.
--
Barry Margolin, ***@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
Kaz Kylheku
2020-02-26 06:55:53 UTC
Permalink
Post by Barry Margolin
Post by Stefan Monnier
Post by t***@google.com
So, SETQ is a bit of vestige of this development, retained mostly for backward
compatibility, and to keep the ancient lisp wizards happy.
Yes and no: something like `setq` is needed in the macroexpansion of
`(setf VAR VAL)`. But admittedly, it can be kept hidden as an
implementation detail.
Theoretically, SETF could have been the primitive special operator,
rather than a macro. Being a macro is just another vestige of the
history.
Making anything a special operator right away means you have to
implement it twice if you have an interpreter and compiler.

Generalized places solve an M x N problem: M place-mutating operators
have to work with N kinds of places. Moreover, the M and N
categories are open.

Ideally, we want to implement the framework in O(M + N) amount
of code, not O(M x N).

For each new place, we want to be able to write a small amount of
additional code (ideally concentrated in one place), which then works
with all the operators.

For each new mutating operator, we likewise want to be able to write a
small amount of code which works with all places.

Somehow, these requirements seem to call for macros. Some of them
call for code transformation. Special operators can do their work using
code transformation, but then they "want" to be macros.

The category of place-mutating operators being extensible requires at
least the non-built-in ones supplied by the application to be macros.
--
TXR Programming Lanuage: http://nongnu.org/txr
Music DIY Mailing List: http://www.kylheku.com/diy
ADA MP-1 Mailing List: http://www.kylheku.com/mp1
Kaz Kylheku
2020-02-25 07:43:36 UTC
Permalink
Post by t***@google.com
compatibility, and to keep the ancient lisp wizards happy. I would expect that
if the language were designed today, SETQ would not exist and SETF would be
used in its place. SET still has a very minor application for situations where
In a blank-slate design unconstrained by backward compatibility, yet
guided by thorough familiarity with prior Lisp development, nobody in
their right mind would stick an extra F onto SET for naming an
important, general assignment operator.
Gregory Ramirez
2020-02-20 11:14:46 UTC
Permalink
Post by Udyant Wig
In what situations would SETQ be preferable to SETF?
Is there anything SETQ does that SETF does not?
Udyant Wig
--
We make our discoveries through our mistakes: we watch one another's
success: and where there is freedom to experiment there is hope to
improve.
-- Arthur Quiller-Couch
Vsevolod Dyomkin maintains the packages rutils, rutilsx which
contain the more general setf and getf operators := and ?.

https://lisp-univ-etc.blogspot.com/2019/07/crash-course-in-lisp.html
Loading...