Live data from Hacker News

a[low:high:max] in Golang – A Rare Slice Trick

build-your-own.org

71–80 of 131 posts

Re: a[low:high:max] in Golang – A Rare Slice Trick

#71
post #32

Earlier quoted context omitted.

This is misleading enough it's a lie; to do this you need to use a function named `unsafe.Pointer` with a type named `reflect.StringHeader`, not just `[]byte` and `string`.

It means there is special protection for string-data that is not available to anything else, and that library-authors get panic reports about immutable byte slices. To that degree, it's something that the specialized type exposes you to but the type system does not adequately protect or signal. But yes, AFAIK this requires use of `unsafe`. Which does change things, and puts the blame for misuse squarely on the immuta…

It seems pretty absurd to me that you would blame Go’s design for silly things people do with unsafe. Yes, I wish ago had more/better immutability semantics and it’s slightly odd that strings are immutable but other types are not, but griping that something bad happened when you used a package called “unsafe” is pretty silly.

Re: a[low:high:max] in Golang – A Rare Slice Trick

#72
post #11

Earlier quoted context omitted.

This is a pretty good vignette of how Go is designed. "Users don't need this feature (immutability, polymorphism, etc.), let's not include it. Ah crap, turns out we actually need it for a core language feature. Is there a lesson we can take away here? Nah, just make an ad-hoc implementation of the functionality in this one place."

For what it’s worth it sounds no worse than Java: you have immutable strings but you have no way to enforce that you can’t modify something that you have recieved, which is why the underlying char array for a string has to be defensively copied if the user asks for `asArray()` or whatever it is. Strings being immutable doesn’t seem like a special case, though. The underlying mutable array is just encapsulated, which…

I don't think you can reflect onto the standard library anymore, with the recent "strong encapsulation".

Re: a[low:high:max] in Golang – A Rare Slice Trick

#74
post #11
post #9

Earlier quoted context omitted.

But also strings are actually immutable sometimes (at the very least when hardcoded), and they can be converted to a `[]byte` slice that looks mutable, but panics when modified. AFAIK no other slice-like data in Go behaves like this. Fun!

This is a pretty good vignette of how Go is designed. "Users don't need this feature (immutability, polymorphism, etc.), let's not include it. Ah crap, turns out we actually need it for a core language feature. Is there a lesson we can take away here? Nah, just make an ad-hoc implementation of the functionality in this one place."

I mean, what language got everything exactly right from day 0? Yes, Go started from a minimalist position, but that’s been a wildly successful decision—Go lacks a lot of the cruft of other languages. Go is an easily understandable language, it compiles super quickly, it has top notch tooling (e.g., compiling almost any Go project on any system with ‘go build’ and even cross compile by changing a couple of env vars), it compiles to relatively small[^1] static binaries by default, and it does all of this with pretty good performance.

[^1]: Someone is going to come in with some rant about how big a “hello world” binary is compared to C, as if this is emblematic of some real-world use case.

Re: a[low:high:max] in Golang – A Rare Slice Trick

#75
post #59

Earlier quoted context omitted.

I don’t think you can fairly call go’s generics an “ad-hoc” implementation. They added syntax for it.

