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
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
Dmitry Vyukov
unread,
Jan 19, 2012, 12:39:43 PM1/19/12
to Paul Borman, 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
}
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
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:
well, it is also rather easy to create an 'itertools' package with a RangeOn 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.
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:
It's fun, but it's *horrible* coding practice. Kittens will die if you use it.> 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?
for i := 0; i < 10; i++ {for i := range [10] struct{}{} {
Shorter, more flexible, and recognizable since decades ago.
If we apply roger peppe's proposal that struct{}{} is nil, then it becomes:
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 '['
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
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.
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
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
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{} func main() {
var l10 T
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
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
_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:
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
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
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.
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 PM2/15/24
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 AM2/17/24
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 AM2/17/24
to Amnon, golang-nuts
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++
(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 AM2/17/24
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.
--
Kurtis Rader
Caretaker of the exceptional canines Junior and Hank
poweredb...@gmail.com
unread,
Feb 17, 2024, 5:38:25 PM2/17/24
to Kurtis Rader, Patrick Smith, Amnon, golang-nuts
I agree with you.
Powered By Citizen
Henry
unread,
Feb 23, 2024, 1:18:33 AM2/23/24
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 PM2/23/24
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 {
Amnon
unread,
Feb 24, 2024, 2:57:26 AM2/24/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. 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
You just needed to wait around for a 12 years.
Because you were just ahead of your time....