Tough (for me at least) macro question

Started by gcanyon, September 21, 2006, 09:05:43 AM

Previous topic - Next topic

gcanyon

In my experience with other languages I'm used to being able to do this:


repeat with i = 1 to 10
  #do step a
  if i = 5 then next repeat
  #do step b
end repeat


This means that for i = 1 2 3 4 6 7 8 9 10 the code does both step a and step b. For i = 5, the code only does step a, and then skips on to i = 6.



First question: is there something in newLISP to do this? I didn't see it in the documentation. If there is then ignore the rest of this message. ;-)



If there isn't, I think I see how to do this in a macro. It would take the above and change it to something like:


repeat with i = 1 to 10
  #do step a
  if not (i = 5) then #do step b
end repeat


That seems do-able.



But what if the code looks more like this:


repeat with i = 1 to 10
  #do step a
  if i > 3 then
    #do step b
    if i < 8 then
      #do step c
      if i = 5 then next repeat
      #do step d
    end if
    #do step e
  end if
  #do step f
end repeat


My guess is that to write this as a macro, I'd have to take the code handed to the macro and walk through the tree looking for the nextRepeat command, keeping track of every repeat and if, and then unroll it as necessary to reassemble into something like:


repeat with i = 1 to 10
  #do step a
  if i > 3 then
    #do step b
    if i < 8 then
      #do step c
      if not (i = 5) then #do step d
    end if
    if not (i = 5) then #do step e
  end if
  if not (i = 5) then #do step f
end repeat


That seems like it would be hard to write in a way that would handle all cases. Am I wrong?

Lutz

#1
Yes, there is no 'continue' or 'repeat next' in newLISP loops. Over time you get acustomed to program in a functional style, using  'if', 'cond' etc. to control the flow.



All loop constructs in newLISP like 'dotimes', 'for' and 'dolist' can have a break expression to leave the loop early. Then there is 'catch'and 'throw', which also can be used to change the normal program flow.



I would not suggest to write a macro implementing  a 'continue' or 'break' but rather suggest to get accustomed to a more functional style of programming. It feels clumsy at first coming from other languages, but then you get accustomed to formulate solutions in a different way and will not miss anything.



Lutz

cormullion

#2
I would do one of these - more idiomatic perhaps?


(dolist (n (sequence 1 10))
(println n " step a")
(unless (= n 5)
(println n " step b")))


(dolist (n (sequence 1 10))
(and
(println n "step a")
(!= n 5)
(println n "step b")))

gcanyon

#3
Quote from: "Lutz"Yes, there is now 'continue' or 'repeat next' in newLISP loops. Over time you get acustomed to program in a functional style, using  'if', 'cond' etc. to control the flow.



All loop constructs in newLISP like 'dotimes', 'for' and 'dolist' can have a break expression to leave the loop early. Then there is 'catch'and 'throw', which also can be used to change the normal program flow.



I would not suggest to write a macro implementing  a 'continue' or 'break' but rather suggest to get accustomed to a more functional style of programming. It feels clumsy at first coming from other languages, but then you get accustomed to formulate solutions in a different way and will not miss anything.



Lutz


Believe me, I have no interest in trying to subvert newLISP's functional nature. Rather newLISP's functional nature is why I'm here in the first place ;-)



I don't see continue in the documentation. How do I use it?



thanks,



Geoff

Lutz

#4
Oops, I meant 'no' continue, not 'now' continue, I corrected my previous post



Lutz



ps: I am not a native English speaker, so sometimes I get 'phonetic' ;)

gcanyon

#5
Quote from: "Lutz"Oops, I meant 'no' continue, not 'now' continue, I corrected my previous post



Lutz



ps: I am not a native English speaker, so sometimes I get 'phonetic' ;)


This time through, I saw your edited post first. I saw "there is no continue" and said, "wait a second, didn't that say "now?" I wondered how I could have misread until I saw the quote in my post, then I realized what had happened and laughed.



Thanks for the clarification.

gcanyon

#6
Quote from: "cormullion"I would do one of these - more idiomatic perhaps?


(dolist (n (sequence 1 10))
(println n " step a")
(unless (= n 5)
(println n " step b")))


(dolist (n (sequence 1 10))
(and
(println n "step a")
(!= n 5)
(println n "step b")))


Both of these look like good solutions, thanks.

Lutz

#7
(dolist (n (sequence 1 10)) ...)

very descriptive but also wasting CPU cycles and memory, because the list: (1 2 3 4 5 6 7 8 9 10) has to be created first. Better:


(for (n 1 10) ...)

Lutz

Dmi

#8
Quote from: "Lutz"
I would not suggest to write a macro implementing  a 'continue' or 'break' but rather suggest to get accustomed to a more functional style of programming.

Lutz! Can you show some example of functional analog for
for(i=0;i<100;i++){if (fun(i)) break;}
...or just a link to a sample. And even not exactly in newLISP - possible, in CL.



I can't realize how to reorganize the code for that.



Nevertheless, with the catch/throw the macro seems to be redundant...
WBR, Dmi

Lutz

#9
There are 2 possibilities.



(1) All loop constructs 'for', 'dotimes' and 'dolist' in newLISP can take a break condition:


(for i 0 99 1 (fun x))
    (println i)
)


The loop will be left as soon as the break condition (fun x) is 'true' or any other value not 'nil'. The return value of the loop function will be the return value of the break condition. There are other examples in the manual for 'dotimes' and 'dolist'



(2) You can use catch and throw


(catch
  (for (i 0 9)
      (if (= i 5) (throw "The End"))
      (print i " ")))

      ; will output

      0 1 2 3 4
      ; and the return value will be
      => ; "The End"


The 'catch' and 'throw' method is more flexible than the break expression in the first method, because you could have statements before and after the 'throw'.



On the other side the first method makes tighter code.



Lutz



ps: corrected the first example, had forgotten the step parameter, necessary when having break condition

Dmi

#10
Yeah! I forgot about a break condition! But I remember now that it was introduced some time ago.



It is sufficient of course. Thanx.
WBR, Dmi