Range over int

12,754 views
Skip to first unread message

Cyril Oblikov

unread,
Jan 19, 2012, 5:49:37 AM1/19/12
to golan...@googlegroups.com
Hi, guys. Sorry if it was already discussed.

Why isn't this code correct?

var N int = ...
for i := range N {
    doSmth(i)
}

In my opinion it looks much simpler than:

var N int = ...
for i := 0; i < N; i++ {
    doSmth(i)
}

Volker Dobler

unread,
Jan 19, 2012, 11:14:46 AM1/19/12
to golang-nuts
The "why not correct" can be answered very simple:
The spec doesn't allow it.
See http://golang.org/doc/go_spec.html#RangeClause

The question why the spec doesn't allow it is more
complex. It could be allowed I think, but the argument
"looks much simpler" might not convince e.g. a
programmer with a strong C background who thinks
that for i:=0;i<N;i++ looks way more natural and clear.
I think there is just no real need.

Volker

Ronnie Howell

unread,
Jan 19, 2012, 11:29:33 AM1/19/12
to golan...@googlegroups.com
Go does allow the range operator in this fashion, it's a matter of syntax in this case.  To get this to work you would need to use the following:
N := []int{...}
for index,element := range N {
  doSomethingWithIndex(index)
 doSomethingWithElement(element)

Cyril Oblikov

unread,
Jan 19, 2012, 12:05:50 PM1/19/12
to golan...@googlegroups.com
четверг, 19 января 2012 г. 19:14:46 UTC+3 пользователь Volker Dobler написал:
The question why the spec doesn't allow it is more
complex.  It could be allowed I think, but the argument
"looks much simpler" might not convince e.g. a
programmer with a strong C background who thinks
that for i:=0;i<N;i++ looks way more natural and clear.  

Maybe, but a programmer with strong Python background probably would prefer range :)
As far as I can see this feature is obvious enough and will not mislead anyone. 

Paul Borman

unread,
Jan 19, 2012, 12:32:35 PM1/19/12
to golan...@googlegroups.com
The two forms are not interchangeable.

for i := 0; i < 5; i++ {
   println(i)
   i = 5
}

(prints one line)

and

for i := range 5 {
    println(i)
    i = 5
}

would likely do different things.  I would assume the latter would work like:

for i := range make([]int, 5) {
    println(i)
    i = 5
}

(prints 5 lines)

I do admit this would be nice, but what about ranging from 1 to N instead of 0 to N, or ranging from -5 to 5?  You would end up with something like

for i := range [ start, stop] {
}

where range N is a shorthand for range [0, N-1] unless you assume range [1,5] gives you 1,2,3,4.  You might as well go full on sets so you can say

range [-2...2] ->  -2, -1, 0, 1, 2
range [0...3) -> 0, 1, 2
range [1, 3, 5...7] -> 1, 3, 5, 6, 7
range (0...3) -> 1, 2
range (0, 3) -> nothing

I think the argument would be made that you can already do all of these things with the existing specification.  So while I agree range N would simplify some code (and I have even typed it a few times), I think it would open up more questions.  Currently you can only range on things that can produce a set of values.  From that viewpoint range N would simply degenerate down to N.

    -Paul

Steven Blenkinsop

unread,
Jan 19, 2012, 12:37:14 PM1/19/12
to golan...@googlegroups.com, golan...@googlegroups.com
The traditional for clause is more flexible as it can define upper and lower bounds, a step, or even more complex   iteration behaviours. Ranging over an int provides only 0 →n - 1, which can easily be expressed using the traditional for clause, and very often can be replaced with a range over a slice. So, in terms of gain in expressive power, this feature doesn't seem like it would pull its weight. It's not about whether it's obvious, you still have to specify it.

Dmitry Vyukov

unread,
Jan 19, 2012, 12:38:36 PM1/19/12
to Paul Borman, golan...@googlegroups.com
2012/1/19 Paul Borman <bor...@google.com>

Dmitry Vyukov

unread,
Jan 19, 2012, 12:39:43 PM1/19/12
to Paul Borman, golan...@googlegroups.com
2012/1/19 Paul Borman <bor...@google.com>

The two forms are not interchangeable.

for i := 0; i < 5; i++ {
   println(i)
   i = 5
}

(prints one line)

and

for i := range 5 {
    println(i)
    i = 5
}

would likely do different things.  I would assume the latter would work like:

for i := range make([]int, 5) {
    println(i)
    i = 5
}


for i := range [10] struct{}{} {
    ...
}

:)

Brad Fitzpatrick

