Is it possible to return an association list from a function? Here's a test:
(define (test)
(local (a b c)
(set 'a 1)
(set 'b 2)
(set 'c 3)
(set 'sum (+ a b c))
'(("a" a) ("b" b) ("c" c) ("sum" sum))
))
(println (lookup "sum" (test)))
I think this is a newbie question... :-)
Yes, a small change does it:
(define (test)
(letex (a 1 b 2 c 3)
(letex (sum (+ a b c))
'(("a" a) ("b" b) ("c" c) ("sum" sum)) )
) )
(test) -> (("a" 1) ("b" 2) ("c" 3) ("sum" 6))
Lutz
Thanks, Lutz. I think i get it - the symbols need expanding before their values are lost?
But I'd like to use the (local) construction, and avoid those two nested letexes which are too unintuitive for me to remember... :-) Can I use expand while building an assoc list?
(define (test)
(local (a b c)
(set 'a 1)
(set 'b 2)
(set 'c 3)
(set 'sum (+ a b c))
(expand (list a b c))))
will return (1 2 3).
Like this?
(define (test)
(letn (a 1 b 2 c 3 sum (+ a b c))
(expand '(("a" a) ("b" b) ("c" c) ("sum" sum)) 'a 'b 'c 'sum)))
(test) -> (("a" 1) ("b" 2) ("c" 3) ("sum" 6))
Lutz
yes, that looks better .... ;-)
thanks
PS quiet round here isn't it?
Lutz wrote:
(define (test)
(letex (a 1 b 2 c 3)
(letex (sum (+ a b c))
'(("a" a) ("b" b) ("c" c) ("sum" sum)) )
) )
(test) -> (("a" 1) ("b" 2) ("c" 3) ("sum" 6))
This makes me think - maybe we could create a new 'letexn' :-)
(define (test)
(letexn (a 1 b 2 c 3 sum (+ a b c))
'(("a" a) ("b" b) ("c" c) ("sum" sum)) ))
Fanda
Another solution:
(define (test)
(letn (a 1 b 2 c 3 sum (+ a b c))
(list (list "a" a) (list "b" b) (list "c" c) (list "sum" sum))))
Fanda
thanks Fanda. I think this is the one I shall use:
(define (test)
(local (a b c sum)
(set 'a 1 'b 2 'c 3 'sum (+ a b c))
(list (list "a" a) (list "b" b) (list "c" c) (list "sum" sum))))
(println (lookup "sum" (test)))
It reads nicely... ;-)
cormullion!
With the addition of the pair function:
(constant (global 'pair) (fn (lst)
(array-list (array (/ (length lst) 2) 2 lst))))
You can bum it even more:
(define (test)
(local (a b c sum)
(set 'a 1 'b 2 'c 3 'sum (+ a b c))
(pair (list "a" a "b" b "c" c "sum" sum))))
pair. Never leave home without it ;-)
m i c h a e l
Welcome back, mm. :-) But what does pair do? - why is it using arrays?
I've never really been away. Just went back to my more natural wallflower mode ;-)
pair was taken from the Code Snippets page on newLISP.org.
pair turns this: (1 2 3 4 5 6 7 8 9 10) into this: ((1 2) (3 4) (5 6) (7 8) (9 10)).
As to "why the arrays," you'll have to ask the original author about that one :-)
m i c h a e l
It looks like the Hand of Fanda...
Probably using arrays for speed...
It's one of those situations where you kind of want the functionality to be already there - you don't want to define other functions just to get your existing functions to work the way you want them to. But you have to draw the line somewhere. And besides, we're supposed to be bending the language to suit our application, so perhaps it's a good thing to do.
I am not sure, who made a 'pair' function, but lets guess... Lutz? ;-)
Be careful - pair is losing it's elements, if they are not even:
> (pair '(1 2 3 4))
((1 2) (3 4))
> (pair '(1 2 3))
((1 2))
I like group: (group lst [n] [keep-tail])
(define (group lst (n 2) (keep-tail true))
(set 'lst (map (lambda (i) (slice lst i n)) (sequence 0 (- (length lst) 1) n)))
(if (and (not keep-tail) (!= n (length (last lst))))
(pop lst -1))
lst)
> (group '(1 2 3 4))
((1 2) (3 4))
> (group '(1 2 3))
((1 2) (3))
> (group '(1 2 3 4 5 6 7 8) 3)
((1 2 3) (4 5 6) (7 8))
> (group '(1 2 3 4 5 6 7 8) 3 nil)
((1 2 3) (4 5 6))
Fanda
The 'array' function was used because it has pairing/grouping already built into it, and it can take a flat list for initialization:
(array 3 2) => ((nil nil) (nil nil) (nil nil))
; or with initialization
(array 3 2 '(1 2 3 4 5 6)) => ((1 2) (3 4) (5 6))
It also would work for more than 2 dimensions. Similar to Fanda's group function you could define:
(define (group lst (n 2))
(array-list (array (/ (length lst) n) n lst)))
Since version 9.0 the functions 'append, last, first, rest and slice' (and their implicit indexing forms) can also be used on arrays. This means that very often it is not necessary to convert the array back into a list using 'array-list'.
For shorter lists (rule of thumb: < 100 elements) arrays don't offer much of a speed advantage, but on longer lists and when accessing elements not in a sequential fashion, the speed advantage can be dramatic.
Lutz
Thanks Lutz. The idea was that I thought it would be a useful way to return a set of results from a function, by returning them in an association list. Speed isn't much of an issue, since there would be only 5 to 10 values to return. Ease of expression is more the thing - something that naturally flows out of the fingers once the hard work of defining the function body is completed, that doesn't require another piece of program code to achieve. That's why I'm currently leaning towards the (list (list approach.
Quote
Ease of expression is more the thing ... that doesn't require another piece of program code to achieve.
I wholeheartedly agree. Ease of expression and self sufficiency should always be the first priority, before efficiency considerations, when coding. Decisions in this area always have a subjective component, which is fine and how it should be.
Because of this I also reject 'standardized coding styles' or the notion that there is a 'right way' of doing things.
Much of the fun in programming stems from the freedom we can take to express (code) in our own individual way and a prgrammming language should allow this.
The best programmers are those who take the freedom to cultivate their own styles.
Lutz
Quote from: "Lutz"
Quote
Ease of expression is more the thing ... that doesn't require another piece of program code to achieve.
I wholeheartedly agree. Ease of expression and self sufficiency should always be the first priority, before efficiency considerations, when coding. Decisions in this area always have a subjective component, which is fine and how it should be.
Because of this I also reject 'standardized coding styles' or the notion that there is a 'right way' of doing things.
Much of the fun in programming stems from the freedom we can take to express (code) in our own individual way and a prgrammming language should allow this.
The best programmers are those who take the freedom to cultivate their own styles.
Lutz
Quote book material.
Yet another:
(define (zip) (transpose (args)))
(define (test)
(local (a b c sum)
(set 'a 1)
(set 'b 2)
(set 'c 3)
(set 'sum (+ a b c))
(zip '(a b c sum) (list a b c sum))))
> (test)
((a 1) (b 2) (c 3) (sum 6))
To understand zip's meaning, think about what happens to two separate rows of teeth as they pass through a zipper.
Cheers, --Rick
That's neat! And inline:
(transpose (list '(a b c sum) (list a b c sum)))
works for me, and is shorter than:
(list (list "a" a) (list "b" b) (list "c" c) (list "sum" sum))
thanks for all the ideas!
Very nice, rickyboy ... and works for n-way zips too:
(zip '(1 2 3) '(a b c) '(x y z)) => ((1 a x) (2 b y) (3 c z))
I will put this into the http://newlisp.org/index.cgi?page=Code_Snippets page
Lutz
Oops! You had better not give me credit for that. The idea and name of 'zip' is something taken from FP languages like Haskell or ML. The newlisp implementation of 'zip' I first saw in Fanda's function 'merge' in //http://www.intricatevisions.com/source/newlisp/list.lsp. When I saw Fanda's 'merge', I thought "Hey that's zip and a very pithy definition at that." So, I vote that you strike my name from the Snippets credit and stick Fanda's name there. :-) Cheers, --Rick
For an unspecified number of arguments:
(define-macro (test )
(let ((s (map (lambda (x) (list (sym x) (eval x))) (args))))
(append s (list (list 'sum (apply '+ (map (lambda (x) (x 1)) s)))))))
Line 2 gathers the arguments into an assoc list
Line 3 sums the second elements and sticks it on the end
the local variable s is used so arguments are only evaluated once
so
> (setq a 1)
1
> (setq b 2)
2
> (setq c 3)
3
> (test a b c)
((a 1) (b 2) (c 3) (sum 6))
>
Nigel
PS to keep the original intent of strings in the list use name:
(define-macro (test )
(let ((s (map (lambda (x) (list (name x) (eval x))) (args))))
(append s (list (list "sum" (apply '+ (map (lambda (x) (x 1)) s)))))))
gives
> (test a b c)
(("a" 1) ("b" 2) ("c" 3) ("sum" 6))
>
Quote from: "rickyboy"
Oops! You had better not give me credit for that. The idea and name of 'zip' is something taken from FP languages like Haskell or ML. The newlisp implementation of 'zip' I first saw in Fanda's function 'merge' in //http://www.intricatevisions.com/source/newlisp/list.lsp. When I saw Fanda's 'merge', I thought "Hey that's zip and a very pithy definition at that." So, I vote that you strike my name from the Snippets credit and stick Fanda's name there. :-) Cheers, --Rick
Rick, I am glad to see that you read my code :-)
Just to be clear on who gets the credit: I first saw zip-merge-dispose from Nigel Brown and named it 'merge':
//http://www.alh.net/newlisp/phpbb/viewtopic.php?p=4582
Quote
Here is a dispose that is just a wrapper around the builtin newLISP function transpose.
using args lets you accept any number of lists
viz
> (define (dispose) (transpose (args)))
(lambda () (transpose (args)))
> (dispose '(1 2 3) '(4 5 6))
((1 4) (2 5) (3 6))
> (dispose '(1 2 3) '(4 5 6) '(7 8 9))
((1 4 7) (2 5 8) (3 6 9))
> (setq m '(1 2 3 4 5 6 7))
(1 2 3 4 5 6 7)
> (setq n '(7 6 5 4 3 2 1))
(7 6 5 4 3 2 1)
> (dispose m n)
((1 7) (2 6) (3 5) (4 4) (5 3) (6 2) (7 1))
>
Nigel
So, credit goes to Nigel!
Fanda
PS: Code Snippets show old update time: last updated 2005-12-08
Quote from: "Fanda"
So, credit goes to Nigel!
I call it, if Nigel doesn't want it.
I'd completely forgotten dispose.
You can see from my contribution re test above I like using (args)
Nigel