Google 网上论坛不再支持新的 Usenet 帖子或订阅项。历史内容仍可供查看。

How to achieve side effect in functions

已查看 2 次
跳至第一个未读帖子

Eqbal Z

未读,
2002年12月15日 19:08:222002/12/15
收件人
Hi,

I need to write a lisp function rev(lst revlist) which reverses the
list lst and stores it in revlist.
I am able to write the rev(lst) function but how do I write the
function so the result is stored in one of its arguments?

Thanks

Jochen Schmidt

未读,
2002年12月15日 19:19:002002/12/15
收件人
Eqbal Z wrote:

Lisp has call-by-value. You can simulate what you want by making "rev"
a macro.

Having said that you should definitely look up some information about
returning multiple values in Common Lisp.

ciao,
Jochen

--
http://www.dataheaven.de

Simon András

未读,
2002年12月16日 07:59:032002/12/16
收件人
eza...@pioneer-usa.com (Eqbal Z) writes:

If you're willing to pass a cons as the second argument, then you can
(but shouldn't) do this by setf-ing its car and cdr to that of the
reversed list. But note that CL is not C, so only do this if it's a
homework assignment and you're desperate.

Andras

Erik Naggum

未读,
2002年12月16日 09:46:272002/12/16
收件人
* eza...@pioneer-usa.com (Eqbal Z)

| I need to write a lisp function rev(lst revlist) which reverses the
| list lst and stores it in revlist.

Why do you think you need this?

--
Erik Naggum, Oslo, Norway

Act from reason, and failure makes you rethink and study harder.
Act from faith, and failure makes you blame someone and push harder.

Kaz Kylheku

未读,
2002年12月16日 14:41:412002/12/16
收件人
eza...@pioneer-usa.com (Eqbal Z) wrote in message news:<3b440a00.02121...@posting.google.com>...

> Hi,
>
> I need to write a lisp function rev(lst revlist) which reverses the

You don't have to call list variables LST in Lisp. Even though there
is a function named LIST, you can still use it as a variable name.

> list lst and stores it in revlist.
> I am able to write the rev(lst) function but how do I write the

Lisp already has a REVERSE function, so you wasted your time.

> function so the result is stored in one of its arguments?

Try writing:

(setf revlist (reverse list))

If you want a special notation for this, write a macro which
translates that notation into the above, e.g.

(defmacro reverse-into (source-list target-place)
`(setf ,target-place (reverse ,source-list)))

I can't think of any good reason for wanting this, but there you have
it.

Eqbal Z

未读,
2002年12月16日 15:20:502002/12/16
收件人
asi...@math.bme.hu (Simon Andr s) wrote in message news:<vcdbs3m...@tarski.math.bme.hu>...


Yes this is a homework assignment. How do you pass cons as an argument?

Simon András

未读,
2002年12月16日 20:46:282002/12/16
收件人
eza...@pioneer-usa.com (Eqbal Z) writes:

(rev this-is-your-list (list nil))

(list nil) is a cons. But any cons, that is, anything (call it x) for
which (typep x 'cons) returns T would do.

But see the other replies. Mine was just an attempt to show that you
can do what you want to with a function, depending on how you're going
to use it.

Andras

Simon András

未读,
2002年12月17日 01:26:012002/12/17
收件人
asi...@math.bme.hu (Simon András) writes:

> > Yes this is a homework assignment. How do you pass cons as an argument?
>
> (rev this-is-your-list (list nil))

Perhaps I should add that although this answers your quoted question,
considering the wider context, I should've written

(let ((this-will-be-the-reversed-list (list nil)))
(rev this-is-your-list this-will-be-the-reversed-list)
;; here this-will-be-the-reversed-list is already the reversed list
;; you do whatever you want with it
)

Andras

Pascal Bourguignon

未读,
2002年12月19日 19:19:482002/12/19
收件人
eza...@pioneer-usa.com (Eqbal Z) writes:


Since you want probably recover the modified value after the call, you
need to keep a reference to the cons. So first, you assign it to a
variable (theta in my case) then you call the function passing that
variable 'by value'. Just that a cons contains two pointers, so you
effectively passed a reference to the function. Note that in my case I
only modify the cdr of the cons but both the car and the cdr can be
used.


(defun fun (n output)
(do ((i 0 (1+ i)))
((> i n))
(push i (cdr output))))

(show
(let ((theta (cons nil nil)))
(fun 3 theta)
(cdr theta))
)

==> (3 2 1 0)

Of course, instead of having an 'output' or 'inout' parameter that
needs such a special initialization before calling, you may want to
have a input parameter and recover an output as result, maybe a
multiple result if the function must return other values too.

So, instead of writting:
(setq inout (cons nil variable))
(setq result (fun n inout))
(setq variable (cdr inout))

and using (setf (cdr inout) ...) and (cdr inout) in the function fun,

(defun fun (n inout)
;; ...
(setf (cdr inout) (f (cdr inout)))
;; ...
result)

[ note the equivalence with C:

result=fun(n,&variable);

result_t fun(int n,variable_t* inout)
{
/* ... */
(*inout)=f(*inout);
/* ... */
return(result);
}

]

you may also write:

(multiple-value-bind (res out) (fun n variable)
(setq result res)
(setq variable out))

and use (setq inout) and inout in the function fun and (values result
inout) at the end:

(defun fun (n inout)
;; ...
(setq inout (f inout))
;; ...
(values result inout))


[ note the equivalence with C: oops, you can only return one result here...

variable=fun(n,variable);

variable_t fun(int n,variable_t inout)
{
/* ... */
inout=f(inout);
/* ... */
return(inout);
}

]


--
__Pascal_Bourguignon__ http://www.informatimago.com/
----------------------------------------------------------------------
There is a fault in reality. do not adjust your minds. -- Salman Rushdie

0 个新帖子