unread,
Jan 19, 2012, 12:43:28 PM1/19/12
to Dmitry Vyukov, Paul Borman, golan...@googlegroups.com
On Thu, Jan 19, 2012 at 9:39 AM, Dmitry Vyukov <dvy...@google.com> wrote:
2012/1/19 Paul Borman <bor...@google.com>
The two forms are not interchangeable.

for i := 0; i < 5; i++ {
   println(i)
   i = 5
}

(prints one line)

and

for i := range 5 {
    println(i)
    i = 5
}

would likely do different things.  I would assume the latter would work like:

for i := range make([]int, 5) {
    println(i)
    i = 5
}


for i := range [10] struct{}{} {
    ...
}

:)

You're a sick man, Dmitry.

Sebastien Binet

unread,
Jan 19, 2012, 12:45:58 PM1/19/12
to Cyril Oblikov, golan...@googlegroups.com

well, it is also rather easy to create an 'itertools' package with a Range
function returning a slice with the data, and an IRange function
returning a channel to the data (when the slice begins to be too big)

package itertools

func Range(args ...int) []int {
nargs := len(args)
start, stop, stride := 0, 0, 0
switch nargs {
case 1:
start = 0
stop = args[0]
stride= 1
case 2:
start = args[0]
stop = args[1]
stride= 1
case 3:
start = args[0]
stop = args[1]
stride= args[2]
default:
panic("boo")
}
out := []int{}
for i := start; i < stop; i += stride {
out = append(out, i)
}
return out
}
// EOF //


then:
for i := range itertools.Range(10) {
fmt.Println(i)
}

-s

Dmitry Vyukov

unread,
Jan 19, 2012, 12:46:57 PM1/19/12
to Brad Fitzpatrick, Paul Borman, golan...@googlegroups.com
Is it sickness? Go does not allow me to show the real sickness. It was a way more funny with C++ templates.

minux

unread,
Jan 19, 2012, 12:47:36 PM1/19/12
to Dmitry Vyukov, golan...@googlegroups.com

2012/1/20 Dmitry Vyukov <dvy...@google.com>

for i := range [10] struct{}{} {
    ...
}

:)
The magical 'struct {}'! This kind of trick might be worth mention in effective_go
or go-wiki? Or this is considered not that good coding practice?

Dmitry Vyukov

unread,
Jan 19, 2012, 12:49:22 PM1/19/12
to Sebastien Binet, Cyril Oblikov, golan...@googlegroups.com
On Thu, Jan 19, 2012 at 9:45 PM, Sebastien Binet <seb....@gmail.com> wrote:
On Thu, 19 Jan 2012 09:05:50 -0800 (PST), Cyril Oblikov <mun...@gmail.com> wrote:
> четверг, 19 января 2012 г. 19:14:46 UTC+3 пользователь Volker Dobler
> написал:
> >
> > The question why the spec doesn't allow it is more
> > complex.  It could be allowed I think, but the argument
> > "looks much simpler" might not convince e.g. a
> > programmer with a strong C background who thinks
> > that for i:=0;i<N;i++ looks way more natural and clear.
> >
>
> Maybe, but a programmer with strong Python background probably would prefer
> range :)
> As far as I can see this feature is obvious enough and will not mislead
> anyone.

well, it is also rather easy to create an 'itertools' package with a Range
function returning a slice with the data, and an IRange function
returning a channel to the data (when the slice begins to be too big)

If you use that funny []struct{} then it is never too big :)

Brad Fitzpatrick

unread,
Jan 19, 2012, 12:49:53 PM1/19/12
to minux, Dmitry Vyukov, golan...@googlegroups.com
This is perfectly efficient, but not idiomatic.  It probably doesn't deserve to get promoted.

 

roger peppe

unread,
Jan 19, 2012, 1:07:20 PM1/19/12
to Dmitry Vyukov, Paul Borman, golan...@googlegroups.com
2012/1/19 Dmitry Vyukov <dvy...@google.com>:

