changing argument variables

Discussion of Common Lisp

changing argument variables

Postby LispProgrammer » Mon Dec 01, 2008 6:42 am

if I have a function like....

(defun hello (x)

(setf x 6)
)

and then I ran...

(setf y 3)
(hello y)

How can I make it so that so that the value of y is changed to 6???
LispProgrammer
 

Re: changing argument variables

Postby lnostdal » Mon Dec 01, 2008 6:54 am

Code: Select all
(defun new (&optional value)
  (cons value nil))

(defun value-of (ptr)
  (car ptr))

(defun (setf value-of) (new-value ptr)
  (setf (car ptr) new-value))


;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;


(defun blah (x)
  (setf (value-of x) 4321))

(defun test ()
  (let ((my-ptr (new 1234)))
    (blah my-ptr)
    (value-of my-ptr)))


;; (test) => 4321
lnostdal
 
Posts: 20
Joined: Thu Jul 03, 2008 2:01 pm
Location: Skien, Norway

Re: changing argument variables

Postby dmitry_vk » Mon Dec 01, 2008 8:06 am

LispProgrammer wrote:if I have a function like....

(defun hello (x)

(setf x 6)
)

and then I ran...

(setf y 3)
(hello y)

How can I make it so that so that the value of y is changed to 6???

In Lisp, you can't pass the variable by reference, you can only pass the value (which might itself be a reference). You can wrap the variable in a structure or in a cons cell, or you can pass the setter function.
Code: Select all
;; Implementation of reference-to-variable
(defmacro make-reference (x)
  (let ((y (gensym)))
    `(cons (lambda () ,x)
           (lambda (,y) (setf ,x ,y)))))

(defun dereference (ref) (funcall (car ref)))
(defun (setf dereference) (value ref) (funcall (cdr ref) value))

(defun hello (x)
  (setf (dereference x) 6))

(let ((y 3))
  (hello (make-reference y))
  (print y))
=> 6
dmitry_vk
 
Posts: 96
Joined: Sat Jun 28, 2008 8:01 am
Location: Russia, Kazan

Re: changing argument variables

Postby Paul Donnelly » Mon Dec 01, 2008 4:19 pm

LispProgrammer wrote:if I have a function like....

(defun hello (x)

(setf x 6)
)

and then I ran...

(setf y 3)
(hello y)

How can I make it so that so that the value of y is changed to 6???

Why do you want to do this? How about:
Code: Select all
(defun hello (x) (* x 6)) ; For example

(setf x (hello x))

Even if your way were possible (which it is with a macro rather than a function), what benefit would you get? And what if the argument you pass to HELLO isn't a variable?
Code: Select all
(hello (+ 1 2))
(hello 3)
(mapcar #'hello (list 1 2 3 4))
Paul Donnelly
 
Posts: 148
Joined: Wed Jul 30, 2008 11:26 pm

Re: changing argument variables

Postby qbg » Mon Dec 01, 2008 7:59 pm

Dynamic variables would be one solution, should you really want to do this.
Code: Select all
(defun hello (name)
   (set name 6))
=> HELLO

(defun test ()
   (let ((*a* 4))
     (declare (special *a*))
     (hello '*a*)
     *a*))
=> TEST

(test)
=> 6
qbg
 
Posts: 64
Joined: Mon Jun 30, 2008 1:05 pm
Location: Minnesota

Re: changing argument variables

Postby dmitry_vk » Mon Dec 01, 2008 10:28 pm

Paul Donnelly wrote:And what if the argument you pass to HELLO isn't a variable?

The most intuitive thing to do is to treat the argument as the «place» (generalized reference, see http://www.lispworks.com/documentation/ ... /05_aa.htm). E.g., (hello (car x)) should change the car of x, (hello (slot-value some-object 'some-slot)) should change the slot of the object.
But the same syntax is impossible to use (unless hello is a macro), so argument should be wrapped into some other form (that creates the reference).
dmitry_vk
 
Posts: 96
Joined: Sat Jun 28, 2008 8:01 am
Location: Russia, Kazan

Re: changing argument variables

Postby Paul Donnelly » Tue Dec 02, 2008 1:13 am

dmitry_vk wrote:
Paul Donnelly wrote:And what if the argument you pass to HELLO isn't a variable?

The most intuitive thing to do is to treat the argument as the «place» (generalized reference, see http://www.lispworks.com/documentation/ ... /05_aa.htm). E.g., (hello (car x)) should change the car of x, (hello (slot-value some-object 'some-slot)) should change the slot of the object.
But the same syntax is impossible to use (unless hello is a macro), so argument should be wrapped into some other form (that creates the reference).

What when the argument is the result of a more complex computation, or is constant, or is supplied by a higher-order function rather than explicitly by the programmer? My point is that while OP might like modifying the argument, it's less generally useful than the way it is normally done. Of course if you do have a good reason, places are fine for their purpose.
Paul Donnelly
 
Posts: 148
Joined: Wed Jul 30, 2008 11:26 pm

Re: macros

Postby danb » Tue Dec 02, 2008 11:22 am

LispProgrammer wrote:
Code: Select all
(defun hello (x)  (setf x 6))
(setf y 3)
(hello y)

How can I make it so that so that the value of y is changed to 6???

This operates on a place, so it would be a macro:

Code: Select all
CL-USER> (defmacro setf-6 (place) `(setf ,place 6))
SETF-6
CL-USER> (let ((x 3))
           (setf-6 x)
           x)
6
danb
 
Posts: 35
Joined: Sat Jun 28, 2008 1:05 pm
Location: Urbana, Illinois, US

Re: changing argument variables

Postby metageek » Thu Dec 18, 2008 7:22 am

LispProgrammer wrote:How can I make it so that so that the value of y is changed to 6???


If you're doing this because you want to return multiple values (that being a common use case for pass-by-reference in C++), try (values) instead.
metageek
 
Posts: 10
Joined: Fri Jul 25, 2008 8:01 am

Re: changing argument variables

Postby gutzofter » Thu Dec 18, 2008 9:37 am

Why not do this:
Code: Select all
(let ((y 6))
  (defun reset-y ()
    (setf y 6))
  (defun set-y (x)
    (setf y x))
  (defun get-y ()
    y))

It looks like what your doing is describing an object that has three functions. A a reset, setter, and a getter.
gutzofter
 
Posts: 10
Joined: Thu Jul 03, 2008 12:53 pm

Next

Return to Common Lisp

Who is online

Users browsing this forum: Yahoo [Bot] and 1 guest