I think in this context "ad hoc" refers to the context in which that syntax was added. IIRC the original creators were against generics ever being added to Golang, so they wouldn't have thought about their eventual introduction when choosing Go's initial syntax. The result is that the generics that eventually were added feel awkward and "bolted on" to many people. (I don't have any strong opinions on it personally, b…

Maybe you shouldn't play game of telephone like that.

Go generics are exceptionally well designed.

The reason it took so long for Go to get generics is because Go designers took their time to arrive at a design that fits with the rest of Go.

It's not rushed, it's not "bolted on".

They did several designs that they rejected before they accepted the design that got implemented.

Re: a[low:high:max] in Golang – A Rare Slice Trick

#76
post #59

Earlier quoted context omitted.

I don’t think you can fairly call go’s generics an “ad-hoc” implementation. They added syntax for it.

I think in this context "ad hoc" refers to the context in which that syntax was added. IIRC the original creators were against generics ever being added to Golang, so they wouldn't have thought about their eventual introduction when choosing Go's initial syntax. The result is that the generics that eventually were added feel awkward and "bolted on" to many people. (I don't have any strong opinions on it personally, b…

I haven’t heard many gripes about the syntax, but I have heard plenty of gripes about how long it took them to add them. Frankly my biggest grievance with Go’s generics is the goofy dictionary implementation that makes performance difficult to reason about. I also think the people who complain the loudest about missing generics were often just unaware that there are other (often simpler) ways to achieve the same thing—it often feels like people were just angry that Go didn’t look exactly like $theirFaveLang. There are definitely some use cases that are improved by generics, but most complaints were about avoiding writing relatively simple loops (iterator chains are more readable in the trivial cases, but quickly become less readable particularly when you need to short circuit on errors and so on—a loop is often cleaner, clearer, and faster to implement).

Re: a[low:high:max] in Golang – A Rare Slice Trick

#77
post #68

Earlier quoted context omitted.

I coincidentally was just looking at some docs, and I think I have a handle on it (to it?:) now. The specific strange design decision in Go is that you can create a child slice that has its own starting offset and length, but may or may not inherit its parent’s capacity. Just because it’s well-defined doesn’t mean it isn’t tricky. Even if you kept the semantics the same but made cap=len for subslices by default, sure…

cap==len is effectively the default - most slicing is done with [start:end], not [start:end:additional-cap]

No it’s not -- I just checked the language specification and it says:

After slicing the array a

a := [5]int{1, 2, 3, 4, 5}

s := a[1:4]

the slice s has type []int, length 3, capacity 4

Many of us here are arguing that the default should be cap==len==3, but it’s not, it’s 4.

Re: a[low:high:max] in Golang – A Rare Slice Trick

#78
post #64

why do people write articles about go features? when PHP was in its prime, almost nobody wrote blogs explaining how they found some philosophy in PHP. there's a reason for that. when you see someone open their article explaining a language feature by talking of the implementation details or specific use cases, that's a language smell (of course all industrial PLs stink). ironically go is the only post 80s language th…

I'm not sure how your snippet above exemplifies memory unsafety.

Concurrent access does let you hit some 'fun' behavior, but you have to be doing pretty dumb things to hit them. And while the implementation may be able to save you from something like that, such things would likely bubble up elsewhere(disk i/o, network i/o, etc) if doing that kind of thing.

Re: a[low:high:max] in Golang – A Rare Slice Trick

#79
post #64

why do people write articles about go features? when PHP was in its prime, almost nobody wrote blogs explaining how they found some philosophy in PHP. there's a reason for that. when you see someone open their article explaining a language feature by talking of the implementation details or specific use cases, that's a language smell (of course all industrial PLs stink). ironically go is the only post 80s language th…

TLDR:

The best part of Go is that there is very little magic in Go. If you understand that slices are just fat pointers implemented as a built-in, there is nothing confusing about them. I can understand every part of a Go program, all the way down to the language syntax that generate assembly. I don't have to be afraid of or be mystified by any language feature, because 1) there are few, 2) they are just programs implementable in Go. This does not happen with many languages.

Longer version:

Go didn't need to add slices as a language feature (it could have been a library function of containers, as fat pointers are not a new thing), but having it in the language makes using them easy. And not having generics at the start sort of forced their hand.

And as slices are just fat pointers to an underlying array, obviously it's not multi-thread safe.

So if you understand that slices are just C-style structs with pointer to data, a length counter and a capacity counter, then nothing in your example code is surprising. There is no hidden memory copy, no hidden synchronization lock to make it thread safe. And Go's a = append(a, item) now makes sense, because if 'a' grew in size, append would have to create a new underlying array, and a new slice struct with a pointer to new data. To me, it's much easier to reason about what the code is doing than other languages with Array types.

> nobody would ever design something like this without massive cognitive dissonance

Somebody did, without any cognitive dissonance. And I like it :)

> just copy and modify the previous industrial PL, C in this case

Go really wanted to be "A Better C". The language is not much larger than C, removed a bunch of C foot-guns, and it's as capable as Java, if not a bit more. I think the compromises Go made were well considered compared to other C family of languages.

Re: a[low:high:max] in Golang – A Rare Slice Trick

#80
post #75

Earlier quoted context omitted.

I think in this context "ad hoc" refers to the context in which that syntax was added. IIRC the original creators were against generics ever being added to Golang, so they wouldn't have thought about their eventual introduction when choosing Go's initial syntax. The result is that the generics that eventually were added feel awkward and "bolted on" to many people. (I don't have any strong opinions on it personally, b…

Maybe you shouldn't play game of telephone like that. Go generics are exceptionally well designed. The reason it took so long for Go to get generics is because Go designers took their time to arrive at a design that fits with the rest of Go. It's not rushed, it's not "bolted on". They did several designs that they rejected before they accepted the design that got implemented.

This is a truly unreal level of blub paradox and/or brown nosing. It's almost a complete inversion of reality.

Go's maintainers had to be beaten into bolting on a poorly-done implementation of polymorphism over like a decade. I can't imagine anyone who's used any language with polymorphism baked in to the design describing Go's implementation as "exceptionally well designed". If this is a Poe's law thing and you're just joking, then you got me.

Post reply on HN