> 2012/1/19 Paul Borman <bor...@google.com>
>>
>> The two forms are not interchangeable.
>>
>> for i := 0; i < 5; i++ {
>>    println(i)
>>    i = 5
>> }
>>
>> (prints one line)
>>
>> and
>>
>> for i := range 5 {
>>     println(i)
>>     i = 5
>> }
>>
>> would likely do different things.  I would assume the latter would work
>> like:
>>
>> for i := range make([]int, 5) {
>>     println(i)
>>     i = 5
>> }
>
>
>
> for i := range [10] struct{}{} {

dammit, you got there first!

Gustavo Niemeyer

unread,
Jan 19, 2012, 1:21:36 PM1/19/12
to minux, Dmitry Vyukov, golan...@googlegroups.com
> The magical 'struct {}'! This kind of trick might be worth mention in
> effective_go or go-wiki? Or this is considered not that good
> coding practice?

It's fun, but it's *horrible* coding practice. Kittens will die if you use it.

for i := range [10] struct{}{} {

for i := 0; i < 10; i++ {

Shorter, more flexible, and recognizable since decades ago.

--
Gustavo Niemeyer
http://niemeyer.net
http://niemeyer.net/plus
http://niemeyer.net/twitter
http://niemeyer.net/blog

-- I'm not absolutely sure of anything.

Sebastien Binet

unread,
Jan 19, 2012, 1:22:23 PM1/19/12
to Dmitry Vyukov, Cyril Oblikov, golan...@googlegroups.com
On Thu, 19 Jan 2012 21:49:22 +0400, Dmitry Vyukov <dvy...@google.com> wrote:
> On Thu, Jan 19, 2012 at 9:45 PM, Sebastien Binet <seb....@gmail.com>wrote:
>
> > On Thu, 19 Jan 2012 09:05:50 -0800 (PST), Cyril Oblikov <mun...@gmail.com>
> > wrote:
> > > четверг, 19 января 2012 г. 19:14:46 UTC+3 пользователь Volker Dobler
> > > написал:
> > > >
> > > > The question why the spec doesn't allow it is more
> > > > complex. It could be allowed I think, but the argument
> > > > "looks much simpler" might not convince e.g. a
> > > > programmer with a strong C background who thinks
> > > > that for i:=0;i<N;i++ looks way more natural and clear.
> > > >
> > >
> > > Maybe, but a programmer with strong Python background probably would
> > prefer
> > > range :)
> > > As far as I can see this feature is obvious enough and will not mislead
> > > anyone.
> >
> > well, it is also rather easy to create an 'itertools' package with a Range
> > function returning a slice with the data, and an IRange function
> > returning a channel to the data (when the slice begins to be too big)
> >
>
> If you use that funny []struct{} then it is never too big :)

right, but then the start/stop/stride aren't relevant anymore, are they ?

ie:

for _,v := range itertools.Range(2,10,3) {
fmt.Print("v=",v,"\n")
}


-s

--
#########################################
# Dr. Sebastien Binet
# Laboratoire de l'Accelerateur Lineaire
# Universite Paris-Sud XI
# Batiment 200
# 91898 Orsay
#########################################

Dmitry Vyukov

unread,
Jan 19, 2012, 2:24:22 PM1/19/12
to Gustavo Niemeyer, minux, golan...@googlegroups.com
On Thu, Jan 19, 2012 at 9:21 PM, Gustavo Niemeyer <gus...@niemeyer.net> wrote:
> The magical 'struct {}'! This kind of trick might be worth mention in
> effective_go or go-wiki? Or this is considered not that good
> coding practice?

It's fun, but it's *horrible* coding practice. Kittens will die if you use it.

 for i := range [10] struct{}{} {
 for i := 0; i < 10; i++ {
 
Shorter, more flexible, and recognizable since decades ago.

If we apply roger peppe's proposal that struct{}{} is nil, then it becomes:

 for i := range[10]nil {
 for i := 0; i < 10; i++ {

2 symbol win :)

Gustavo Niemeyer

unread,
Jan 19, 2012, 2:27:56 PM1/19/12
to Dmitry Vyukov, minux, golan...@googlegroups.com
On Thu, Jan 19, 2012 at 17:24, Dmitry Vyukov <dvy...@google.com> wrote:
> If we apply roger peppe's proposal that struct{}{} is nil, then it becomes:
>
>  for i := range[10]nil {
>  for i := 0; i < 10; i++ {
>
> 2 symbol win :)

It's getting better and better.. :)

roger peppe

unread,
Jan 19, 2012, 2:28:50 PM1/19/12
to Dmitry Vyukov, Gustavo Niemeyer, minux, golan...@googlegroups.com

for the record, i wasn't proposing that struct{}{} to *be* nil, just
that for it to be compatible with nil (the same as it's compatible
with *Foo interface{} and chan bool, without "being" any of those types).

Michael Jones

unread,
Jan 19, 2012, 10:57:54 AM1/19/12
to golan...@googlegroups.com
Looks nice visually. Since 'range' is used to mean "each element within" then you would need to believe that people will understand that [0..N-1] means "within" N -- that starting at 1 or ending at N are not to be expected. 

Would this be equally clear with more complicated expressions?
    for i := range IndexOfCharacter(s, '[') { // process characters up to '['
--
Michael T. Jones | Chief Technology Advocate  | m...@google.com |  +1 650-335-5765

Miguel Pignatelli

unread,
Jan 24, 2012, 7:40:13 AM1/24/12
to golan...@googlegroups.com
On 19/01/12 17:47, minux wrote:
>
> 2012/1/20 Dmitry Vyukov <dvy...@google.com <mailto:dvy...@google.com>>

Hmmm... I am not planning to use this construct, but I am puzzled about
this behaviour of struct{}.
What is the "magical 'struct {}'".

M;

chris dollin

unread,
Jan 24, 2012, 7:41:24 AM1/24/12
to Miguel Pignatelli, golan...@googlegroups.com
On 24 January 2012 12:40, Miguel Pignatelli <eme...@gmail.com> wrote:

>
> Hmmm... I am not planning to use this construct, but I am puzzled about this
> behaviour of struct{}.
> What is the "magical 'struct {}'".

A struct{} takes up no room.

Chris

--
Chris "allusive" Dollin

Message has been deleted

Andrew Walker

unread,
Jan 23, 2014, 3:44:10 AM1/23/14
to golan...@googlegroups.com
I know this is a super old thread, but it's still the first thing that comes up if someone googles "golang range int" and I imagine a lot of people might be coming to the language from perl, python or ruby where you can do 

"for (1..5) { #stuff }"
"for _ in range(5)"
and
"5.times {}"

respectively, and are looking for an easy and clean-looking way to do it in Go.

I saw someone created an "itertools", which returns a slice, but I'm surprised no one mentioned channels.  It seems to me it would be much more efficient and idiomatic to use a closure/goroutine/channel.  That way you're not creating an array of any sort or (eesh!) creating x new slices as we see in that example.

Something like this perhaps?  http://play.golang.org/p/VcW3EMnj9t

func numRange(first int, rest ...int) chan int {
out := make(chan int)
var start, end int
if len(rest) == 0 {
start = 1
end = first
} else {
start = first
end = rest[0]
}
go func() {
for i := start; i <= end; i++ {
out <- i
}
close(out)
}()
return out
}

And then you can just:

for s := range numRange(5) {
fmt.Println(s)
}
for s := range numRange(5, 10) {
fmt.Println(s)
}
for _ = range numRange(1, 3) {
fmt.Println("bar")
}

Unless there's something I'm missing and there's already a standard library way to do this (which is very possible!)

chris dollin

unread,
Jan 23, 2014, 3:47:59 AM1/23/14
to Andrew Walker, golang-nuts
On 23 January 2014 08:41, Andrew Walker <walk...@gmail.com> wrote:

I know this is a super old thread, but it's still the first thing that comes up if someone googles "golang range int" and I imagine a lot of people might be coming to the language from perl, python or ruby where you can do 

"for (1..5) { #stuff }"
"for _ in range(5)"
and
"5.times {}"

respectively, and are looking for an easy and clean-looking way to do it in Go.


I don't see what's non-easy/unclean about

    for i := 1; i <= 5; i ++ { whatever() }

Dmitry Vyukov

unread,
Jan 23, 2014, 3:48:25 AM1/23/14
to Andrew Walker, golang-nuts
what's wrong with for i := 0; i < 10; i++ ?

On Thu, Jan 23, 2014 at 12:41 PM, Andrew Walker <walk...@gmail.com> wrote:
> I know this is a super old thread, but it's still the first thing that comes
> up if someone googles "golang range int" and I imagine a lot of people might
> be coming to the language from perl, python or ruby where you can do
>
> "for (1..5) { #stuff }"
> "for _ in range(5)"
> and
> "5.times {}"
>
> respectively, and are looking for an easy and clean-looking way to do it in
> Go.
>
> I saw someone created an "itertools", which returns a slice, but I'm
> surprised no one mentioned channels. It seems to me it would be much more
> efficient and idiomatic to use a closure/goroutine/channel. That way you're
> not creating an array of any sort or (eesh!) creating x new slices as we see
> below.
> --
> 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 golang-nuts...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.

Jan Mercl

unread,
Jan 23, 2014, 3:48:27 AM1/23/14
to Andrew Walker, golang-nuts
On Thu, Jan 23, 2014 at 9:41 AM, Andrew Walker <walk...@gmail.com> wrote:
> "for (1..5) { #stuff }"
> "for _ in range(5)"
> and
> "5.times {}"

package main // http://play.golang.org/p/-5FIKdPVgg

import (
"fmt"
)

var n [int(^uint(0) >> 1)]struct{}

func main() {
for i := range n[:5] {
fmt.Println(i, "Hello")
}
}

-j

Michael Jones

unread,
Jan 23, 2014, 10:36:22 AM1/23/14
to Andrew Walker, golang-nuts
On Thu, Jan 23, 2014 at 12:41 AM, Andrew Walker <walk...@gmail.com> wrote:
"for (1..5) { #stuff }"
"for _ in range(5)"
and
"5.times {}"

respectively, and are looking for an easy and clean-looking way to do it in Go.

for i := 0; i <5; i++ {
    stuff
}

is the easy and clean-looking way to do it in Go.

RickyS

unread,
Jan 23, 2014, 11:37:10 AM1/23/14
to golan...@googlegroups.com, Paul Borman
A more stylish version at http://play.golang.org/p/HR4tFDGAFl


type T [10]struct{}
var l10 T

func main() {
    fmt.Printf("type %T, value is %v\n----------\n", l10, l10)
    for j := range l10 {
        fmt.Printf("  %d.   ", j)
    }
}

John Souvestre

unread,
Jan 23, 2014, 10:55:40 PM1/23/14
to Jan Mercl, golang-nuts
Hello Jan.

> for i := range n[:5] { ... }

Nice! Clearer and easier.

John

John Souvestre - New Orleans LA - (504) 454-0899




Brad Fitzpatrick

unread,
Jan 23, 2014, 11:23:41 PM1/23/14
to RickyS, golang-nuts, Paul Borman
I like:


    func main() {
         for i := range iter.N(10) {
             println(i)
         }
    }

No allocations. No risk of blocked sending goroutines.



Rob Pike

unread,
Jan 23, 2014, 11:50:27 PM1/23/14
to Brad Fitzpatrick, RickyS, golang-nuts, Paul Borman
I don't like.

Rob Pike

unread,
Jan 23, 2014, 11:58:24 PM1/23/14
to Brad Fitzpatrick, RickyS, golang-nuts, Paul Borman
I should explain. A for loop is called a for loop because looping is
what it is for. So use a for for what it's intended for: a loop.

It seems that almost every time someone comes up with a way to avoid
doing something like a for loop the idiomatic way, because it feels
too long or cumbersome, the result is almost always more keystrokes
than the thing that is supposedly shorter. In this case (and there are
others)

for i := range iter.N(5)

is one keystroke longer than

for i := 0; i < 5; i++

_before_ you count the cost of typing the import.

That's leaving aside all the crazy overhead these "improvements" bring.

Sorry, I know this is a joke thread but I have seen real examples of
this general style of making things "nicer", by making them much
worse. And they take time to stamp out, as if one can ever succeed.

But sure, have fun.

-rob

Brad Fitzpatrick

unread,
Jan 24, 2014, 12:00:22 AM1/24/14
to Rob Pike, RickyS, golang-nuts, Paul Borman
You didn't count the shift keys.

(Sorry... :-))

Brad Fitzpatrick

unread,
Jan 24, 2014, 12:04:58 AM1/24/14
to Rob Pike, RickyS, golang-nuts, Paul Borman
Actually, on a somewhat serious point... you wrote:

> _before_ you count the cost of typing the import.

But I haven't written import lines for months now.  And interestingly, having goimports has actually changed my aversion towards creating new small packages.  Now I have no fear of making a new package because it won't be annoying to use.  I had a tendency to dump too much into util-style packages before, rather than placing it where it belongs.

If I actually wanted to seriously use this "iter" joke package, I'd just type "range iter.N(5)" and it would work on save.  And I saved two shift keys.  Or four keys overall if I rename the package "to".

Rob Pike

unread,
Jan 24, 2014, 12:17:17 AM1/24/14
to Brad Fitzpatrick, RickyS, golang-nuts, Paul Borman
Sure, but that says nothing about the run-time overhead and the
compiler-opitimization-defeating obfuscation.

I'll stop. I realized earlier this week that the metric for software
quality today has almost nothing to do with the issues I believe to
matter. For instance, a newline is worth at least 100 other
keystrokes, for some unknown reason.

Seriously, I'll stop.

-rob

John

unread,
Jan 24, 2014, 12:38:09 AM1/24/14
to Rob Pike, Brad Fitzpatrick, RickyS, golang-nuts, Paul Borman
Perhaps the appeal of Brad’s approach is less repetition at the cost of length, and appearing less selfish.

:)

Henrik Johansson

unread,
Jan 24, 2014, 1:57:12 AM1/24/14
to John, golang-nuts, Brad Fitzpatrick, RickyS, Rob Pike, Paul Borman

Sublime auto generates a standard for loop so there is only the upper bound to fill in. :-)

Kevin Gillette

unread,
Jan 24, 2014, 2:26:30 AM1/24/14
to golan...@googlegroups.com
On Thursday, January 23, 2014 1:44:10 AM UTC-7, Andrew Walker wrote:
I saw someone created an "itertools", which returns a slice, but I'm surprised no one mentioned channels.  It seems to me it would be much more efficient and idiomatic to use a closure/goroutine/channel.

Brad's example is the most efficient way, in time and space, that you can do this unidiomatically. Channels have considerable overhead compared to a slice of zero-sized elements (meaning that slice won't take up any space on the heap at all).

That said, I strongly suspect people are interested in this because they haven't yet learned to disambiguate actual programming fundamentals from the particular idiosyncrasies and style of a given language.  For example, the `for x in range(10)` loop in python makes a lot of sense because python doesn't have a c-style for loop, and further because emulating a c-style for loop using a while loop in python is considerably more verbose than it needs to be. Historically range was suboptimal in python because it does allocate a list, which is why xrange was invented; it's ironic that allocating arrays/slices "is to be avoided" when emulating that style in go, since it is derived from a very inefficient, allocating approach in another language.

The only idiomatic way to do this in go, simply, is with a regular 3-clause for loop. Perhaps it deserves a FAQ entry; it doesn't deserve a package or a language change.

egon

unread,
Jan 24, 2014, 3:34:52 AM1/24/14
to golan...@googlegroups.com


On Thursday, January 23, 2014 10:44:10 AM UTC+2, Andrew Walker wrote:
I know this is a super old thread, but it's still the first thing that comes up if someone googles "golang range int" and I imagine a lot of people might be coming to the language from perl, python or ruby where you can do 

"for (1..5) { #stuff }"
"for _ in range(5)"
and
"5.times {}"

respectively, and are looking for an easy and clean-looking way to do it in Go.

I saw someone created an "itertools", which returns a slice, but I'm surprised no one mentioned channels.  It seems to me it would be much more efficient and idiomatic to use a closure/goroutine/channel.  

The idiomatic way is to simply use:

for i := 0; i < len; i++ {
...
}

It will be faster than closure/goroutine/channel.

+ egon

Michael Jones

unread,
Jan 24, 2014, 9:58:02 AM1/24/14
to egon, golang-nuts
Don't give up, Rob. Plenty of people understand what Dikjstra meant here:



--
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 golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.



--

Michael Jones

unread,
Jan 24, 2014, 10:41:27 AM1/24/14
to egon, golang-nuts
(yes, I know it's spelled Dijkstra, just a typo...)

Gustavo Niemeyer

unread,
Jan 24, 2014, 11:03:18 AM1/24/14
to Michael Jones, egon, golang-nuts
On Fri, Jan 24, 2014 at 12:58 PM, Michael Jones <m...@google.com> wrote:
> Don't give up, Rob. Plenty of people understand what Dikjstra meant here:
>
> http://www.cs.utexas.edu/~EWD/transcriptions/EWD10xx/EWD1036.html

Dijkstra's life-long view of computing as applied mathematics tends to
be either extremely insightful, or hilariously entertaining.

"""
The reason for this last suggestion is that the anthropomorphic
metaphor —for whose introduction we can blame John von Neumann— is an
enormous handicap for every computing community that has adopted it. I
have now encountered programs wanting things, knowing things,
expecting things, believing things, etc., and each time that gave rise
to avoidable confusions. The analogy that underlies this
personification is so shallow that it is not only misleading but also
paralyzing. (...)
"""


gustavo @ http://niemeyer.net

Matt Harden

unread,
Jan 24, 2014, 8:50:06 PM1/24/14
to Jan Mercl, Andrew Walker, golang-nuts
> var n [int(^uint(0) >> 1)]struct{}

That's ingenious. I love it.

Jan Mercl

unread,
Jan 25, 2014, 4:11:59 AM1/25/14
to Matt Harden, golang-nuts, Andrew Walker


On Jan 25, 2014 2:50 AM, "Matt Harden" <matt....@gmail.com> wrote:
>
> > var n [int(^uint(0) >> 1)]struct{}
>
> That's ingenious. I love it.

It's (c) Rob Pike ;-)

-j

Gerard

unread,
Jan 25, 2014, 5:17:57 AM1/25/14
to golan...@googlegroups.com, RickyS, Paul Borman
And add some extra functionality:

    for _, i := range iter.N(20).Step(2).Except(4, 6).From(10, Step(3)).Except(16) {
        println(i)
    }

Yeah, it should work, with a little bit of overhead ;-)

Tim

unread,
Jan 6, 2015, 9:26:06 AM1/6/15
to golan...@googlegroups.com


On Friday, 24 January 2014 04:58:24 UTC, Rob 'Commander' Pike wrote:
for i := range iter.N(5)

is one keystroke longer than

for i := 0; i < 5; i++

_before_ you count the cost of typing the import.

Yeah but `for i := range 5` is fewer, and if it was a language feature you wouldn't need an import. Besides are we really counting keystrokes? I just tried to use this form as I naturally assumed it would work.

As for clarity, I guess it has been a while since Rob learnt C, but I can still (vaguely) remember being confused by for loops - they have three different clauses that appear to be identical in syntax but do totally different things. I mean `for initialiser; incrementer; condition {` is equally as "obvious" as `for initialiser; condition; incrementer {` and there is no way to distinguish them other than experience. This is one of those things that only seems clear if you have done it thousands of times before.

My use case was actually this

for range numIterations {
}

which is way shorter and clearer than the equivalent non-ranged for loop. Slightly sad it didn't work - go seems to like omitting things for brevity in other places, e.g. infinite `for { }` loops.

Ah well it is a minor issue compared to the missing generics! :-P

atd...@gmail.com

unread,
Jan 6, 2015, 9:37:23 AM1/6/15
to golan...@googlegroups.com
Hey we are in 2015 now :o)

Dave Cheney

unread,
Jan 6, 2015, 9:59:10 AM1/6/15
to golan...@googlegroups.com
This thread just graduated to preschool.

atd...@gmail.com

unread,
Jan 6, 2015, 10:06:28 AM1/6/15
to golan...@googlegroups.com
Message has been deleted

Tim Hutt

unread,
Jan 6, 2015, 5:05:19 PM1/6/15
to atd...@gmail.com, golan...@googlegroups.com

Ha yes, I know I resurrected an old thread but this is high in the google results. The updated syntax in go 1.4 is still doesn't allow you to use a single integer for the range.

--
You received this message because you are subscribed to a topic in the Google Groups "golang-nuts" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-nuts/7J8FY07dkW0/unsubscribe.
To unsubscribe from this group and all its topics, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

atd...@gmail.com

unread,
Jan 7, 2015, 1:11:58 AM1/7/15
to golan...@googlegroups.com, atd...@gmail.com
Ah, yes you can't range over integers that easily.
I think the language is frozen for the time being. (some heavy work is being done behind the scenes)
But well that's where we would be having too many ways to write a for loop if everything were to be accepted.
Personally, I don't mind writing the *long* version ( otherwise why not simply for 5 { ... } etc etc)

tomwilde

unread,
Jan 7, 2015, 11:51:03 AM1/7/15
to golan...@googlegroups.com, atd...@gmail.com
Besides the already mentioned reasons, it takes only 5 minutes of thinking to understand why it would be a bad idea to implement this in the language:

Should "x := range n" loop from 0 to n, 1 to n, 0 to n-1 or 1 to n-1? In other words: should the range be inclusive and on what end(s)?

Having introduced this convenience range-syntax where you can specify the upper bound; wouldn't it by extension make sense to also allow the programmer to specify a lower bound à la "x := range a, b".

And from there people will want list comprehensions, texas ranges, etc, etc...

It's a slippery slope.

Christopher Probst

unread,
Jan 7, 2015, 12:19:00 PM1/7/15
to golan...@googlegroups.com, brad...@golang.org, rickys...@gmail.com, bor...@google.com
Hey,

I'm not a real part of the golang community yet, I've used golang only for a couple of hobby projects, so my opinion is not much worth I guess.

But I really want to say THANK YOU for keeping useless and crappy stuff out of the language, this goes out to all of you involved in the golang project ;)
I'm kind of a language enthusiast, so I learned and used all kind of languages, even the crazy ones, be it Haskell or Prolog.

