Discussion:
how to map a variable to a list?
(too old to reply)
Jinsong Zhao
2023-04-10 13:05:23 UTC
Permalink
Hi there,

In the following code example,

(defun a-test (lst)
(let ((a (elt lst 0))
(b (elt lst 1))
(c (elt lst 2)))
(+ a (- c b))))

How to map local variable a, b, and c to the elements of lst? In my
actual code, the lst have 12 elements, and I have 12 named local
variables that appeared in the body with high frequency.

Best,
Jinsong
Spiros Bousbouras
2023-04-10 13:49:39 UTC
Permalink
On Mon, 10 Apr 2023 21:05:23 +0800
Post by Jinsong Zhao
Hi there,
In the following code example,
(defun a-test (lst)
(let ((a (elt lst 0))
(b (elt lst 1))
(c (elt lst 2)))
(+ a (- c b))))
How to map local variable a, b, and c to the elements of lst? In my
actual code, the lst have 12 elements, and I have 12 named local
variables that appeared in the body with high frequency.
Why is the above code not satisfactory ?
Kaz Kylheku
2023-04-10 18:41:11 UTC
Permalink
Post by Spiros Bousbouras
On Mon, 10 Apr 2023 21:05:23 +0800
Post by Jinsong Zhao
Hi there,
In the following code example,
(defun a-test (lst)
(let ((a (elt lst 0))
(b (elt lst 1))
(c (elt lst 2)))
(+ a (- c b))))
How to map local variable a, b, and c to the elements of lst? In my
actual code, the lst have 12 elements, and I have 12 named local
variables that appeared in the body with high frequency.
Why is the above code not satisfactory ?
Other than that nobody who knows Common Lisp inside out would
write it that way, rather than doing a destructuring-bind?

This could be an X-Y problem; perhaps the function just wants
to take separate arguments, and the caller should apply the list.

(defun a-test (a b c) ...)

