SKILL Q: Other looping constructs besides "foreach?"

E

Edward

Guest
I'm writing a few utilities to make my workflow go smoother, and I've
just started to think about refactoring a few functions that use
"foreach." Specifically, I'm looking for something like a "do-
until," a foreach that stops iterating a list once it finds the
element it's looking for. Because SKILL is a dialect of Lisp, I
could write a recursive list-searching function, but first I would
like to hear from anyone who is more familiar with SKILL's standard
command set. Maybe there is a command I missed that already does what
I want.

Thanks,

Edward
 
On Jun 20, 7:02 pm, Edward <edward.do...@gmail.com> wrote:
I'm writing a few utilities to make my workflow go smoother, and I've
just started to think about refactoring a few functions that use
"foreach." Specifically, I'm looking for something like a "do-
until,"
Like while() and unless()?

-Jay-
 
On Jun 21, 6:42 pm, jayl-n...@accelerant.net wrote:
On Jun 20, 7:02 pm, Edward <edward.do...@gmail.com> wrote:

I'm writing a few utilities to make my workflow go smoother, and I've
just started to think about refactoring a few functions that use
"foreach." Specifically, I'm looking for something like a "do-
until,"

Like while() and unless()?

-Jay-
Yes, while() is a good one, but I was looking for an iterative
selector, a keep-looking-until-you-find-this-and-and-then-stop
function. After perusing the SKILL reference and user-guide, I found
exists() and this is closer to what I wanted.

Thanks,

Edward
 
this is pretty easy with SKILL's powerful macro system.
How about the following? untested...


(defmacro do_until (test expr1 @rest others)
,expr1
,@others
(unless ,test
,expr1
,@others))


What value do you want the do_until to return? If you want it
to return the last expression of the body that was evalutated, or
perhaps
the first non-nil value of test the macro will be a little more
complicated
but not much more. E.g., the following will return the first non-nil
value
of test and repeat the given body until the test is non-nil.

(defmacro do_until (test expr1 @rest others)
(let ((var (gensym)))
,expr1
,@others
(unless (setq ,var ,test) ,expr1 ,@others)
,var))


Example.

(let ((x 1.1))
(do_until (x > 100)
(println x)
(x = 2*x)))




On Jun 21, 4:02 am, Edward <edward.do...@gmail.com> wrote:
I'm writing a few utilities to make my workflow go smoother, and I've
just started to think about refactoring a few functions that use
"foreach." Specifically, I'm looking for something like a "do-
until," a foreach that stops iterating a list once it finds the
element it's looking for. Because SKILL is a dialect of Lisp, I
could write a recursive list-searching function, but first I would
like to hear from anyone who is more familiar with SKILL's standard
command set. Maybe there is a command I missed that already does what
I want.

Thanks,

Edward
 
On Fri, 22 Jun 2007 21:29:19 -0000, Edward <edward.dodge@gmail.com> wrote:

On Jun 21, 6:42 pm, jayl-n...@accelerant.net wrote:
On Jun 20, 7:02 pm, Edward <edward.do...@gmail.com> wrote:

I'm writing a few utilities to make my workflow go smoother, and I've
just started to think about refactoring a few functions that use
"foreach." Specifically, I'm looking for something like a "do-
until,"

Like while() and unless()?

-Jay-

Yes, while() is a good one, but I was looking for an iterative
selector, a keep-looking-until-you-find-this-and-and-then-stop
function. After perusing the SKILL reference and user-guide, I found
exists() and this is closer to what I wanted.

Thanks,

Edward
There's exists(), as you said, and also member()/memq() which are effectively
specialized forms of exists(). Another possibility is forall() which is similar
to exists except the condition is the opposite - it keeps going while something
is true, and it only returns t if it made it through the whole list.

You can also do early jump-outs by using things like this:

prog(()
foreach(a '(1 2 3 4 5 6 7)
println(a)
when(a>4 return('break))
)
)

(the value in the return doesn't really matter - I just returned a symbol to
indicate the the prog was exited early).

Personally I don't like doing the above, but in some exceptional cases it's a
reasonable thing to do.

Regards,

Andrew.
--
Andrew Beckett
Senior Solution Architect
Cadence Design Systems, UK.
 
Jim,

These are definitely untested ;-(
You missed out the backquote, and there's no kind of looping in there. It's not
obvious to me how you intended them to work...

Even assuming you meant to put a `progn(...) around the code:

(defmacro do_until (test expr1 @rest others)
(let ((var (gensym)))
`(progn
,expr1
,@others
(unless (setq ,var ,test) ,expr1 ,@others)
,var)))

It still doesn't work properly - it just executes the body a maximum of twice.

Perhaps you also meant to have while (with a null on the condition) instead of
unless?

(defmacro do_until (test expr1 @rest others)
(let ((var (gensym)))
`(progn
,expr1
,@others
(while (null (setq ,var ,test)) ,expr1 ,@others)
,var)))

And there's no particular need to have expr1 and others separated:

(defmacro do_until (test @rest others)
(let ((var (gensym)))
`(progn
,@others
(while (null (setq ,var ,test)) ,@others)
,var)))

although I guess this gives a nasty error if you don't give enough args to
do_until, whereas the one with expr1 is clearer.

Regards,

Andrew.


On Wed, 27 Jun 2007 12:58:34 -0700, cadence <jimka@rdrop.com> wrote:

this is pretty easy with SKILL's powerful macro system.
How about the following? untested...


(defmacro do_until (test expr1 @rest others)
,expr1
,@others
(unless ,test
,expr1
,@others))


What value do you want the do_until to return? If you want it
to return the last expression of the body that was evalutated, or
perhaps
the first non-nil value of test the macro will be a little more
complicated
but not much more. E.g., the following will return the first non-nil
value
of test and repeat the given body until the test is non-nil.

(defmacro do_until (test expr1 @rest others)
(let ((var (gensym)))
,expr1
,@others
(unless (setq ,var ,test) ,expr1 ,@others)
,var))


Example.

(let ((x 1.1))
(do_until (x > 100)
(println x)
(x = 2*x)))




On Jun 21, 4:02 am, Edward <edward.do...@gmail.com> wrote:
I'm writing a few utilities to make my workflow go smoother, and I've
just started to think about refactoring a few functions that use
"foreach." Specifically, I'm looking for something like a "do-
until," a foreach that stops iterating a list once it finds the
element it's looking for. Because SKILL is a dialect of Lisp, I
could write a recursive list-searching function, but first I would
like to hear from anyone who is more familiar with SKILL's standard
command set. Maybe there is a command I missed that already does what
I want.

Thanks,

Edward

--
Andrew Beckett
Senior Solution Architect
Cadence Design Systems, UK.
 
hi andrew yes you're right. i wrote those before heading to bed.
And on my pillow i realized
some very obvious mistakes. thanks for correcting them for me.

yes, the point of having two variables expr1 and others is to hide the
degenerate
case that no expressions were given. It makes it clear that at least
one
expression is required and that others are optional. It could be
improved slightly:

(defmacro do_until (test expr1 @rest body)
,@body
(while (not ,test)
nil
,@body))

The nil, inserted in the while, assures that the body of the while is
never empty, thus allowing
a usage such as

x=42
(do_until (zerop (mod ++x 17)))


thanks again andrew for clearing it up, but i think you are loging on
too early in the
morning (grins).

-jim


On Jun 28, 1:50 am, Andrew Beckett <andr...@DcEaLdEeTnEcTe.HcIoSm>
wrote:
Jim,

These are definitely untested ;-(
You missed out the backquote, and there's no kind of looping in there. It's not
obvious to me how you intended them to work...

Even assuming you meant to put a `progn(...) around the code:

(defmacro do_until (test expr1 @rest others)
(let ((var (gensym)))
`(progn
,expr1
,@others
(unless (setq ,var ,test) ,expr1 ,@others)
,var)))

It still doesn't work properly - it just executes the body a maximum of twice.

Perhaps you also meant to have while (with a null on the condition) instead of
unless?

(defmacro do_until (test expr1 @rest others)
(let ((var (gensym)))
`(progn
,expr1
,@others
(while (null (setq ,var ,test)) ,expr1 ,@others)
,var)))

And there's no particular need to have expr1 and others separated:

(defmacro do_until (test @rest others)
(let ((var (gensym)))
`(progn
,@others
(while (null (setq ,var ,test)) ,@others)
,var)))

although I guess this gives a nasty error if you don't give enough args to
do_until, whereas the one with expr1 is clearer.

Regards,

Andrew.



On Wed, 27 Jun 2007 12:58:34 -0700, cadence <j...@rdrop.com> wrote:
this is pretty easy with SKILL's powerful macro system.
How about the following? untested...

(defmacro do_until (test expr1 @rest others)
,expr1
,@others
(unless ,test
,expr1
,@others))

What value do you want the do_until to return? If you want it
to return the last expression of the body that was evalutated, or
perhaps
the first non-nil value of test the macro will be a little more
complicated
but not much more. E.g., the following will return the first non-nil
value
of test and repeat the given body until the test is non-nil.

(defmacro do_until (test expr1 @rest others)
(let ((var (gensym)))
,expr1
,@others
(unless (setq ,var ,test) ,expr1 ,@others)
,var))

Example.

(let ((x 1.1))
(do_until (x > 100)
(println x)
(x = 2*x)))
 

Welcome to EDABoard.com

Sponsor

Back
Top