From all of them, golang is one of the few I would consider a solid piece of great technology, created by people who really know what programming is about.
I'm not just speaking for me, I know a bunch of people who were frustrated about the status quo and really appreciate the simplicity of golang.

So, long story short. Please keep up your great work and the patience for carefully considering what goes into the language.
Don't be too much "pissed off" by people asking for those pythonic "features" or ... generics :D, golang ist awesome. One just have to realize it, which is difficult.

Anyways, have a nice day everybody.

- chrisprobst

Sean Russell

unread,
Jan 7, 2015, 8:42:07 PM1/7/15
to golan...@googlegroups.com, atd...@gmail.com
On Wednesday, January 7, 2015 11:51:03 AM UTC-5, tomwilde wrote:
...
Having introduced this convenience range-syntax where you can specify the upper bound; wouldn't it by extension make sense to also allow the programmer to specify a lower bound à la "x := range a, b".

And from there people will want list comprehensions, texas ranges, etc, etc...

It's a slippery slope.

There are already people who want list comprehension; you don't need range syntax changes as a gateway feature for that.

--- SER

Jorge Massih

unread,
Feb 15, 2024, 8:38:55 PMFeb 15
to golang-nuts
Hey folks! Now in in Go v1.22 (released 02-06-2024) it's possible to iterate over a range of integers by doing the approach mentioned at the beginning of this conversation.

