List context - performance

Started by Tim Johnson, September 29, 2009, 12:09:51 PM

Previous topic - Next topic

Tim Johnson

The more I use newlisp the more I like it. Mostly

I find 'append to be an exception. I have found myself coding a lot of
(set 'res(append res (list "blah" "blah1" "blah2"))) ;; untested
This begs (IMHO) for a "reconstructive" (or "destructive", I like "reconstructive" better)

function or a context.

I'd like to do something like
(set 'lst (new list))
(lst:cat "blah" "blah1" "blah2" "...")


and I can and would be happy to write such a context. I realize that there could

be a performance penalty. I would welcome comments, both on where the

performance penalities would be greatest and whether I may possibly be

"barking up the wrong tree".

Thanks, Keep up the good work Lutz
Programmer since 1987. Unix environment.

Jeff

#1
You could always write a function that does (push item lst -1) and returns lst again.
Jeff

=====

Old programmers don\'t die. They just parse on...



http://artfulcode.net\">Artful code

TedWalther

#2
Quote from: "Jeff"You could always write a function that does (push item lst -1) and returns lst again.


Doesn't push return lst already?
Cavemen in bearskins invaded the ivory towers of Artificial Intelligence.  Nine months later, they left with a baby named newLISP.  The women of the ivory towers wept and wailed.  \"Abomination!\" they cried.

cormullion

#3
Hi Tim - if I read you right, you want either a 'flat push' or a 'destructive append'?


(set 'r (list "start"))
(push (list "this" "is" "a" "list" "of" "strings") r -1)
(println r)
;-> ("start" ("this" "is" "a" "list" "of" "strings")) ; want flat list

(set 'r (list "start"))
(append r (list "this" "is" "a" "list" "of" "strings")) ; want this result in r ...
(println r)
;-> ("start")


I've wondered about this too! Haven't discovered the solution yet... Sometimes I try 'join' hoping that it works on two or more lists... But it never does :)



As for performance, a function should be pretty quick - esp if pass by reference?

Lutz

#4
would it be called 'adjoin' ?

Jeff

#5
Quote from: "TedWalther"Doesn't push return lst already?


Nope. It returns the item pushed. You would need to use a macro to prevent the funcall from copying the list, though.


Quote from: "Lutz"would it be called 'adjoin' ?


Or nconc
Jeff

=====

Old programmers don\'t die. They just parse on...



http://artfulcode.net\">Artful code

Tim Johnson

#6
Quote from: "Lutz"would it be called 'adjoin' ?

From your manual, I've played with "redefining" protected symbols in contexts,

works good - so append could be re-used with an "object". Which I really like.

thanks
Programmer since 1987. Unix environment.

Tim Johnson

#7
Following code is my starting point:
(context 'lst)
(set
'context-name "lst"     ## name of context
'object-name  "[none]"  ## name of object
'data '()               ## list - holds data
)
(define(dbg)
(println "Class: " context-name
        " Name: " object-name
" Data: " data)
)
(define (lst:clear) (set 'data '()))
(define (lst:++)
(set 'data (append data (args))))
(context 'MAIN)
(define (lst! )
(new lst 'newlst)
(set 'newlst:data (rest(args))
  'newlst:object-name (first (args))
)
newlst)

FYI: 'context-name, 'object-name and 'dbg are standard boiler-plate for me.

This allows me to use an 'inspect function for debugging.  

And using MAIN:lst! as an initializer with the stringizing symbol lends itself

handily (for me) to an editor macro

Console session:

> (load "/home/http/run/newlisp/list.lsp")
(lambda () (new lst 'newlst) (set 'newlst:data (rest (args)) 'newlst:object-name
  (first (args))) newlst)
> (set 'l (lst! "l" "one" "two"))
newlst
> (l:dbg)
Class: lst Name: l Data: ("one" "two")
Programmer since 1987. Unix environment.

Lutz

#8
QuoteNope. It returns the item pushed.


Nope. It returns the list ;-)


> (set 'lst '(b c d))
(b c d)               "
> (push 'a lst)
(a b c d)
> lst
(a b c d)
>  


This was changed in 10.0. The return value now is also a reference, so you can do destructive queues and cycles:


> (set 'lst '(1 2 3 4 5))
(1 2 3 4 5)
> (push (pop lst -1) lst)
(5 1 2 3 4)
> (push (pop lst -1) lst)
(4 5 1 2 3)
> (push (pop lst -1) lst)
(3 4 5 1 2)
> (push (pop lst -1) lst)
(2 3 4 5 1)
> (push (pop lst -1) lst)
(1 2 3 4 5)
>

Kazimir Majorinc

#9
I have this in my library at http://www.instprog.com">www.instprog.com


(map (lambda()
          (letn ((old-function-name (first (args))))
                (set (sym (append "setq"(string old-function-name)))
                     (expand '(lambda-macro()
                                  (set (first (args))
                                       (apply old-function-name
                                              (map eval (args)))))
                                   'old-function-name))

                (set (sym (append "set" (string old-function-name)))
                     (expand '(lambda-macro()
                                   (set (eval (first (args)))
                                        (apply old-function-name
                                              (map eval
                                                  (cons (eval (first (args)))
                                                        (rest (args)))))))
                               'old-function-name))

                (set (sym (append "setf" (string old-function-name)))
                     (expand '(lambda-macro()
                                  (eval
                                    (letex((x (first (args))))
                                       '(setf x (apply old-function-name
                                                      (map eval (args)))))))
                               'old-function-name))))



     '( + - * / % add mul sub div mod append max min and or))


(set 'x '(1 2 3 4))
(setfappend x '(39))
(println x) ; => (1 2 3 4 39)

(setf x 3)
(setfmax x 6)
(setf+ x 4)
(println x) ;=> 10
(exit)


set and setq versions are also defined.
http://kazimirmajorinc.com/\">WWW site; http://kazimirmajorinc.blogspot.com\">blog.

TedWalther

#10
Quote from: "Lutz"
QuoteNope. It returns the item pushed.


Nope. It returns the list ;-)




So, what is the right way to do this?



(constant 'mc lambda-macro)
Cavemen in bearskins invaded the ivory towers of Artificial Intelligence.  Nine months later, they left with a baby named newLISP.  The women of the ivory towers wept and wailed.  \"Abomination!\" they cried.

Lutz

#11
The words 'lambda','fn' and 'lambda-macro', 'fn-macro' macro are not normal symbols/keywords and cannot be re-assigned. They mark a list as a special type of list (a lambda list). This is why:


(length (lambda )) => 0) ; not 1

; and

(first (lambda (x y z))) => (x y z)

Kazimir Majorinc

#12
Quote from: "TedWalther"
So, what is the right way to do this?



(constant 'mc lambda-macro)


This is what I used for some time:


(set 'macro
    (lambda-macro()
        (eval (append '(lambda-macro) (args)))))
http://kazimirmajorinc.com/\">WWW site; http://kazimirmajorinc.blogspot.com\">blog.

cormullion

#13
Nice code, guys... Interesting comparing the styles.



I was thinking that perhaps this extend would be a useful addition: taking perhaps an existing symbol and a list:


(define-macro (extend s lst)
   (set s (append (eval s) (eval lst))))
   
(set 'p (sequence 1 5))
(extend p (sequence 6 10))
p
;-> (1 2 3 4 5 6 7 8 9 10)


(pretty untested... )



It would also be neat if it created the symbol (like push) if necessary.

Tim Johnson

#14
This is turning out to be a great thread. Lots of ideas for a great list context.

tj
Programmer since 1987. Unix environment.