(apply #'a-test '(1 2 3))
--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @***@mstdn.ca
steve
2024-04-19 22:14:18 UTC
Permalink
Spiros Bousbouras <***@gmail.com> writes:

< On Mon, 10 Apr 2023 21:05:23 +0800
Post by Jinsong Zhao
Hi there,
In the following code example,
(defun a-test (lst)
(let ((a (elt lst 0))
(b (elt lst 1))
(c (elt lst 2)))
(+ a (- c b))))
How to map local variable a, b, and c to the elements of lst? In my
actual code, the lst have 12 elements, and I have 12 named local
variables that appeared in the body with high frequency.
< Why is the above code not satisfactory ?

no idea, works for me.

(defun a-test (lst)
(let ((a (pop lst))
(b (pop lst))
(c (pop lst)))
(+ a (- c b))))


(a-test '(3 5 7))

(defun a-test2 (lst)
(let ((a (elt lst 0))
(b (elt lst 1))
(c (elt lst 2)))
(+ a (- c b))))


(a-test2 '(1 4 7))



show the code? might be helpful. 12 variables can be done with reduce
mapcar, depending on the operation.
Tom Russ
2023-04-10 16:38:53 UTC
Permalink
Post by Jinsong Zhao
Hi there,
In the following code example,
(defun a-test (lst)
(let ((a (elt lst 0))
(b (elt lst 1))
(c (elt lst 2)))
(+ a (- c b))))
How to map local variable a, b, and c to the elements of lst? In my
actual code, the lst have 12 elements, and I have 12 named local
variables that appeared in the body with high frequency.
Tom Russ
2023-04-10 16:46:19 UTC
Permalink
Post by Jinsong Zhao
Hi there,
In the following code example,
(defun a-test (lst)
(let ((a (elt lst 0))
(b (elt lst 1))
(c (elt lst 2)))
(+ a (- c b))))
How to map local variable a, b, and c to the elements of lst? In my
actual code, the lst have 12 elements, and I have 12 named local
variables that appeared in the body with high frequency.
Best,
Jinsong
It isn't clear to us what behavior you want to have from your mapping.
In the code you show, each of the variables is bound to a particular element
of your input list. So you can use them to reference the values of the list.
But each of the variables is a local variable inside the LET form, so any change
to the variable is just a local effect. It will not change the value in the input
list unless the change you make on the local variable is a mutation of the object
that the variable is bound to.

The code you provided should return the value of (+ A (- C B)). What do you
expect it to do?

Some other comments.
In general ELT is not a great function to use on lists, because it has to walk the
list until it gets to the Nth element. If you want to bind a number of variables to
elements of a list, then DESTRUCTURING-BIND will be more convenient and also
more efficient.

But if you have a fixed size list where the individual elements have some meaningful
names, then perhaps an even better approach would be to use a struct (via DEFSTRUCT)
to provide named accessors to the elements. It would also have the side benefit
of being both more space and time efficient.
Jinsong Zhao
2023-04-12 13:02:00 UTC
Permalink
Thanks a lot for all your replies. DESTRUCTURING-BIND is what I want.

Before asking this question, I actually read its CLHS pages, however, I
did not understand it well.

Best,
Jinsong
Post by Tom Russ
Post by Jinsong Zhao
Hi there,
In the following code example,
(defun a-test (lst)
(let ((a (elt lst 0))
(b (elt lst 1))
(c (elt lst 2)))
(+ a (- c b))))
How to map local variable a, b, and c to the elements of lst? In my
actual code, the lst have 12 elements, and I have 12 named local
variables that appeared in the body with high frequency.
Best,
Jinsong
It isn't clear to us what behavior you want to have from your mapping.
In the code you show, each of the variables is bound to a particular element
of your input list. So you can use them to reference the values of the list.
But each of the variables is a local variable inside the LET form, so any change
to the variable is just a local effect. It will not change the value in the input
list unless the change you make on the local variable is a mutation of the object
that the variable is bound to.
The code you provided should return the value of (+ A (- C B)). What do you
expect it to do?
Some other comments.
In general ELT is not a great function to use on lists, because it has to walk the
list until it gets to the Nth element. If you want to bind a number of variables to
elements of a list, then DESTRUCTURING-BIND will be more convenient and also
more efficient.
But if you have a fixed size list where the individual elements have some meaningful
names, then perhaps an even better approach would be to use a struct (via DEFSTRUCT)
to provide named accessors to the elements. It would also have the side benefit
of being both more space and time efficient.
Tom Russ
2023-04-13 01:06:01 UTC
Permalink
Post by Jinsong Zhao
Thanks a lot for all your replies. DESTRUCTURING-BIND is what I want.
Out of curiosity, what is an example of the code that you want to write?

I ask because I wonder if a struct would be a better data structure than a list.
Jinsong Zhao
2023-04-13 10:14:39 UTC
Permalink
Post by Tom Russ
Post by Jinsong Zhao
Thanks a lot for all your replies. DESTRUCTURING-BIND is what I want.
Out of curiosity, what is an example of the code that you want to write?
I ask because I wonder if a struct would be a better data structure than a list.
The list in my sample code is the size of the different sections decoded
from the binary header. Mapping them to locally named variables makes it
easy to check the validity of the file. Because it is only used once,
structure is perhaps too heavy. Also, there are rumors that structure is
obsolete and class should be used, which I am even less familiar with.

Thanks again for the reply and helps.

Best,
Jinsong
Spiros Bousbouras
2023-04-13 10:55:06 UTC
Permalink
On Thu, 13 Apr 2023 18:14:39 +0800
Post by Jinsong Zhao
The list in my sample code is the size of the different sections decoded
from the binary header. Mapping them to locally named variables makes it
easy to check the validity of the file. Because it is only used once,
structure is perhaps too heavy.
Perhaps. Without knowing how the list gets created to begin with , it is
impossible to tell.
Post by Jinsong Zhao
Also, there are rumors that structure is
obsolete and class should be used, which I am even less familiar with.
I don't know where you heard the "rumours" but they are wrong. Main
differences between classes and structures :

Classes Structures

Support multiple
inheritance YES NO


Can be redefined YES NO ; undefined
behaviour if you attempt
to do so.


So classes offer greater flexibility at the cost of execution speed
although I don't think it would cost too much in execution speed
if structures also offered multiple inheritance.

With structures you also get automatically defined accessors , print methods
and copier functions ; you can optionally define the layout to be a vector or
a list but then the structure does not become a new type in the CL type
system but counts as a vector or list respectively.
--
If it was a Bill Clinton day, the dry cleaners could have a special on removing
stains.
Mark O'Brien
http://www.stonekettle.com/2016/02/presidents-daze.html
Spiros Bousbouras
2023-04-14 02:34:19 UTC
Permalink
On Thu, 13 Apr 2023 10:55:06 -0000 (UTC)
Post by Spiros Bousbouras
On Thu, 13 Apr 2023 18:14:39 +0800
Post by Jinsong Zhao
Also, there are rumors that structure is
obsolete and class should be used, which I am even less familiar with.
I don't know where you heard the "rumours" but they are wrong. Main
Classes Structures
Support multiple
inheritance YES NO
Can be redefined YES NO ; undefined
behaviour if you attempt
to do so.
So classes offer greater flexibility at the cost of execution speed
although I don't think it would cost too much in execution speed
if structures also offered multiple inheritance.
With structures you also get automatically defined accessors , print methods
and copier functions ; you can optionally define the layout to be a vector or
a list but then the structure does not become a new type in the CL type
system but counts as a vector or list respectively.
Also the accessors in structures are regular functions whereas in classes they
are generic functions. So again , you get greater flexibility with classes at
the cost of execution speed. So structures and classes offer different
tradeoffs and neither one is going away , even without taking into account
backwards compatibility.
jimtaylor
2023-04-13 02:42:31 UTC
Permalink
Post by Jinsong Zhao
Before asking this question, I actually read its CLHS pages, however,
I did not understand it well.
It just takes time to familiarize yourself with it.

Be sure to check out the Common Lisp Cookbook as well, it's often a bit
easier to follow at least initially.
HenHanna
2024-10-21 22:34:08 UTC
Permalink
Post by jimtaylor
Post by Jinsong Zhao
Before asking this question, I actually read its CLHS pages, however,
I did not understand it well.
It just takes time to familiarize yourself with it.
Be sure to check out the Common Lisp Cookbook as well, it's often a bit
easier to follow at least initially.
What was the question????

Kaz Kylheku
2023-04-10 18:38:32 UTC
Permalink
Post by Jinsong Zhao
Hi there,
In the following code example,
(defun a-test (lst)
(let ((a (elt lst 0))
(b (elt lst 1))
(c (elt lst 2)))
(+ a (- c b))))
How to map local variable a, b, and c to the elements of lst? In my
actual code, the lst have 12 elements, and I have 12 named local
variables that appeared in the body with high frequency.
(destructuring-bind (a b c) lst
...)
--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @***@mstdn.ca
Ben Bacarisse
2023-04-10 20:16:40 UTC
Permalink
Post by Jinsong Zhao
In the following code example,
(defun a-test (lst)
(let ((a (elt lst 0))
(b (elt lst 1))
(c (elt lst 2)))
(+ a (- c b))))
How to map local variable a, b, and c to the elements of lst? In my actual
code, the lst have 12 elements, and I have 12 named local variables that
appeared in the body with high frequency.
As others have said, it's not clear what the problem is. It would help
if you posted the actual code, because giving a simplified example may be
hiding what you see as the problem.

In the meantime, since 'lst' suggests a list, have you considered using
destructuring-bind?

(defun a-test (lst)
(destructuring-bind (a b c &rest _) lst
(+ a (- c b))))

(Note: elt works on any sequence so this may not suit your use.)
--
Ben.
Yong
2023-04-11 13:12:53 UTC
Permalink
Post by Jinsong Zhao
Hi there,
In the following code example,
(defun a-test (lst)
  (let ((a (elt lst 0))
        (b (elt lst 1))
        (c (elt lst 2)))
    (+ a (- c b))))
How to map local variable a, b, and c to the elements of lst? In my
actual code, the lst have 12 elements, and I have 12 named local
variables that appeared in the body with high frequency.
Best,
Jinsong
Emacs macro seq-let can do the similar thing:

(seq-let (v1 v2) '(val1 val2 val3)
(message "%s %s" v1 v2))


I believe that common lisp must have a similar function, currently a
known way to do this is:

;; assign 5, 6 to v1, v2
(let (v1 v2)
(mapcar (lambda (sym val) (set sym val)) '(v1 v2) '(5 6)))
Madhu
2023-04-11 16:26:16 UTC
Permalink
Post by Yong
(seq-let (v1 v2) '(val1 val2 val3)
(message "%s %s" v1 v2))
I believe that common lisp must have a similar function, currently a
;; assign 5, 6 to v1, v2
(let (v1 v2)
(mapcar (lambda (sym val) (set sym val)) '(v1 v2) '(5 6)))
In general this is wrong, unless v1 and v2 are "declared" "special". SET
modifies the global binding of the variable. You should have done a
(defvar v1) (defvar v2) first before using LET.

presumably the op was asking only about lexical bindings.

For dynamic bindings there is progv, which is a strange beast

http://www.lispworks.com/documentation/lw80/CLHS/Body/s_progv.htm
"progv allows binding one or more dynamic variables whose names may be
determined at run time"

assuming v1 and v2 do not have top-level bindings and are not declared
globally special,

```
(let ((v1 1) (v2 2)) (progv '(v1 v2) '(5 6) (list v1 v2))) ;=> (1 2)

(let ((v1 1) (v2 2))
(declare (special v1 v2))
(progv '(v1 v2) '(5 6)
(list v1 v2))) ;=> (5 6)
```
Kaz Kylheku
2023-04-11 21:45:50 UTC
Permalink
Post by Yong
(seq-let (v1 v2) '(val1 val2 val3)
(message "%s %s" v1 v2))
I believe that common lisp must have a similar function, currently a
;; assign 5, 6 to v1, v2
(let (v1 v2)
(mapcar (lambda (sym val) (set sym val)) '(v1 v2) '(5 6)))
Please refrain from posting "AI"-generated drivel.
--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @***@mstdn.ca
Loading...