- JM

Amnon

unread,
Feb 17, 2024, 1:27:09 AMFeb 17
to golang-nuts
Indeed. The thread started 12 years ago. At the time I thought the idea of ranging over an int was just dumb, and un-go-like.
But now it is out, I think it is great, and have run 
    perl -pi -e 's/for (\w+) := 0; \1 < ([\w()]+); \1\+\+/for \1 := range \2/' $(git grep -l for) over my entire codebase to use it everywhere.

Patrick Smith

unread,
Feb 17, 2024, 2:06:52 AMFeb 17
to Amnon, golang-nuts
On Fri, Feb 16, 2024 at 10:27 PM Amnon <amn...@gmail.com> wrote:
But now it is out, I think it is great, and have run 
    perl -pi -e 's/for (\w+) := 0; \1 < ([\w()]+); \1\+\+/for \1 := range \2/' $(git grep -l for) over my entire codebase to use it everywhere.

You know your own codebase, and maybe this was safe for you to do. But in general, blindly applying such a blanket change has the potential to cause bugs, as these two are not always equivalent:

for i := range k
for i := 0; i < k; i++ 

In particular, if k is changed inside the loop they may be very different. https://go.dev/play/p/kAHcmu7377I

(Yes, many people, myself included, would consider changing k inside such a loop to be bad coding style. But "bad style" doesn't mean it's not going to be done.)

