dolist but getting more values at the same time
dolist but getting more values at the same time
Hello,
I need to read a list, but I want to get more than one value per loop cycle. This is an "abstract example":
(dolist ( (i j k) '(1 2 3 4 5 6 7 8 9) ) (println (i "-" j "-" k)))
Well, I could get something like:
1-2-3
4-5-6
7-8-9
In fact, at every loop I could "load" the variables with three values.
Is it possible with a specific function?
Thank you for your help!
(Hello to everyone, since it is some time I do not frequent this forum!)
I need to read a list, but I want to get more than one value per loop cycle. This is an "abstract example":
(dolist ( (i j k) '(1 2 3 4 5 6 7 8 9) ) (println (i "-" j "-" k)))
Well, I could get something like:
1-2-3
4-5-6
7-8-9
In fact, at every loop I could "load" the variables with three values.
Is it possible with a specific function?
Thank you for your help!
(Hello to everyone, since it is some time I do not frequent this forum!)
--
Re: dolist but getting more values at the same time
A code example :
And operation examples :
Sorry, I did not think of a break condition.
But, if the optional break expression is not necessary,
the following function could be used :
And examples :
Code: Select all
(define-macro (mvdolist)
(letex (_vars (args 0 0)
_vals (args 0 1)
_body (cons 'begin (1 (args))))
(local _vars
(dolist (_x (explode _vals (length '_vars)))
(bind (transpose (list '_vars _x)))
_body))))
Unless the optional break expression as the dolist function, [exp-break].> (mvdolist ( (i j k) '(1 2 3 4 5 6 7 8 9)) (println i "-" j "-" k))
1-2-3
4-5-6
7-8-9
9
> (mvdolist ( (i j k) (sequence 1 9) ) (println i "-" j "-" k))
1-2-3
4-5-6
7-8-9
9
> (mvdolist ( (i j k) (sequence 1 5) ) (println i "-" j "-" k))
1-2-3
4-5-nil
nil
>
Sorry, I did not think of a break condition.
But, if the optional break expression is not necessary,
the following function could be used :
Code: Select all
(define-macro (mvdolist)
(letex (_varlst (map list (args 0 0))
_vars (args 0 0)
_vals (args 0 1)
_flag (and (= 3 (length (args 0))) (args 0 2))
_body (cons 'begin (1 (args))))
(let _varlst
(dolist (_x (if _flag _vals (explode _vals (length '_vars))))
(bind (transpose (list '_vars _x)))
_body))))
> (mvdolist ( (i j k) '((1 2 3)(4 5 6)(7 8 9)) ) (println i "-" j "-" k))
(1 2 3)-(4 5 6)-(7 8 9)
(7 8 9)
> (mvdolist ( (i j k) '((1 2 3)(4 5 6)(7 8 9)) true) (println i "-" j "-" k))
1-2-3
4-5-6
7-8-9
9
> (mvdolist ( (i j k) (explode (sequence 1 9) 3) true) (println i "-" j "-" k))
1-2-3
4-5-6
7-8-9
9
> (mvdolist ( (i j k) (explode (sequence 1 9) 4) true) (println i "-" j "-" k))
1-2-3
5-6-7
9-nil-nil
nil
> (mvdolist ( (i j k) (explode (sequence 1 9) 2) true) (println i "-" j "-" k))
1-2-nil
3-4-nil
5-6-nil
7-8-nil
9-nil-nil
nil
> (mvdolist ( (i j k) '(1 2 3) true) (println i "-" j "-" k))
1-1-1
2-2-2
3-3-3
3
>
-
- Posts: 2038
- Joined: Tue Nov 29, 2005 8:28 pm
- Location: latiitude 50N longitude 3W
- Contact:
Re: dolist but getting more values at the same time
If one of Lutz' Laws is "Don't underrate an iterate...", then Cormullion's Corollary is "You don't always have to do lists with dolist."
Code: Select all
(set 'l (series 1 2 12))
;-> (1 2 4 8 16 32 64 128 256 512 1024 2048)
(map (fn (n) (apply add n)) (explode l 3))
;-> (7 56 448 3584)
(dolist (n (explode l 3))
(println (apply add n)))
;->
7
56
448
3584
; the old banger...
(do-while l
(println (apply add (list (pop l) (pop l) (pop l)))))
;-> 7
56
448
3584
Re: dolist but getting more values at the same time
This is interesting.If one of Lutz' Laws is "Don't underrate an iterate...", then Cormullion's Corollary is "You don't always have to do lists with dolist."
I hope to read all words of Lutz' Laws.
Please teach me this sentence or url(?).
What is the subject that means this sentence ?
For instance, readability or speed, or philosophy , etc.
By the way,
Code: Select all
> (map (fn (x) (println (x 0) "-" (x 1) "-" (x 2))) (explode (sequence 1 9) 3))
1-2-3
4-5-6
7-8-9
(3 6 9)
> (map (curry apply (fn (i j k) (println i "-" j "-" k))) (explode (sequence 1 9) 3))
1-2-3
4-5-6
7-8-9
(3 6 9)
>
I like the second example.
Then, I wrote the following macro.
Code: Select all
(define-macro (map-mv)
;(map-mv exp-functor nested-list)
(letex (_func (args 0)
_vals (args 1))
(map (curry apply _func) _vals)))
> (map-mv (fn (i j k) (println i "-" j "-" k)) (explode (sequence 1 9) 3))
1-2-3
4-5-6
7-8-9
(3 6 9)
> (map-mv pow '((2 1) (2 2) (2 3)))
(2 4 8)
>
Thank you for advice, cormullion.
-
- Posts: 2038
- Joined: Tue Nov 29, 2005 8:28 pm
- Location: latiitude 50N longitude 3W
- Contact:
Re: dolist but getting more values at the same time
Don't worry I'm just being silly. What I'm saying is that there are always alternative ways of doing things. Lutz has sometimes observed that iteration is sometimes as good or better than recursion... And every time you type dolist you can ask yourself whether there are alternatives... That's all! :)
Re: dolist but getting more values at the same time
Nice example guys! Thank you!
Everyday you teach me something more!
I know very well imperative languages, but everyday I discover how "big" (I can say "deep") are functional languages.
Thank you.
Everyday you teach me something more!
I know very well imperative languages, but everyday I discover how "big" (I can say "deep") are functional languages.
Thank you.
--
Re: dolist but getting more values at the same time
Just today I was needing a multi valued dolist and it was great to find a pointer towards a more elegant solution, that I currently have.
In my case I'd need another variant of dolist with values being supplied in context, so it would return something like
I've come up with this "solution"
I'm sure it can be improved, e.g. by storing length of _vals somewhere.
In my case I'd need another variant of dolist with values being supplied in context, so it would return something like
Code: Select all
nil 1 2
1 2 3
2 3 4
3 4 5
4 5 6
6 7 8
7 8 9
8 9 nil
Code: Select all
(define-macro (mvdolist)
(letex (_vars (args 0 0)
_vals (args 0 1)
_body (cons 'begin (1 (args))))
(local _vars
(for (_x 0 (- (length _vals) 1))
(bind (transpose (list '_vars
(list
(if (= _x 0)
nil
(_vals (- _x 1)))
(_vals _x)
(if (= _x (- (length _vals) 1))
nil
(_vals (+ _x 1)))))))
_body))))
-
- Posts: 2038
- Joined: Tue Nov 29, 2005 8:28 pm
- Location: latiitude 50N longitude 3W
- Contact:
Re: dolist but getting more values at the same time
Hi Kirill, your solution is impressive!
I confess that I would probably try to avoid such a solution, because I find it a bit too advanced. I would go for a more basic approach, starting with trying to generate suitable list indices on the fly:
Your solution is much more Lispy.
I confess that I would probably try to avoid such a solution, because I find it a bit too advanced. I would go for a more basic approach, starting with trying to generate suitable list indices on the fly:
Code: Select all
(define (C:C)
(if (nil? a)
(set 'a 0)
(inc a))
(list a (+ a 1) (+ a 2)))
(set 'L (sequence 100 120))
(select L (C))
;-> (100 101 102)
(select L (C))
;-> (101 102 103)
(select L (C))
;-> (102 103 104)
Re: dolist but getting more values at the same time
The issue appeared as I wanted to automatically create the menu on my updated web page http://km.krot.org/. The menu is defined in terms of a nested list data structure and in order to expand one item I need to know if the previous item in the list is the page user is currently viewing, as you may see by going to http://km.krot.org/english.
And the page structure is defined like this:
And the page structure is defined like this:
Code: Select all
(context 'pages)
(setq pages:pages '(
("/index" "Velkommen")
("/archive2010" "Arkiv")
; ("/archive" "Arkiv")
; (
; ("/archive2010" "Arkiv 2006–2010")
; )
("/code" "Programkode")
("/english" "<strong>English</strong>")
(
("http://www.linkedin.com/in/kmiazin/en" "LinkedIn profile")
)
("mailto:km@krot.org" "✉ km@krot.org")
; ("http://validator.w3.org/check?uri=referer" ".")
))
Re: dolist but getting more values at the same time
I'm with cormullion. I don't know if macros are necessary.
Code: Select all
newLISP v.10.3.3 on Win32 IPv4/6, execute 'newlisp -h' for more info.
> [cmd]
(define (make-sandwich bread meat)
(cons bread (push bread meat -1)))
(define (generate-moving-window size xs)
(map (lambda (i) (slice xs i size)) (sequence 0 (- (length xs) size))))
[/cmd]
> (generate-moving-window 3 (make-sandwich nil (sequence 1 9)))
((nil 1 2) (1 2 3) (2 3 4) (3 4 5) (4 5 6) (5 6 7) (6 7 8) (7 8 9) (8 9 nil))
(λx. x x) (λx. x x)
Re: dolist but getting more values at the same time
Addendum. Change in code for readability.
Before:
After (and more "newlispier", hehehe -- see Lutz, I'm learning):
Another note also -- and this is for the newer newLISP users -- making sandwiches is not ultimately destructive. :-)
Before:
Code: Select all
(define (generate-moving-window size xs)
(map (lambda (i) (slice xs i size)) (sequence 0 (- (length xs) size))))
Code: Select all
(define (generate-moving-window size xs)
(map (fn (i) (i size xs)) (sequence 0 (- (length xs) size))))
Code: Select all
newLISP v.10.3.3 on Win32 IPv4/6, execute 'newlisp -h' for more info.
> (define (make-sandwich bread meat) (cons bread (push bread meat -1)))
> (define L '(1 2 3))
> (make-sandwich nil L)
(nil 1 2 3 nil)
> L
(1 2 3)
> ;; Yup. L is still unchanged.
(λx. x x) (λx. x x)
Re: dolist but getting more values at the same time
Some thoughts:
- Since 10.3.0 you don't need the [cmd], [/cmd] tags anymore. Just hit enter at the prompt, then enter you multiple code lines. When entering any empty line, you get out of multiline mode and the whole thing gets evaluated.
See here: http://www.newlisp.org/downloads/newlis ... .html#REPL
- for the moving window have you tried using explode?
Ps: regarding your question in your other post here:
http://newlispfanclub.alh.net/forum/vie ... 608#p19608
I am not lmf :), and I don't think there is one on this board. Perhaps that person is on this forum, but with a different handle. Also the link is
http://lmf-ramblings.blogspot.com
not
http://lmf-ramlbings.blogspot.com <- switched "bl"
- Since 10.3.0 you don't need the [cmd], [/cmd] tags anymore. Just hit enter at the prompt, then enter you multiple code lines. When entering any empty line, you get out of multiline mode and the whole thing gets evaluated.
See here: http://www.newlisp.org/downloads/newlis ... .html#REPL
- for the moving window have you tried using explode?
Code: Select all
> (dolist (item (explode (sequence 1 9) 3)) (println "-> " item))
-> (1 2 3)
-> (4 5 6)
-> (7 8 9)
Ps: regarding your question in your other post here:
http://newlispfanclub.alh.net/forum/vie ... 608#p19608
I am not lmf :), and I don't think there is one on this board. Perhaps that person is on this forum, but with a different handle. Also the link is
http://lmf-ramblings.blogspot.com
not
http://lmf-ramlbings.blogspot.com <- switched "bl"
Re: dolist but getting more values at the same time
Ah, very cool! Thanks!Lutz wrote:Come on, rickyboy! [cmd] is so yesterday! Here's how you do it:
RTFM: http://www.newlisp.org/downloads/newlis ... .html#REPL
Well, when the "window size" is, say, 3, can explode shift by 1, instead of 3 as in your example above? The application generate-moving-window is shifting by 1 with a "window size" of 3.Lutz wrote: - for the moving window have you tried using explode?
Code: Select all
> (dolist (item (explode (sequence 1 9) 3)) (println "-> " item)) -> (1 2 3) -> (4 5 6) -> (7 8 9)
Yes, I knew that it was not you. :) I wonder who it is though. I'd vote we torture Kazimir until he tells us who it is, but from the looks of him, I think he could throttle us all at once.Lutz wrote:I am not lmf :), I never was lmf, and I'm not planning to be lmf. I don't where you get these crazy ideas, rickyboy.
I know I would lose in a fight with him, so I'm not going there. :)
(λx. x x) (λx. x x)
Re: dolist but getting more values at the same time
Thanks all! I liked make-sandwich and generate-moving-window very much. The solution was really to add a nil to the start and end of the list. :) But to me it also was very helpful to "explore" the language by experimenting with macros.
-
- Posts: 608
- Joined: Mon Feb 05, 2007 1:04 am
- Location: Abbotsford, BC
- Contact:
Re: dolist but getting more values at the same time
Here is my solution:
The code gives you your moving window. It also lets you access the original list, in case your code needs to modify the original list. And it doesn't make duplicates of the original list, so should be more efficient.
Code: Select all
(setq lst '(a b c d e f g 1 2 3 4 5))
(dotimes (i (- (length lst) 2))
(do-something (i 3 lst)))
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.
Re: dolist but getting more values at the same time
This is how you could build generators for different window sizes and shifts. The generator sees the list as a circle and can go around if required.
shift is negative for rotating left, positive for rotating right.
Code: Select all
(define (make-window-generator size shift thelist)
(expand (fn () (0 size (rotate 'thelist shift))) 'size 'shift 'thelist))
; or alternative syntax of expand uppercasing the vars to expand
(define (make-window-generator Size Shift Thelist)
(expand (fn () (0 Size (rotate 'Thelist Shift)))))
(define gen (make-window-generator 3 -1 (sequence 0 9)))
(gen) => (1 2 3)
(gen) => (2 3 4)
(gen) => (3 4 5)
Re: dolist but getting more values at the same time
This concern is not practically an issue with the function generate-moving-window. According to the manual at the section entitled Passing Data By Reference -- and this also bears out with a little testing -- if the list you pass your function is not large, "the speed difference between reference and value passing is negligible"; if your list is large enough to notice the copy, the manual recommends to pass that list by reference: "Strings and lists, which are packed in a namespace using default functors, are passed automatically by reference."TedWalther wrote:And it doesn't make duplicates of the original list, so should be more efficient.
While I prefer that method, another way to avoid copying a big list in calling generate-moving-window is to change its definition from a lambda to a lambda-macro (and an accompanying letex, of course).
Well, I don't know what to say to this, except: "Knock yourself out, brother!" :) I'm a functional programmer; so my whole outlook on programming is based on NOT doing that. ;)TedWalther wrote:It also lets you access the original list, in case your code needs to modify the original list.
(λx. x x) (λx. x x)
-
- Posts: 58
- Joined: Sat Jun 10, 2006 5:34 am
Re: dolist but getting more values at the same time
I enjoy using the int-reduce option in apply.
When int-reduce is 2, the behavior is like fold or reduce; when it's larger than 2, it's even more fun.
When int-reduce is 2, the behavior is like fold or reduce; when it's larger than 2, it's even more fun.
Code: Select all
> (apply (fn(_ a b c)(println a b c)) (cons nil (sequence 1 9)) 4)
123
456
789