7 ms·
Constants
- millstone 12y ago> In summary, a typed constant obeys all the rules of typed values in Go. I think this is too optimistic. For example, you can divide by a 0 value but not by a 0 constant: 1.0 / 0.0 // compile error but zero := 0.0 1.0 / zero // infinity Or try: foo := 0.0 fmt.Printf("%f", -foo) // outputs -0.0 fmt.Printf("%f", -0.0) // outputs 0.0 So negating a zero value is different than negating a zero constant. Rather confusing.
- deleted 12y ago[deleted]
- dsymonds 12y agoThat section is talking about typing. In that sense, a typed constant obeys all the [type] rules of typed values in Go. It's true that dividing by zero is different, but there's lots of other more obvious ones, such as a typed value being assignable (and usually addressable).
- pcwalton 12y agoInteresting. IEEE 754 allows either behavior (trapping or not) for division by zero, but it requires that -0.0 yield a different value from 0.0 (that nevertheless compares equal to it but can be distinguished via copysign or reciprocal).
- deleted 12y ago[deleted]
- Tloewald 12y agoSeems like they've eliminated a class of subtle bugs and introduced a new class of subtle bugs. I can understand why mixing signed and unsigned types leads to subtle bugs, but not being able to mix floating types and integer types is, in practice, a big pain in the butt and I'm not convinced it's preventing anything bad from happening -- it just wraps bugs in casts.
- jerf 12y agoTo really do this right, a cast probably should have been able to fail, but this really complexifies code. On the other hand, only a certain restricted class of casts can truly not fail and I wish Go could tell the difference. To be honest, this seems like one of those places where Go suffers from having paid a little less attention to the mainstream of type theory than I'd like. One of the things I think we can learn from our various experiments and years of experience with code is that any sharp bit of the code will eventually come out and bite your program. No matter how inconvenient it is to have to deal with errors on truncation, if you make it "easy" and just silently eat the extra bits, it will eventually cause bugs, pretty much every time. I mean that fairly literally... it boggles my mind that damn near every time I set to use a number I encounter this problem incredibly regularly. I'd really like to be able to use uints more often, but it's too easy for them to blow up in your face instead of helpfully restricting the range of things you have to think about, as a type should. You can tell the Go authors over the years have independently rediscovered a lot of the same principles, because Go is a lot more careful than C or a number of other extant languages in a lot of places, but there's the occasional blind spot like the numeric type hierarchy. I've come to like Go in a lot of ways, but I find dealing with the numeric types a bit of a throwback... I wish I could flip a flag or something and get panics on overflows or underflows instead of silent truncation. It's an annoyingly difficult bug to track down sometimes.
- JoeAltmaier 12y agoFunny, I haven't had but a few truncation bugs in 20 years. And only when doing math on rates etc. Where I know they can occur, and do a diligent job of testing, so no issue. I think this is overblown. Should every i++ have to deal with truncation issues? This would overburden code pointlessly.
- jerf 12y agoFrom my training in other languages, I really want to use uint on values that have no meaning when negative. If you look at that statement with C eyes, that probably sounds insane, but if you look at it from a modern type system perspective, it sounds eminently sensible and if anything not paranoid enough (where's your upper bound?). Unfortunately it's too darned easy to casually subtract something and bam, Big Numbers due to underflow. What I want is to be told I have bug... what I get is just the bug. I've also encountered it in some network code where the numbers in question were bitpacked. I mean, sure, it's my bug, but philosophically I no longer think that's the end of the story. Anything a compiler or runtime can do to help me avoid bugs, it should, and noticing a truncation is definitely in that class. Again, that statement may sound crazy in a C world, but it's perfectly sensible in a modern one. You don't get truncation bugs because you're so used to not getting any help that you just do bad things like not correctly specify your type, because you've thoroughly internalized how bad and wrong the compiler and runtime are here. You shouldn't have to lie about your types to make your code work.
- twotwotwo 12y agoKind of fun that, say, uint(0+0i) works, not that I'm going to use that tomorrow.
- kristianp 12y agoThis is the permanent link for the constants article, currently the link points to the blog front page: http://blog.golang.org/constants http://blog.golang.org/constants edit: it has been updated now.
- dang 12y agoThanks!
- kornakiewicz 12y agoWhen I was playing around one of most irritating thing in Go was that I need to write a lot of type conversions, especially since there's eight "normal" integer types. In my opinion, for sake of simplicity it could be reduced.
- Sanddancer 12y agoThe problem is that if you're writing code that you want to be as fast as possible, then you're going to want to pin down the size of those integers to be as small as possible in order to let the compiler take advantage of the vector units found in modern processors. For example, if you're writing a lot of graphics code, not only are you going to be wasting space if you're giving every color channel of every variable 64 bits (8 bytes) of space, but you're going to be giving up a lot of performance, because the compiler has a lot fewer hints when it tries to autovectorize your code. Or, as another example, if you're writing a low-level networking library, then things like byte-level alignment matter. Reducing the integral types may make it simpler, but makes the language itself a lot less useful.
- kornakiewicz 12y agoYeah, I totally understand why there's a place for uint8 and int64, but wonder why I have to write x := uint64(a)+b // b is uint64 and x also will be instead just x := a+b, because type of x is still clear and casting could be done invisibly. But after rethinking the issue I agree with you that's good idea, just hadn't meet place for this in my pet projects.
- Sanddancer 12y agoThere, I think the question is what type is (a). We're starting to get into the philosophy of languages here, regarding how much of a push between implicit and explicit we want. Are we expecting variable a to be pushed up into uint64 size in the intermediary? or are we expecting (b) to be pushed down to (a)'s size before adding them together. To be honest, I personally prefer C#'s model, where one can define explicit and implicit conversions, and handle accordingly, but can see the merits of go's tack in guaranteeing obviousness, even if it means typing a bit extra.
- pilif 12y agoThis brings back memories of times long since past as this is pretty much how Delphi deals with constants.
- eru 12y agoIt's strange that they only have numeric and string constants. What about, say, constant arrays?
- Laremere 12y agoGo doesn't have them. There is no large need for any special consideration of values other than those discussed in the blog post. The programmer can declare the global variable easy enough, and even use Go's Init method to populate the values. As the blog outlined, variables all have type, and it's only constants which don't have a specific type in Go. It's true it's possible to theorize up a special case where you'd want a slice of these broadly typed values, but that would add a lot of complexity to the language for doing some work which isn't very hard to do without the language feature. As for wanting a constant variable, Go doesn't have that because in the opinion of the designers it makes the type system much more complicated for a gain that isn't worth the effort and language complication.
- alecbenzer 12y agoI don't understand. Why is const str = "Hello, world!" important to have and easy to implement, but const strs = []string{"Hello", "world!"} is not?
- tjgq 12y agoWhat happens when you write var x []string = strs ? If you make a copy of the slice's underlying array and point x to the copy, then you are hiding a potentially expensive allocation behind an apparently innocuous initialization (something that Go tries very hard not to do). If, instead, you make x point to the same underlying array as strs, then you would have to have immutable slices, which is something that currently does not exist in Go. I'm not saying neither of the two options is acceptable, but they surely raise issues that go against the grain of the language.
- alecbenzer 12y ago
- zak_mc_kracken 12y ago> When designing Go, we decided to avoid this minefield by mandating that there is no mixing of numeric types Except when these values are constant, in which case you can mix at will. Quite a weird design decision.