From: raptor
Subject: chaining functions ?
Date: 
Message-ID: <1139441966.221101.83740@f14g2000cwb.googlegroups.com>
I have an (if...) and like on the else part to add more acction. I have
this this :

(if (nth n) (nth n) (setq *mylist* (append *mylist* (myfunc n) )) )

Several questions on that :
1. Is there some trick not to repeat (nth n), will doing this slow the
things 'cause it has to call the same function twice, just wondering.
2. Isnt there easier way to append element to the list, not prepend
/push/ and modify the *mylist*,  (not doing list generation and
assignment, but just modify *mylist* in-place)
3. In the else part what I really like to do :
    pushAtBack @mylist, myfunc(n);
    return nth(n)

not just 'pushAtBack'.

:"), ok that is for now
tia

From: Pascal Costanza
Subject: Re: chaining functions ?
Date: 
Message-ID: <44vee8F4671nU1@individual.net>
raptor wrote:
> I have an (if...) and like on the else part to add more acction. I have
> this this :
> 
> (if (nth n) (nth n) (setq *mylist* (append *mylist* (myfunc n) )) )
> 
> Several questions on that :
> 1. Is there some trick not to repeat (nth n), will doing this slow the
> things 'cause it has to call the same function twice, just wondering.

You're almost already giving the answer in the question:

(let ((value (nth n)))
   (if value value
      (setq *mylist* (append *mylist* (myfunc n)))))

A macro that abbreviates this is a typical exercise in macro programming.

> 2. Isnt there easier way to append element to the list, not prepend
> /push/ and modify the *mylist*,  (not doing list generation and
> assignment, but just modify *mylist* in-place)

See the first example in the HyperSpec entry for define-modify-macro.

> 3. In the else part what I really like to do :
>     pushAtBack @mylist, myfunc(n);
>     return nth(n)

(if expression
   (progn do-several-things ...)
   (progn do-several-otherthings ...))

or

(cond (expression do-several-things ...)
       (t do-several-other-things ...))


Pascal

-- 
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/
From: raptor
Subject: Re: chaining functions ?
Date: 
Message-ID: <1139443146.647403.160700@f14g2000cwb.googlegroups.com>
thanx for the answers. As u mentioned this :

| See the first example in the HyperSpec entry for define-modify-macro.

is there some command tool similar to perldoc, so that I can say :

lispdoc -f cons

and i get quick documentation on the function/macros/whatever

thx
From: Lars Rune Nøstdal
Subject: Re: chaining functions ?
Date: 
Message-ID: <1139447577.591602.327230@g43g2000cwa.googlegroups.com>
Slime can lookup stuff in the hyperspec and show it locally in emacs or
use an external browser if you prefer.
From: Pascal Costanza
Subject: Re: chaining functions ?
Date: 
Message-ID: <450eodF4aomvU1@individual.net>
Lars Rune N�stdal wrote:
> Slime can lookup stuff in the hyperspec and show it locally in emacs or
> use an external browser if you prefer.

Same for LispWorks (but only in a browser).


Pascal

-- 
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/
From: raptor
Subject: Re: chaining functions ?
Date: 
Message-ID: <1139480850.208943.149240@g47g2000cwa.googlegroups.com>
thanx alot guys.
From: Frédéric Jolliton
Subject: Re: chaining functions ?
Date: 
Message-ID: <86vevpp4lm.fsf@mau.intra.tuxee.net>
"raptor" <·······@gmail.com> writes:
[..]
> is there some command tool similar to perldoc, so that I can say :
>
> lispdoc -f cons
> and i get quick documentation on the function/macros/whatever

Easy:

$ echo 'links "http://www.xach.com/clhs?q=$1"' > lispdoc
$ chmod a+x lispdoc

Then:

$ ./lispdoc cons

(Where 'links' is a WWW curses browser.)

