Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

simple swap func

15 views
Skip to first unread message

Schonfeld Uri

unread,
Apr 17, 1997, 3:00:00 AM4/17/97
to

I am really new at lisp but I've been trying for hours to write a
simple func' that swaps the values of two vars. A destructive func.
Isn't this something you do in lisp?

Juan Jose Flores Romero

unread,
Apr 17, 1997, 3:00:00 AM4/17/97
to

In article <335684...@csc.technion.ac.il>,

USER(8): (defmacro swap (x y)
`(let ((temp ,x))
(setq ,x ,y)
(setq ,y temp)))
SWAP
USER(9):(setq a 3)
3
USER(10):(setq b 4)
4
USER(11):(swap a b)
3
USER(12):a
4
USER(13):b
3
--
JUAN JOSE FLORES ROMERO (541) 346-4416
Deschutes Hall, Room 354 ju...@cs.uoregon.edu
University of Oregon http://www.cs.uoregon.edu/~juan/
Eugene, Oregon


Lyman S. Taylor

unread,
Apr 17, 1997, 3:00:00 AM4/17/97
to

In article <335684...@csc.technion.ac.il>,

Schonfeld Uri <s256...@csc.technion.ac.il> wrote:
>I am really new at lisp but I've been trying for hours to write a
>simple func' that swaps the values of two vars. A destructive func.
>Isn't this something you do in lisp?

Well it can't be a function ( actually it could be it would only work on
mutable values. And you would have to copy the "internals" of one to the
other. Immutable values wouldn't ( e.g. integers) work). Remember
everything in Lisp is a reference. You're not pushing around "values".

It can be a macro though. Look up ROTATEF in your favorite Common Lisp
reference (if it is Common Lisp that you are using). Which actually is a tad
bit more general than a two place swap.

--

Lyman S. Taylor "Computers are too reliable to replace
(ly...@cc.gatech.edu) humans effectively."
Commander Nathan Spring, "Starcops"

Hrvoje Niksic

unread,
Apr 18, 1997, 3:00:00 AM4/18/97
to

ju...@cs.uoregon.edu (Juan Jose Flores Romero) writes:

> USER(8): (defmacro swap (x y)
> `(let ((temp ,x))
> (setq ,x ,y)
> (setq ,y temp)))

I dom't think this is a good idea. Eval this:

(progn
(setq a 3)
(setq temp 10)
(swap a temp))

Now see the value of A and TEMP. :-)

--
Hrvoje Niksic <hni...@srce.hr> | Student at FER Zagreb, Croatia
--------------------------------+--------------------------------
"Beware of bugs in the above code; I have only proved it correct,
not tried it." -- Donald Knuth

Lyman S. Taylor

unread,
Apr 18, 1997, 3:00:00 AM4/18/97
to

In article <5j65el$5...@helix.cs.uoregon.edu>,

Juan Jose Flores Romero <ju...@cs.uoregon.edu> wrote:

>
>USER(8): (defmacro swap (x y)
> `(let ((temp ,x))
> (setq ,x ,y)
> (setq ,y temp)))

>SWAP

This isn't hygienic. The following:

(swap temp b )
or
(swap a temp)

won't work... You'll need a unique temporary variable to
solve this problem.

(defmacro swap ( x y )
(let (( temp (gensym)))
`(let ((,temp ,x ))
(setq ,x ,y)
(setq ,y ,temp))))


Hopefully this isn't a homework problem.... ( However, I'm sure some
derivation of the above can be commonly found... I imagine it could even
be in the FAQ ) The need for hygiene is why if you macroexpand and print
many system macros you find #Gxx symbols sprinkled liberally about....

--

Lyman S. Taylor "I'm a Doctor, not a doorstop... "
(ly...@cc.gatech.edu) The EMH Doctor in "Star Trek: First Contact".

Duncan Smith

unread,
Apr 18, 1997, 3:00:00 AM4/18/97
to

Schonfeld Uri wrote:
>
> I am really new at lisp but I've been trying for hours to write a
> simple func' that swaps the values of two vars. A destructive func.
> Isn't this something you do in lisp?

(ROTATEF X Y)

Hrvoje Niksic

unread,
Apr 18, 1997, 3:00:00 AM4/18/97
to

ju...@cs.uoregon.edu (Juan Jose Flores Romero) writes:

> USER(8): (defmacro swap (x y)
> `(let ((temp ,x))
> (setq ,x ,y)
> (setq ,y temp)))

I dom't think this is a good idea. Eval this:

(progn
(setq a 3)
(setq temp 10)
(swap a temp))

Now see the value of A and TEMP. :-)

Maybe you should rather use the existing ROTATEF macro. BTW, it can
be instructing to see how it expands in various implementations. For
example, in Emacs cl.el, `rotatef' will expand like this:

(rotatef a b)
-> (progn (setf a (prog1 b (setf b a))) nil)

No LET.

Hrvoje Niksic

unread,
Apr 18, 1997, 3:00:00 AM4/18/97
to

ju...@cs.uoregon.edu (Juan Jose Flores Romero) writes:

> USER(8): (defmacro swap (x y)
> `(let ((temp ,x))
> (setq ,x ,y)
> (setq ,y temp)))

I dom't think this is a good idea. Eval this:

(progn
(setq a 3)
(setq temp 10)
(swap a temp))

Now see the value of A and TEMP. :-)

Maybe you should rather use the existing ROTATEF macro. BTW, it can
be instructing to see how it expands in various implementations. For
example, in Emacs cl.el, `rotatef' will expand like this:

(rotatef a b)
-> (progn

(setq a (prog1 b (setq b a)))
nil)

No LET here.

Vassili Bykov

unread,
Apr 18, 1997, 3:00:00 AM4/18/97
to

Juan Jose Flores Romero <ju...@cs.uoregon.edu> wrote in article
<5j65el$5...@helix.cs.uoregon.edu>...
> In article <335684...@csc.technion.ac.il>,

> Schonfeld Uri <s256...@csc.technion.ac.il> writes:
> > I am really new at lisp but I've been trying for hours to write a
> > simple func' that swaps the values of two vars. A destructive func.
> > Isn't this something you do in lisp?
>
> USER(8): (defmacro swap (x y)
> `(let ((temp ,x))
> (setq ,x ,y)
> (setq ,y temp)))

Easier yet, just use ROTATEF: it is already there

(rotatef x y)

-- Vassili


Hrvoje Niksic

unread,
Apr 18, 1997, 3:00:00 AM4/18/97
to

vo...@novia.net (Christopher J. Vogt) writes:

> > (rotatef a b)
> > -> (progn
> > (setq a (prog1 b (setq b a)))
> > nil)
>

> How about "parallel setq":
> (psetq a b b a)

That should be equivalent. Note that CL will expand it to the same
thing. On the other hand, MACROEXPAND-1 gives the following results
in CMU CL:

* (macroexpand-1 '(rotatef a b))
(LET* ()
(MULTIPLE-VALUE-BIND
(#:G430)
B
(MULTIPLE-VALUE-BIND (#:G431) A (SETQ A #:G430) (SETQ B #:G431) NIL)))

* (macroexpand '(psetq a b b a))
(LET ((#:G432 B) (#:G433 A))
(SETQ A #:G432 B #:G433))

This seems to suggest that PSETQ is more efficient than ROTATEF in
CMUCL. But I may be wrong, as I'm no Lisp expert -- I've only noticed
the quite obvious error with the original poster.

--
Hrvoje Niksic <hni...@srce.hr> | Student at FER Zagreb, Croatia
--------------------------------+--------------------------------

ED WILL NOT CORRUPT YOUR PRECIOUS BODILY FLUIDS!!

Dorai Sitaram

unread,
Apr 18, 1997, 3:00:00 AM4/18/97
to

In article <3357AF...@bway.net>, Ken Tilton <ti...@bway.net> wrote:
> And in response to Romero's good (but unhygienic) try we would
>just offer the counter examples and suggest checking out the use of
>gensym in macros.

Shouldn't we be using ``gentemp'' rather than ``gensym'' in
macro definitions, so that we don't unnecessarily deprive
macro-expansions of read-write invariance?

--d

--
http://www.cs.rice.edu/~dorai

Lyman S. Taylor

unread,
Apr 18, 1997, 3:00:00 AM4/18/97
to

In article <kigvi5k...@jagor.srce.hr>,

Hrvoje Niksic <hni...@srce.hr> wrote:
>vo...@novia.net (Christopher J. Vogt) writes:
>
>> > (rotatef a b)
>> > -> (progn
....

Does emacs lisp have SETF? If so that's why there is no LET.
If you're going to rotatef with "places" that have a side effects then
you'll want to retrieve them all before starting to setting the new
values. Hence the more complicated...

>
>* (macroexpand-1 '(rotatef a b))
>(LET* ()
> (MULTIPLE-VALUE-BIND

....


>
>* (macroexpand '(psetq a b b a))
>(LET ((#:G432 B) (#:G433 A))

....


>
>This seems to suggest that PSETQ is more efficient than ROTATEF in
>CMUCL. But I may be wrong, as I'm no Lisp expert -- I've only noticed
>the quite obvious error with the original poster.

But ROTATEF will work with places... hence the the more generalized
expansion. [ Although I imagine one could special case to a PSETQ
if all of the items to be exchanged were symbols...]

(rotatef (gethash 'a my-hash-table) (gethash 'b my-hash-table))

psetq won't work with that... ;-)

Hmmm, I wonder if the my-swap macro I posted does the right thing too??? ;-)

Ken Tilton

unread,
Apr 18, 1997, 3:00:00 AM4/18/97
to

Lyman S. Taylor wrote:
>
> In article <5j65el$5...@helix.cs.uoregon.edu>,

> Juan Jose Flores Romero <ju...@cs.uoregon.edu> wrote:
>
> >
> >USER(8): (defmacro swap (x y)
> > `(let ((temp ,x))
> > (setq ,x ,y)
> > (setq ,y temp)))
> >SWAP
>
> This isn't hygienic. The following:

<snip>

> Hopefully this isn't a homework problem....

Hey, why don't we conjure up an informal policy in this ng as to how to
handle apparent homework queries. Seems to be a lot of them.

They are worth fending off, since they do not help students (in the long
run) and they have the worse consequence of making us less likely to
pitch in on what might be honest newbie Q's unrelated to homework.

For one thing, we could ask queriers to post what they have tried so
far.

Second, we could offer more direction than answer, as with your first
reply in which you pointed out Lisp functions would not fly but macros
would. And in response to Romero's good (but unhygienic) try we would


just offer the counter examples and suggest checking out the use of
gensym in macros.

It's a win-win. We just type a few words of suggestion and they get a
better quality help than solutions (which can be provided as the querier
demonstrates good faith). No one gets blown off, and even if it *is*
homework we haven't been bothered much and the student learns in spite
of itself. <g>

Peace, love and hygiene,

Ken

Christopher J. Vogt

unread,
Apr 18, 1997, 3:00:00 AM4/18/97
to

In article <kigybag...@jagor.srce.hr>, Hrvoje Niksic
<hni...@srce.hr> wrote:

> ju...@cs.uoregon.edu (Juan Jose Flores Romero) writes:
>

> > USER(8): (defmacro swap (x y)
> > `(let ((temp ,x))
> > (setq ,x ,y)
> > (setq ,y temp)))
>

> I dom't think this is a good idea. Eval this:
>
> (progn
> (setq a 3)
> (setq temp 10)
> (swap a temp))
>
> Now see the value of A and TEMP. :-)
>
> Maybe you should rather use the existing ROTATEF macro. BTW, it can
> be instructing to see how it expands in various implementations. For
> example, in Emacs cl.el, `rotatef' will expand like this:
>

> (rotatef a b)
> -> (progn

> (setq a (prog1 b (setq b a)))
> nil)

How about "parallel setq":
(psetq a b b a)

--
mailto:vo...@novia.net
Omaha, NE
http://www.novia.net/~vogt/

Cyber Surfer

unread,
Apr 18, 1997, 3:00:00 AM4/18/97
to

With a mighty <5j68ut$p...@pravda.cc.gatech.edu>,
ly...@cc.gatech.edu uttered these wise words...

> It can be a macro though. Look up ROTATEF in your favorite Common Lisp
> reference (if it is Common Lisp that you are using). Which actually is a tad
> bit more general than a two place swap.

What about using:

(defmacro (swapf a b)
`(rotatef ,a ,b))
--
<URL:http://www.wildcard.demon.co.uk/> You can never browse enough
Martin Rodgers | Programmer and Information Broker | London, UK
Please note: my email address is gubbish.

Lyman S. Taylor

unread,
Apr 18, 1997, 3:00:00 AM4/18/97
to

In article <3357AF...@bway.net>, Ken Tilton <ti...@bway.net> wrote:

...


>would. And in response to Romero's good (but unhygienic) try we would
>just offer the counter examples and suggest checking out the use of
>gensym in macros.

...
I thought about doing just that. :-) Since it was "mostly" there already
I kind of just filled in the rest. Perhaps I could have done an example that
just used gensym that didn't do swap. Brief examples of a new construct
tend to help folks out also... but sometimes those are harder to construct
than the solution itself. ;-)

Erik Naggum

unread,
Apr 18, 1997, 3:00:00 AM4/18/97
to

* Dorai Sitaram

| Shouldn't we be using ``gentemp'' rather than ``gensym'' in macro
| definitions, so that we don't unnecessarily deprive macro-expansions of
| read-write invariance?

I prefer `make-symbol'. I also bind *print-circle* to t, even though it
costs more when printing. e.g.,

(let ((x (make-symbol "x")))
`(list ,x ,x))
=> (list #1=#:x #1#)

(this also works in GNU Emacs Lisp from the next version onward.)

#\Erik
--
I'm no longer young enough to know everything.

Barry Margolin

unread,
Apr 18, 1997, 3:00:00 AM4/18/97
to

In article <5j8jlf$b...@news.gte.com>, Dorai Sitaram <ds...@bunny.gte.com> wrote:
>Shouldn't we be using ``gentemp'' rather than ``gensym'' in
>macro definitions, so that we don't unnecessarily deprive
>macro-expansions of read-write invariance?

If you want read-write invariance set *PRINT-CIRCLE* to T before printing
the macro-expansions. The gensym'ed variables should then be printed using
#n= and #n# notation.
--
Barry Margolin
BBN Corporation, Cambridge, MA
bar...@bbnplanet.com
(BBN customers, call (800) 632-7638 option 1 for support)

Erik Naggum

unread,
Apr 18, 1997, 3:00:00 AM4/18/97
to

* Christopher J. Vogt

| How about "parallel setq":
| (psetq a b b a)

`psetq' is also a macro, and at least in one implementation results in
_exactly_ the same code as `rotatef'.

but while we're on it...

(multiple-value-setq (a b) (values b a))

which also results in exactly same code as `rotatef'...

Lyman S. Taylor

unread,
Apr 18, 1997, 3:00:00 AM4/18/97
to

In article <5j8jlf$b...@news.gte.com>, Dorai Sitaram <ds...@bunny.gte.com> wrote:
>
>Shouldn't we be using ``gentemp'' rather than ``gensym'' in
>macro definitions, so that we don't unnecessarily deprive
>macro-expansions of read-write invariance?

GENTEMP will intern the symbols in the current package. GENSYM does not.
Thereby the package's symbol table does not grow "large" just because
there is a high use of macros. And once interned they stick around
forever....

CL-USER 8 > (defun show-me-the-symbols ()
(describe (gensym))
(describe (gentemp)))


SHOW-ME-THE-SYMBOLS

CL-USER 9 > (show-me-the-symbols)

#:G831 is a SYMBOL
[NAME] : "G831"
[VALUE] : #<unbound value>
[FUNCTION] : #<unbound function>
[PLIST] : NIL
[PACKAGE] : NIL
T0 is a SYMBOL
[NAME] : "T0"
[VALUE] : #<unbound value>
[FUNCTION] : #<unbound function>
[PLIST] : NIL
[PACKAGE] : #<The COMMON-LISP-USER package, 5/16 internal, 0/4 external>

CL-USER 10 >

Hrvoje Niksic

unread,
Apr 19, 1997, 3:00:00 AM4/19/97
to

ly...@cc.gatech.edu (Lyman S. Taylor) writes:

> Does emacs lisp have SETF? If so that's why there is no LET.

`setf' is a macro in Emacs Lisp. In fact, setf is implemented by the
same cl.el that implements rotatef. This is why setf is not used by
rotatef.

> If you're going to rotatef with "places" that have a side effects
> then you'll want to retrieve them all before starting to setting
> the new values.

That works well with that implementation.

> >This seems to suggest that PSETQ is more efficient than ROTATEF in
> >CMUCL. But I may be wrong, as I'm no Lisp expert -- I've only noticed
> >the quite obvious error with the original poster.
>
> But ROTATEF will work with places... hence the the more generalized
> expansion. [ Although I imagine one could special case to a PSETQ
> if all of the items to be exchanged were symbols...]
>
> (rotatef (gethash 'a my-hash-table) (gethash 'b my-hash-table))
>
> psetq won't work with that... ;-)

But then again -- there's PSETF! :-)

--
Hrvoje Niksic <hni...@srce.hr> | Student at FER Zagreb, Croatia
--------------------------------+--------------------------------

Oh lord won't you buy me a color TV...

0 new messages