On Thu, 10 May 2018 15:02:39 -0000 Michael Jones <[email protected]>
wrote:
>
> Maybe the central issue here has been lost because of the confusion between
> English words and the keywords of various languages. Let's be explicit: *a
> controlled looping construct may test the control condition before or after
> the iterated body of code. Go's 'for' tests before and and Go does not
> provide keyword means to specify the test happen after.*
>
> Not a crisis, everyone works around this, but, the workaround is a
> workaround. Language shapes thought. Languages that express test-after in
> their vocabulary embrace code and data structuring that depend on it.
> People who know such languages (such as C and others) will miss it. In 800
> AD Charlemagne said, "To have a second language is to have a second soul."
> Same for computer languages.
Rather than add simple syntatic sugar like "while" or "until",
it would make more sense to add a more powrrful & generalized
loop syntax.
Motivating example:
If you want to iterate through two slices at the same rate,
the "for" syntax doesn't generalize well. You have to do
for i, v := range slice1 {
if i >= len(slice2) { break; }
u := slice2[i]
....
}
This loses the similarity in the way v & u take successive
values from slice1 and slice2. Basically Go's for takes the
first step from "for i := 0; i < N; i++ { ... }" but then
stops.
A generalized loop can clearly bring out the similarity:
Example1:
loop for v := range slice1
for u := range slice2 {
...
}
This iterates through both slices and exits when either range
is exhausted.
It can be more powerful by adding filtering, value generation
and exit tests as loop phrases.
Example2:
loop for v := range slice
while v != 10 {
...
}
This ends as soon as v becomes 10.
Example3:
loop for v := range slice
until v != 10 {
...
}
Here the "until" test is done at the end of the loop (so the
body will be executed with v == 10 *once* but not for any
further values from slice).
Example4:
loop for x := range slice
for y := 2*iota+1 // y takes values 1, 3, 5, ...
...
}
Here an expression around Go's wonderful "iota" is used to
generate successive values. The loop ends once the slice
range is exhausted.
Example5:
loop for x := 2*iota+1 // x takes values 1, 3, 5, ...
if IsPrime(x)
while x < 100 {
...
}
Here the loop body is executed for only prime valued x and terminates
when x becomes > 100.
"range slice" in effect is a generator. In a sense so is
"iota". If we allow use of a generator function in a loop
phrase, things get more interesting.
Example6:
// primegen returns a prime generator function
func primegen() func() int {
p := 2
return func() int {
for {
q := p
if p == 2 { p += 1} else { p += 2 }
if IsPrime(q) { return q }
}
}
}
prime := primegen()
loop for x := prime()
for y := iota
while y < 100 {
fmt.Println(x)
}
Here primegen() returns a new function that returns successive
primes every time it is called. The loop prints out first 100
primes.
This generalized loop should translate in a straightforward
way to go1 style "for" loop code.
Credit: Common Lisp's LOOP macro.
--
You received this message because you are subscribed to the Google Groups
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.