Tough (for me at least) macro question

For the Compleat Fan
Locked
gcanyon
Posts: 31
Joined: Mon Sep 18, 2006 7:58 am

Tough (for me at least) macro question

Post by gcanyon »

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

Code: Select all

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:

Code: Select all

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:

Code: Select all

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:

Code: Select all

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

Post by Lutz »

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
Last edited by Lutz on Thu Sep 21, 2006 5:23 pm, edited 1 time in total.

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

Post by cormullion »

I would do one of these - more idiomatic perhaps?

Code: Select all

(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
Posts: 31
Joined: Mon Sep 18, 2006 7:58 am

Post by gcanyon »

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

Post by 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' ;)

gcanyon
Posts: 31
Joined: Mon Sep 18, 2006 7:58 am

Post by gcanyon »

Lutz wrote: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
Posts: 31
Joined: Mon Sep 18, 2006 7:58 am

Post by gcanyon »

cormullion wrote:I would do one of these - more idiomatic perhaps?

Code: Select all

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

Post by Lutz »

Code: Select all

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

Code: Select all

(for (n 1 10) ...)
Lutz

Dmi
Posts: 408
Joined: Sat Jun 04, 2005 4:16 pm
Location: Russia
Contact:

Post by Dmi »

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

Code: Select all

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

Post by Lutz »

There are 2 possibilities.

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

Code: Select all

(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

Code: Select all

(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
Last edited by Lutz on Mon Sep 25, 2006 3:53 pm, edited 2 times in total.

Dmi
Posts: 408
Joined: Sat Jun 04, 2005 4:16 pm
Location: Russia
Contact:

Post by Dmi »

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

Locked