List context - performance

Pondering the philosophy behind the language
Locked
Tim Johnson
Posts: 253
Joined: Thu Oct 07, 2004 7:21 pm
Location: Palmer Alaska USA

List context - performance

Post by 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

Code: Select all

(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

Code: Select all

(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

Jeff
Posts: 604
Joined: Sat Apr 07, 2007 2:23 pm
Location: Ohio
Contact:

Post by Jeff »

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...

Artful code

TedWalther
Posts: 608
Joined: Mon Feb 05, 2007 1:04 am
Location: Abbotsford, BC
Contact:

Post by TedWalther »

Jeff wrote:You could always write a function that does (push item lst -1) and returns lst again.
Doesn't push return lst already?

cormullion
Posts: 2038
Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:

Post by cormullion »

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

Code: Select all

(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
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

would it be called 'adjoin' ?

Jeff
Posts: 604
Joined: Sat Apr 07, 2007 2:23 pm
Location: Ohio
Contact:

Post by Jeff »

TedWalther wrote: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.
Lutz wrote:would it be called 'adjoin' ?
Or nconc
Jeff
=====
Old programmers don't die. They just parse on...

Artful code

Tim Johnson
Posts: 253
Joined: Thu Oct 07, 2004 7:21 pm
Location: Palmer Alaska USA

Post by Tim Johnson »

Lutz wrote: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

Tim Johnson
Posts: 253
Joined: Thu Oct 07, 2004 7:21 pm
Location: Palmer Alaska USA

Post by Tim Johnson »

Following code is my starting point:

Code: Select all

(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:

Code: Select all

> (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")

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

Nope. It returns the item pushed.
Nope. It returns the list ;-)

Code: Select all

> (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:

Code: Select all

> (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
Posts: 388
Joined: Thu May 08, 2008 1:24 am
Location: Croatia
Contact:

Post by Kazimir Majorinc »

I have this in my library at www.instprog.com

Code: Select all

(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.

TedWalther
Posts: 608
Joined: Mon Feb 05, 2007 1:04 am
Location: Abbotsford, BC
Contact:

Post by TedWalther »

Lutz wrote:
Nope. It returns the item pushed.
Nope. It returns the list ;-)
So, what is the right way to do this?

Code: Select all

(constant 'mc lambda-macro)

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

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:

Code: Select all

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

; and

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

Kazimir Majorinc
Posts: 388
Joined: Thu May 08, 2008 1:24 am
Location: Croatia
Contact:

Post by Kazimir Majorinc »

TedWalther wrote: So, what is the right way to do this?

Code: Select all

(constant 'mc lambda-macro)
This is what I used for some time:

Code: Select all

(set 'macro
    (lambda-macro()
        (eval (append '(lambda-macro) (args)))))

cormullion
Posts: 2038
Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:

Post by cormullion »

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:

Code: Select all

(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
Posts: 253
Joined: Thu Oct 07, 2004 7:21 pm
Location: Palmer Alaska USA

Post by Tim Johnson »

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

Jeff
Posts: 604
Joined: Sat Apr 07, 2007 2:23 pm
Location: Ohio
Contact:

Post by Jeff »

Performance-wise, something like this would be simpler and faster:

Code: Select all

(define-macro (extend)
  (push (eval (args 1)) (eval (args 0)) -1))

(setf lst '(1 2))
(extend lst 3) ; => (1 2 3)
lst ; => (1 2 3)
(extend lst 4) ; => (1 2 3 4)
lst ; => (1 2 3 4)
Jeff
=====
Old programmers don't die. They just parse on...

Artful code

cormullion
Posts: 2038
Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:

Post by cormullion »

Code: Select all

(push (eval (args 1)) (eval (args 0)) -1)
Clever stuff! Looks simple, but only after someone else does it... :)

Tim Johnson
Posts: 253
Joined: Thu Oct 07, 2004 7:21 pm
Location: Palmer Alaska USA

Post by Tim Johnson »

Using the approach that I describe above, I wrote a series of vimscript
functions that initialize an object such as I've shown interest in and shown
an example of:

Code: Select all

" ---------------------------------------------------------------------------------------
"  Given the variable name typed in, expands to a general set statement
" --------------------------------------------------------------------------------------
function! NewlispQuickSet()
 	let wrd=expand("<cWORD>")
	exe "norm! bdwa(set '" . wrd . " )\<Left>"
endfunction
" -----------------------------------------------------------------------------
" Given the variable name typed in, expands to a global initializer
" expression containing an initializer function
" Example: foo => (set 'foo (List! "foo"))
" ----------------------------------------------------------------------------
function! NewlispInitGlobalObject(o)
 	let w=expand("<cWORD>")
	exe "norm! bdwa(set '" . w . "(" . a:o . "! \"" . w . "\" ))\<Left>\<Left>"
endfunction
" ----------------------------------------------------------------------------
" Given the variable name typed in, expands to a local initializer
" as would be contained in a let() initializer expression
" Example: foo => (foo (List! "foo"))
" ---------------------------------------------------------------------------
function! NewlispInitLocalObject(o)
 	let w=expand("<cWORD>")
	exe "norm! bdwa(" . w . "(" . a:o . "! \"" . w . "\" ))\<Left>\<Left>"
endfunction
" --------------------------------------------------------------------
Note: The last two functions expand to a particular coding style, so
if you have stumbled across this, make sure to read my posts in this thread.
Also, for you vimmers, these functions are in turn called from functions which
are agnostic to the programming language.
so if you call them directly, then you'll need to add "a" to get back into
insert mode at the right place.
Key mapping examples:

Code: Select all

inoremap <T-Space>      <Esc>:call StdInitializeVariable()<CR>a
inoremap <F2>l      <Esc>:call StdInitGlobalList()<CR>a
inoremap <F2>m      <Esc>:call StdInitLocalList()<CR>a
Note <T-Space> That is the vimscript notation for the "Super" modifier" following
by "Space"
Thanks again for this thread. I'm going to rip off a whole lot of the examples
submitted for my List! context.
cheers
tim

Locked