Re: mapeach
Hi Erik, I came across a cute little Common Lisp macro, mapeach http://malisper.me/2015/06/14/mapeach/. Naturally, I wanted it to play with it in PicoLisp. The most straightforward translation (for me) of the code in the post was: [de mapeach E# expression (let [(@Var @List . @Body) E] (macro (mapcar '((@Var) . @Body) @List ] Yes, that's fine. An alternative could be (de mapeach Args (mapcar (cons (cons (car Args)) (cddr Args)) (eval (cadr Args)) ) ) The 'cons'es are a little less expensive than the full macro. What are some other ways this could be written? I'm thinking it might be in the spirit of do*, as defined in the FAQ A way in the spirit of do* would be (de mapeach Args (mapcar '((E) (bind (car Args) (set (car Args) E) (run (cddr Args)) ) ) (eval (cadr Args)) ) ) This is a bit longer, but needs no consing at all. It works great for single variable expressions. : (mapeach N (1 2 3) (* N N)) - (1 4 9) Multiple vars will make it angry (return NIL). That's right. But if we define this syntax for multiple variables: (mapeach (X Y) '(a b c) '(d e f) (foo ... we can write (de mapeach Args (let Vars (pop 'Args) (apply mapcar (mapcar eval (cut (length Vars) 'Args)) (cons Vars Args) ) ) ) : (mapeach (X Y) (1 2 3) (4 5 6) (* X Y) ) - (4 10 18) ♪♫ Alex -- UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe
Re: mapeach
Alex, Thanks for the write-up! It's fun to dissect the different versions with 'debug' and mess around at the repl. An alternative could be (de mapeach Args (mapcar (cons (cons (car Args)) (cddr Args)) (eval (cadr Args)) ) ) The 'cons'es are a little less expensive than the full macro. Yes, makes sense. If I understand correctly, you're explicitly stating what my call to 'macro' eventually builds, but by skipping 'macro' you bypass the associated calls to 'pat?', 'fill', and 'run'. A way in the spirit of do* would be (de mapeach Args (mapcar '((E) (bind (car Args) (set (car Args) E) (run (cddr Args)) ) ) (eval (cadr Args)) ) ) This is a bit longer, but needs no consing at all. Awesome! I'm starting to grasp the 'bind', 'set', 'run' combo. This style makes a lot more sense now that I see it with a simpler function. I'm not a fluent 'do*'er. That's right. But if we define this syntax for multiple variables: (mapeach (X Y) '(a b c) '(d e f) (foo ... we can write (de mapeach Args (let Vars (pop 'Args) (apply mapcar (mapcar eval (cut (length Vars) 'Args)) (cons Vars Args) ) ) ) : (mapeach (X Y) (1 2 3) (4 5 6) (* X Y) ) - (4 10 18) Now you're just showing off :) Seriously cool, though.