Kurtis Rader

unread,
Feb 17, 2024, 2:20:03 AMFeb 17
to Patrick Smith, Amnon, golang-nuts
It's not just changing `k` inside the loop body that makes the transformation invalid -- your observation also applies to modifying `i` inside the loop body. Modifying either variable inside the loop body is extremely rare in my experience and doing so warrants a "dragons be here" comment. Still, your point is valid and anyone applying such a transformation should carefully evaluate the body of each loop to see if either variable might be modified by the loop body. Obviously it would be nice if a tool automated that analysis and transformation but I'm not going to hold my breath waiting for someone to implement that tool.

--
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 golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAADvV_trGNxeLUma722wk-JOGnz42fJqM8%3DVZ36TKpr5s-%3DmOQ%40mail.gmail.com.


--
Kurtis Rader
Caretaker of the exceptional canines Junior and Hank

poweredb...@gmail.com

unread,
Feb 17, 2024, 5:38:25 PMFeb 17
to Kurtis Rader, Patrick Smith, Amnon, golang-nuts
I agree with you.


Powered By Citizen 

Henry

unread,
Feb 23, 2024, 1:18:33 AMFeb 23
to golang-nuts
This is one feature that provides little value beyond saving a few keystrokes and looking slightly nice, but with potential of increased complexity when we need to implement more important features to the language down the road. This is my opinion. It shouldn't have been added, but what was done is done. There is nothing we can do about it now. 

