News for hackers. Stuff that matters.
Re:Go 2, here we come by tigershark on Thursday November 29, 2018 @01:27PM (#18562475)
I am misunderstanding or really go is using the ‘int’ type that can be 32 or 64 bit depending on the system that it runs on??? If this is the case I think that is crazy and I can’t think of any useful use case for it. If it’s not the case then please explain me what that proposal is really about...
Re:Go 2, here we come by jerf on Thursday November 29, 2018 @03:02PM (#18563423)
"int" in Go the native index type for arrays. I consider it an error to use it for anything else, and since I've adopted that policy, I've had no particular problem with ints.

Probably a good linter idea in there somewhere.

Re:Go 2, here we come by kbirkeland on Thursday November 29, 2018 @06:17PM (#18565104)
I'm curious what the motivation was to use int instead of uint considering indexes cannot be negative in Go.
Re:Go 2, here we come by jerf on Thursday November 29, 2018 @09:23PM (#18566091)
Despite most of my professional programming being in Go nowadays, I am extremely sympathetic to the Haskell/FP way of thinking about things, and trying to make invalid state unrepresentable.

However, having made the mistake a few times now of trying to use "unsigned ints" for things that I want to assert are never negative, I've learned the hard way not to do that. The problem is, there's always some bug you have in the program that will drive the uint "negative", wrapping over to a huge number. Unfortunately, since you get no warning when that happens, it tends to take longer to show up, and without a clear cutoff to say "ah, this is clearly invalid" it can be hard to even program detection code, whereas checking for "less than 0" can be unambiguous.

I'd loooove it if I could easily, cheaply, and universally (i.e., not just in Go, but across all my programming languages) turn on a behavior that says "if this int or uint under or overflows, throw an exception instead of trying to do whatever stupid thing you're going to do". I get the sense this is heading down the road where in 20 or 30 years, this is just going to be common sense. However, we are very early on the road yet from what I can see. Whenever I bring it up, even today, even in this sort of context, it still is generally negatively received. (But not uniformly. A few other people agree. I think momentum is with me. I'm not sure my programming career will live long enough to see it, though.)

Re:Go 2, here we come by johncolanduoni on Friday November 30, 2018 @12:23AM (#18566920)
Rust does this in debug builds by default, and you can switch it on in production if you'd like.
Re:Go 2, here we come by monocularvision on Friday November 30, 2018 @06:13PM (#18573612)
Swift does this with the default operators. There are alternative operators if you want to get the more classical C-style treatment.
Re:Go 2, here we come by greenleafjacob on Thursday November 29, 2018 @09:59PM (#18566260)
> if this int or uint under or overflows, throw an exception

Overflow flags are supported on some architectures, so it would really just be a matter of checking that flag.

Re:Go 2, here we come by 4ad on Friday November 30, 2018 @06:43AM (#18568388)
Except in Go, types are defined using modular 2s complement. Overflow is not considered a problem, it's a feature that code depends on.
Re:Go 2, here we come by LukeShu on Friday November 30, 2018 @11:34AM (#18570267)
The spec says:

> For signed integers, the operations +, -, , /, and << may legally overflow and the resulting value exists and is deterministically defined by …*

It does not go on to define the overflow values; that gets to be implementation defined.

This is in contrast to unsigned integers, which the spec does precisely define overflow for.

Re:Go 2, here we come by joppy on Friday November 30, 2018 @02:37AM (#18567427)
Using unsigned indexes would be fine if the program automatically throws an error on wrapping. Otherwise, it’s an accident waiting to happen, since you have to code all of your arithmetic keeping in mind the fact that the numbers are trying to blow up in your face.

If x is unsigned, then you can’t rearrange an inequality like x >= 4 into x - 4 >= 0, since the first inequality is only true sometimes, whereas the second is true always. This looks obvious, but bury it a little way into some nontrivial index arithmetic and boom.

Another more aesthetic reason is that indices can represent offsets into a structure relative to some other index, and in this case you really need negative numbers.

Re:Go 2, here we come by IshKebab on Thursday November 29, 2018 @09:27PM (#18566104)
In general it is nicer to use signed numbers for indices. The actual index can't be negative, true, but differences between them can, and it means you don't have so many dubious sign conversions.
Re:Go 2, here we come by pxia on Thursday November 29, 2018 @06:24PM (#18565153)
Because you want to represent errors. For example a find() function that returns the index of some element: you want to return -1 when the element doesn't exist.
Re:Go 2, here we come by growse on Thursday November 29, 2018 @07:12PM (#18565433)
Shouldn't idiomatic go return an error instead? Magic number ranges for errors always seemed a bit old-fashioned.
Re:Go 2, here we come by pxia on Thursday November 29, 2018 @07:23PM (#18565510)
It's just an example... Another example would be you want to iterate your array in reverse. The normal `for (uint i=size-1; i >= 0; i--)` won't work.
Re:Go 2, here we come by growse on Friday November 30, 2018 @06:34AM (#18568350)
That example doesn't work precisely because you're conflating the concept of the loop counter (which type represents an integer that needs to be able to go <0) with the array index accessor. There's no reason for these two things to be the same type, it's just a pattern that accidentally works because we allow arrays to be accessed using a type that represents negative numbers.

What would be a more compelling argument is to use int in the same way that python does - a negative accessor means offset from the end of the array, not the start. I'm not sure golang lets you do this though...?

Re:Go 2, here we come by xyproto on Thursday November 29, 2018 @07:29PM (#18565549)
Returning -1 instead of an error is abusing the type system. In C, there is no error type, so it might be excusable there, but it is inexcusable in Go, IMO.
Re:Go 2, here we come by nordsieck on Thursday November 29, 2018 @07:47PM (#18565638)
> I'm curious what the motivation was to use int instead of uint considering indexes cannot be negative in Go.

I want to emphasize that I do not know the true answer to this question.

I think that indexes are int to play nicely with a decrementing loop counter. Doing:

    for i := len(n) - 1; i >= 0; i-- { fmt.Println(n[i]) }
requires i to be signed due to the last iteration.
Re:Go 2, here we come by a1369209993 on Thursday November 29, 2018 @10:56PM (#18566535)
I'm not sure about go, but in C this could be:

  for(size_t i = zn; i-- > 0 ;) printf("%s\n",n[i]);
(This is a large part of why unsigned over/underflow is well-defined behavior in C.)
Re:Go 2, here we come by nordsieck on Thursday November 29, 2018 @11:28PM (#18566665)
In Go, i++/i-- is a statement, not an expression, so that doesn't work.

More generally, assignment is always a statement, and never an expression (e.g. you can't say a = b = c)

Re:Go 2, here we come by Too on Friday November 30, 2018 @01:44AM (#18567244)
Crazy indeed. This was like lessons learned #2 from C, which later introduced the stdint types int32_t et. al.

A modern language with this type of confusing and platform dependent behavior is inexcusable. By all means, include a native data type as big as the processor can handle (size_t), but don't call it int which is the default data type most people will use out of pure laziness.

Re:Go 2, here we come by throwaway34241 on Thursday November 29, 2018 @03:42PM (#18563797)
Which would you choose instead? To default to 32 bits (even on 64 bit systems) or to default to 64 bits (even on 32 bit systems).

Defaulting to 64 bit math on 32 bit systems will have a huge performance penalty on generally the slowest/oldest systems where this penalty is least desirable. It's not clear to me what the benefit to this would be for most programs.

Running 32 bit ints on 64 bit systems will cause problems handling large arrays on systems with a lot of memory. I think it also complicates generating efficient loop code, although C++ gets around this with signed integer overflow being "undefined behavior".

Of course Go has int64 and int32 types if you want to use them (and all conversions require explicit casting), but the default type for array lengths etc is the platform native type. But what is the better alternative?

Re:Go 2, here we come by tigershark on Friday November 30, 2018 @03:22AM (#18567581)
I would use int and long like in C# for example, with no magic int that can be 32 or 64 bit depending on the platform to avoid any confusion.
Re:Go 2, here we come by throwaway34241 on Friday November 30, 2018 @07:09PM (#18573993)
And as a result of this, you can't have a 3GB byte array in C#. I think there needs to be a big benefit to make hard-coding a restriction like that into the language worth it.

Unfortunately I've read every comment in this HN thread (so far) and I haven't found any specific one mentioned, just people calling it "crazy" and "confusing" over and over.

Go is a language that has explicit pointers! And of course those can be 32 or 64 bits and change struct sizes, field offsets etc. There are certainly things about Go that are confusing but I've never thought this was one of them.

Just FYI Go has int8, int16, int32, int64, and int types. Only the 'int' type is the machine-native one. It's always been obvious to me that 'int' is the one without a fixed size, but I think this would be less obvious if the naming convention was different using short, int, long etc.

Re:Go 2, here we come by toyg on Thursday November 29, 2018 @03:55PM (#18563915)
The subset of Go users who deploy on 32bit hardware in 2018 and care about performance at that level, is likely to be vanishingly small.
Re:Go 2, here we come by LukeShu on Thursday November 29, 2018 @05:32PM (#18564762)
32 bit ARM is still very common.
Re:Go 2, here we come by coldtea on Friday November 30, 2018 @07:36AM (#18568627)
What about Go in 32 bit ARM?
Re:Go 2, here we come by throwaway34241 on Thursday November 29, 2018 @04:16PM (#18564093)
Even if it's OK to degrade the performance of a small minority of users, is there a big benefit to emulating 64 bit ints everywhere on 32 bit hardware? (I'm not saying there isn't a benefit, just that it's not clear to me what it is).

I don't know how many users are still on 32bit. Maybe low power network devices? Older mobile phones (Go isn't usually run on mobile, but it's possible...).

If at some point in the future 32 bit systems become totally irrelevant for Go users, maybe a release of Go could drop support for it altogether and make int an alias for int64, and save people some type casts. 32 bit systems probably aren't at that point yet though.

Re:Go 2, here we come by coldtea on Friday November 30, 2018 @07:37AM (#18568630)
>I don't know how many users are still on 32bit. Maybe low power network devices? Older mobile phones (Go isn't usually run on mobile, but it's possible...).

Well, 16 bit would also be possible if someone took the effort. Perhaps it just shouldn't be encouraged.

Re:Go 2, here we come by throwaway34241 on Friday November 30, 2018 @06:37PM (#18573807)
By 'possible' I meant that it's currently supported by the Go toolchain.
Re:Go 2, here we come by nwmcsween on Thursday November 29, 2018 @02:32PM (#18563152)
Its not crazy, its defined by the system ABI, C, C++ has this too in that can be whatever depending on the ABI, hell char can be 32 bits.
Re:Go 2, here we come by Sharlin on Thursday November 29, 2018 @02:57PM (#18563382)
It may be crazy but it's not exactly without precedent. Neither C nor C++ fix the sizes of the fundamental integer types, although for backward-compatibility reasons popular 64-bit platforms still have 32-bit `int` and even `long`. But yeah, there's a reason eg. Rust has no `int` and friends but `i32` etc. instead.
Re:Go 2, here we come by WakiMiko on Thursday November 29, 2018 @03:25PM (#18563628)
Rust has a `usize` which is 32 or 64 bits depending on the platform and also serves as the native index type for arrays and such.
Re:Go 2, here we come by friday99 on Thursday November 29, 2018 @05:17PM (#18564657)
Yeah, that makes sense because you need some type to span the address space and that depends on the size of the address space. That is what int is used for in go, though why they chose signed rather than unsigned is confusing. unsigned you would never have to do negative bounds checks and you can prove a lot of other useful things if you know your index is always positive.
Re:Go 2, here we come by earenndil on Thursday November 29, 2018 @05:50PM (#18564902)
I don't know how go does it, but in some languages negative indices count backwards from the rear end. E.G. myarr[-1] == myarr[myarr.length-1].
Re:Go 2, here we come by lemoncucumber on Thursday November 29, 2018 @03:42PM (#18563794)
Right, 64-bit Windows has 32-bit int and long and 64-bit long long (LLP64) while 64-bit unixes generally have 32-bit int and 64-bit long/long long (LP64).
Re:Go 2, here we come by user5994461 on Thursday November 29, 2018 @03:13PM (#18563513)
C only defines char, short, int has having a minimum size of 8, 16 and 32 bits.
Re:Go 2, here we come by mrb on Thursday November 29, 2018 @03:17PM (#18563550)
Actually C defines the minimum size of "int" as 16 bits, because it defines the minimum range it should support as [-32768 .. 32767]

See https://en.wikipedia.org/wiki/C_data_types

Re:Go 2, here we come by shric on Thursday November 29, 2018 @04:52PM (#18564439)
Nit: [-32767 .. 32767] C permits ones' complement and sign-and-magnitude as well as two's complement.
Re:Go 2, here we come by jstimpfle on Thursday November 29, 2018 @03:21PM (#18563591)
no, int is 16 bits minimum
Re:Go 2, here we come by pkulak on Thursday November 29, 2018 @01:59PM (#18562799)
You are not crazy, and it's what makes this proposal even more appropriate than other languages. "int" is already a magic type.
Re:Go 2, here we come by icedchai on Thursday November 29, 2018 @04:45PM (#18564364)
Yeah, sounds crazy. It only worked for C for 40+ years...
Re:Go 2, here we come by usrusr on Thursday November 29, 2018 @05:26PM (#18564720)
Ignoring the basic int type and using a zoo of preprocessor defines instead is what has worked for C all that time.

But I still think that native types have their place. It can often be quite reasonable to accept serious limitations on narrow machines where the performance gains won by the trade-off are desperately needed, lift those limitations on wider machines and grant an enormous safety margin on the widest architectures. When you dive deeper, the values where this makes sense still tend to be "index-like", as GP stated, but they don't have to strictly be indexes (e.g. IDs, a wider machine will be capable of working on bigger datasets and therefore be more likely to exhaust a given width of IDs, all indexes are identifiers but not all identifiers are indexes)

Re:Go 2, here we come by geezerjay on Friday November 30, 2018 @02:02PM (#18571631)
> Ignoring the basic int type and using a zoo of preprocessor defines

My C is a bit rusty but why should #defines be used in this scenario? A typedef set in a config.h.in is more than enough to meet the requirements of this usecase.

Re:Go 2, here we come by icedchai on Friday November 30, 2018 @05:30PM (#18573343)
Why do you need your own typedef? stdint.h is available, if you're using a compiler from the past couple of decades at least.
Re:Go 2, here we come by johncolanduoni on Friday November 30, 2018 @12:28AM (#18566942)
And what percentage of programs written in those 40 years are actually able to run on systems with more than one or two different memory layouts?
Re:Go 2, here we come by AsyncAwait on Thursday November 29, 2018 @05:36PM (#18564795)
Why is that a problem? There's int8/16/32/64 for when you need to be specific.