-- 
Fr�d�ric Jolliton
From: Pascal Bourguignon
Subject: Re: chaining functions ?
Date: 
Message-ID: <87d5hxjpmg.fsf@thalassa.informatimago.com>
"raptor" <·······@gmail.com> writes:

> I have an (if...) and like on the else part to add more acction. I have
> this this :
>
> (if (nth n) (nth n) (setq *mylist* (append *mylist* (myfunc n) )) )
>
> Several questions on that :
> 1. Is there some trick not to repeat (nth n), will doing this slow the
> things 'cause it has to call the same function twice, just wondering.

 (or (nth n)  (setq *mylist* (append *mylist* (myfunc n))))


> 2. Isnt there easier way to append element to the list, not prepend
> /push/ and modify the *mylist*,  (not doing list generation and
> assignment, but just modify *mylist* in-place)

There's one difficulty here.  In Lisp, a list is either NIL or a CONS
cell  (whose CDR is a list).  The problem is that NIL is immutable,
while CONS cells (that don't come from the source of the program) are
mutable.  Therefore when (eq *mylist* nil), you cannot do anything
else than assign to *mylist*.

The second point, is whether some tail of *mylist* is shared or not
with another variable, and if it's shared, whether it's "logically" or
only "physically".

(defvar *herlist* (list 5 6 7))
(defvar *mylist*  (list* 1 2 3 *herlist*))
(nconc *mylist* (list 10))
*herlist* --> (5 6 7 10)  ; is this wanted or not?


So assuming that *mylist* is not NIL and that either it's not shared,
or if it's shared then you want all the variables sharing a tail of
*mylist* to be appended at the same time, you can write:

(assert (not (null *mylist*)))
(or (nth n) (nconc *mylist* (myfunc n)))

This is still O(n), that is, when in a loop you get O(n�), so what you
really want to do is:

(loop
    do      (or (nth n) (push (myfunc n) *mylist*))
    finally (setf *mylist* (nreverse *mylist*)))

which is O(n) in total. (I assume your (nth n) is O(1), since it is not CL:NTH).



> 3. In the else part what I really like to do :
>     pushAtBack @mylist, myfunc(n);
>     return nth(n)
>
> not just 'pushAtBack'.

That is, what you start from actually is:

(if (nth n)
    (nth n)
    (progn (setq *mylist* (append *mylist* (myfunc n)))
           (nth n)))

Note that in the else case, (nth n) is NIL (unless your NTH is not a
function, but depends on *mylist* or a side effect of MYFUNC).

You could write:

(assert (not (null *mylist*)))
(or (nth n) (nconc *mylist* (myfunc n)) nil)



Finally if you want to do a lot of "unnatural" operations on lists
(the "natural" list operations  in lisp work on the head (car) and the
rest (cdr) of a list, with the common idiom of push / nreverse, etc),
then you need to introduce a new abstract data type for which you'll
be able to write optimized operations.

For example, with:

(defstruct htlist head tail)

(defun htelements (htlist) 
   (htlist-head htlist))

(defun htpush (item htlist)
   (push item (htlist-head htlist))
   (when (null (htlist-tail htlist)) 
      (setf (htlist-tail htlist) (htlist-head htlist)))
   htlist)

(defun htpush-at-end (item htlist)
   (setf (cdr (htlist-tail htlist)) (cons item nil))
   (when (null (htlist-head htlist)) 
      (setf (htlist-head htlist) (htlist-tail htlist)))
   (setf (htlist-tail htlist) (cdr (htlist-tail htlist)))
   htlist)


you can easily (in O(1)) add elements at both ends:

[60]> (defparameter *mylist* (make-htlist))
*MYLIST*
[61]> (loop :for i :from  1 :to 10 
            :do (if (oddp i) (htpush i *mylist*) (htpush-at-end i *mylist*)) 
            :finally (print (htelements *mylist*)))

(9 7 5 3 1 2 4 6 8 10) 
NIL


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

CONSUMER NOTICE: Because of the "uncertainty principle," it is
impossible for the consumer to simultaneously know both the precise
location and velocity of this product.