Duncan Harris

unread,
Feb 23, 2024, 8:20:04 PMFeb 23
to golang-nuts
I made some changes to use range over int in our code base and was pleasantly surprised with the improvement in readability.

We had quite a few instances where the number of iterations involved a function call which we don't want to repeat:

- for i, n := 0, f(); i < n; i++ {
+ for i := range f() {

A surprising amount where we no longer need the range variable including some nested loops:

- for repeat := 0; repeat < col.Repeat; repeat++ {
for j := 0; j < len(cats); j++ {
for k := 0; k < numStats; k++ {
+ for range col.Repeat {
for range len(cats) {
for k := range numStats {

There were also all the benchmarks:

- for n := 0; n < b.N; n++ {
+ for range b.N {

We could update the docs in https://pkg.go.dev/testing accordingly :-)


Amnon

unread,
Feb 24, 2024, 2:57:26 AMFeb 24
to golang-nuts

So in 2012 Cyril Oblikov wrote

Why isn't this code correct?

var N int = ...
for i := range N {
    doSmth(i)
}

In my opinion it looks much simpler than:

var N int = ...
for i := 0; i < N; i++ {
    doSmth(i)
}

So we should say to Cyril (whether he is today), that it is now correct.
You just needed to wait around for a 12 years.
Because you were just ahead of your time....

And if you are reading these lines, please post again to give us a glimpse of what new features we should expect to be added to Go in 2036...

- amnon
Reply all
Reply to author
Forward
0 new messages