HNHacker News
TopNewBestAskShowJobs

zeeboo

505 karma · joined July 11, 2012

[ my public key: https://keybase.io/zeebo; my proof: https://keybase.io/zeebo/sigs/pUgbWKGyeX4DCJKX05K8nPmSd_MKsHZZElgYcAm29qw ]
submissionscomments
zeeboo··on The most famous transcendental numbers
It is indeed manufactured specifically to show the existence of "normal" numbers, which are, loosely, numbers where every finite sequence of digits is equally likely to appear. This property is both ubiquitous (almost every number is normal in a specific sense) and difficult to prove for numbers not specifically cooked up to be so.
zeeboo··on Good-bye core types; Hello Go as we know and love it
https://go.dev/doc/faq#generic_methods
zeeboo··on What is gained and lost with 63-bit integers? (2014)
Go's GC has been precise since 1.4 released about 13 years ago.
zeeboo··on Go 1.20 released
You forgot to list the most useful feature of adding generics: people on the internet can no longer say "lol no generics", drastically reducing the amount of garbage comments about Go.
zeeboo··on The Ironclad Argument Against Racism
It's for people who think racism is wrong and want a reason to avoid being introspective about what they can do about living in and benefiting from a society built on racism.
zeeboo··on How Go mitigates supply chain attacks
Again, it's not just malicious updates. Normal updates can also introduce security vulnerabilities. For example, I have a dependency at v1.0 and v1.0.1 introduces a security bug unintentionally. It is eventually fixed in v1.1. If I wait to update until v1.1, then I am not vulnerable to that bug whereas an automatic update to v1.0.1 would be vulnerable. My point is that in expectation, updating your dependency could be just as likely to remove a security vulnerability as it is to add one.
zeeboo··on How Go mitigates supply chain attacks
My statement had nothing to do with intent. Conversely, once a vulnerability is introduced (intentionally or not), you don't want every developer to update their deps to the newly insecure version.
zeeboo··on How Go mitigates supply chain attacks
Every change that fixes a security issue implies the existence of a change that introduced the security issue in the first place. Why is bumping a version more likely to remove security issues instead of introduce them?

The reason why older is better than newer has more to do with the fact that the author has actually tested their software with that specific version, and so there's more of a chance that it actually works as they intended.

zeeboo··on A new ProtoBuf generator for Go
So, I thought this at one point, too. But it turns out that methods is a type alias to an unnamed type, so there's no package level privacy issues: https://github.com/protocolbuffers/protobuf-go/blob/v1.26.0/...
zeeboo··on DRPC: A full replacement for gRPC in under 3kloc
For example, it doesn't use HTTP/2 (which has a ~100 page RFC and compiles to a ~2MB object file), does not have any load balancing or name resolution engine, and does not handle connection pooling or multiplexing.

Granted, one person's unnecessary is another person's necessary. But since DRPC has a modular design based on small interfaces, many features that are rarely used in gRPC can be excluded and left up to third parties to implement if they want.

zeeboo··on Proposal: expression to create pointer to simple types
Indeed. This is in a thread where the original comment was "I think the best approach would be making & work in basically any scenario." I'm trying to demonstrate the complications of making it work on map accesses.
zeeboo··on Proposal: expression to create pointer to simple types
I apologize if the tone of my previous comment sounded harsh to you or if some of my arguments sounded like strawmen. I am in good faith trying to interpret your comments as best as I am able. I don't feel like you're giving me the same courtesy, so I'll exit the discussion now. Thanks.
zeeboo··on Proposal: expression to create pointer to simple types
> That's a distinction without a difference. `append` does not "explicitly reallocate", it may or may not reallocate, you've no idea. Even if the backing array is full, it might be realloc'd in-place.

Maybe to you, but to me, a pointer going from modifying the value inside of the map to no longer modifying the value inside of the map during any operation is quite a bit different than requiring a reassignment of the slice header. In other words:

    x := make([]int, 5)
    y := &x[0]
    x[3] = 8
    *y = 5
    print(x[0]) // always prints 5
as compared to

    x := make(map[int]int)
    y = &x[0] // btw, is this even valid? let's assume it implicitly does x[0] = 0
    x[3] = 8
    *y = 5
    print(x[0]) // maybe sometimes prints 5?
is meaningfully different. For slices, we know that x[0] will always print 5 until the value of x is reassigned in some way.

> Also technically nothing prevents a GC from reallocating the slice.

It would have the same problem the map does: you'd have to update any pointers into the slice to point to the new slice, otherwise the semantics of the program changes. That is not something the GC currently does, and would require an awful lot of metadata and scanning.

> I've never heard of a hashmap implementation which would do otherwise.

I'm not sure what this is referring to. I agree every map implementation has to reallocate the backing store of values periodically. I was trying to say that keeping the flexibility to reallocate the backing store of the map during GC means that you cannot choose the "writes through pointer are observed in the map" option (at least without a lot of complication around updating pointers) because as a programmer, you would not be able to know if it would do that or not, which is a fairly useless primitive.

zeeboo··on Proposal: expression to create pointer to simple types
> It doesn't (have to) invalidate the pointer though. When resized the map's content get copied to a new backing buffer, the pointer can keep pointing to the old buffer.

That's true, but I don't think it's very comparable to slices. With slices, you have to explicitly reallocate either by creating a whole new slice or using append. Reslicing, indexing, or other operations do not reallocate. On the other hand, maps may end up resizing on any operation that involves them, or even theoretically in the background without any operations (during GC, for example). It would be unfortunate to lose that implementation flexibility, and keeping it means that you're essentially picking the "make a copy" option.

zeeboo··on Proposal: expression to create pointer to simple types
I think I didn't communicate my point clearly. Consider this hypothetical program:

    x := make(map[int]int)
    x[0] = 5
    
    y := &x[0]
    *y = 10
    
    print(x[0]) // 5 or 10?
    
    x[0] = 6
    
    print(*y) // 6 or 10?
    
    // force the map to grow and reallocate the buckets
    for j := 1; j < 100; j++ {
        x[j] = j
    }
    *y = 11
    
    print(x[0]) // 5, 6, 10, or 11?
The crux of the problem is answering what y actually points at: the value in the map bucket, or some freshly allocated value? There are problems with whichever one you pick.

edit: changed the second print to *y instead of x[0]. thanks masklinn for catching this error.

zeeboo··on Proposal: expression to create pointer to simple types
What about `&m[x]` where m is some map? Does that heap allocate and create a copy, or is it a pointer to the actual storage slot? If the former, that's a hidden copy/allocation that didn't exist before, and if it's the latter, resizing the map invalidates the pointer, so it must be updated somehow.
zeeboo··on netaddr.IP: a new IP address type for Go
A simple map was discussed in the post. The problem it has is that it has unbounded growth. The sync.Pool approach is a best effort to avoid allocations only. If its API was changed to return sentinel pointers rather than the string, it wouldn't have the guarantee that Intern(x) == Intern(x) when x == x.
zeeboo··on netaddr.IP: a new IP address type for Go
If you can look at any widely used API that has existed for an extended period of time and not find a single tradeoff or hindsight flaw, you aren't looking hard enough.
zeeboo··on netaddr.IP: a new IP address type for Go
It also doesn't include the ipv6 zone scope. Adding that would take it to at least 28 bytes, and still have to handle all the interning problems for cheap equality.
zeeboo··on netaddr.IP: a new IP address type for Go
The standard library IP type has worked for numerous programs for a literal decade. Just because a specialized application can do a better job by leveraging, again, decades of real world experience with the language doesn't invalidate that or mean it's half-assed.

I think your statement reflects more on your own biases than reality.

zeeboo··on netaddr.IP: a new IP address type for Go
The type is designed to hold both ipv4 and ipv6 addresses.
zeeboo··on Rust is a hard way to make a web API
You can do dynamic tagged values in Go, too. It's called interface{} and everyone hates it. So this does not respond to the parent's point.
zeeboo··on Run Homebrew Natively on Apple Silicon Arm M1
It can target glibc in a cross-compile setting.

https://andrewkelley.me/post/zig-cc-powerful-drop-in-replace...

zeeboo··on Nine-year-old bug in the Go standard library enables DoS
I should not have used the word "assertion". I meant it in the more general way of "code that checks some property", not a literal "assert" feature as built in to the language.

I was just pointing out that this bug basically requires an explicit test checking for exactly the bug. Fuzzing would not have found the check for you.

zeeboo··on Nine-year-old bug in the Go standard library enables DoS
I think it's unlikely this would have been caught by fuzzing. I think you'd have to write assertions that it only read as many bytes as necessary, which is basically saying just don't write the bug in the first place.
zeeboo··on MetricsDB: TimeSeries Database for storing metrics at Twitter
I've been working on something like this for some years now: https://github.com/zeebo/rothko
zeeboo··on The northern-hemisphere winter of 2019-20 was the warmest ever on land
So after I rolled this 20 sided die 8 times and it got a 20 every time that means it's loaded? smh
zeeboo··on NPM Is Joining GitHub
Technically the Go module _proxy_ is hosted by Google. Even if the proxy went away, you'd still be able to get access to all of the packages as they're still hosted elsewhere. It just wouldn't be as fast.
zeeboo··on Go’s Features of Last Resort
Using chan struct{} is more efficient, and guarantees there is nothing being put into the channel. That's why you see it used on the Context type's Done method, for example.

https://golang.org/pkg/context/#Context

zeeboo··on The Value in Go’s Simplicity
Indeed, because semantically there is a syntactically implicit scope for every let binding. For example, in that case, the outer a is dropped after the inner a, just as if the second a had been inside of a block. There may be multiple syntactic ways to introduce a new scope.
Page 1 of 5Next →