9 ms·
Proposal: expression to create pointer to simple types
- the-dude 5y agoCan I create a pointer to a pointer?
- jerf 5y agoYes, however the utility of doing so in Go is fairly limited. Go has "pointers" but doesn't have pointer arithmetic, and the big use case of pointer-to-pointer in C is to iterate over an array of pointers via pointer arithmetic. Personally I would call them "references" since I consider pointer arithmetic to be the thing that makes pointers pointers and not just references, but that's a personal opinion, not a universally-agreed-upon definition.
- forgetfulness 5y agoPointer-pointers are nice to implement linked data structures in C; they make a lot of logic surrounding re-seating the head pointer far simpler and with fewer edge cases.
- majewsky 5y agoThis reminds me of the old adage that the level of experience of C developers can be ranked into 1 star, 2 stars, 3 stars and so on, based on the highest number of consecutive stars they use in type expressions.
- masklinn 5y agoAn other big use-case for pointers to pointers in C is pointer-type out parameters. Most of that use-case is handled by MRV, but I'm pretty sure there's the odd situation where a double pointer is either necessary or convenient (I remember seeing the odd one in Rust once in a while).
- w-m 5y agoHow exemplary that he filled in the full template questionnaire for language changes, including questions such as "Would you consider yourself a novice, intermediate, or experienced Go programmer?" (he replied "I have some experience").
- vanderZwan 5y ago> Is this about generics? > No. Not sure why, but something about this being the (first part of the) last question he had to answer makes it quite funny to me.
- marcosdumay 5y agoWhen you have two questions about a specific feature that every change proposal must answer, it's a sign that something needs improvement.
- deleted 5y ago[deleted]
- tempest_ 5y agoI found it more amusing that he listed 8 languages that he has experience with and then went out of his way to exclude JavaScript.
- aloisdg 5y agoWhen you know JavaScript enough to be able to say that you don't know JavaScript.
- zibzab 5y agoThat's basically me and C++, and I suspect I am not alone
- Simplicitas 5y agoIs JavaScript a language? <grin>
- candiddevmike 5y agoI like the second option (&int(3)) the most personally, as I find myself occasionally defining a bunch of variables before I can use them as pointers in structs. It looks and feels a lot cleaner to use this vs having new everywhere.
- cassianoleal 5y agoThat would be my preference too. Great readability, and most users would eventually try this out even before searching for the right way (I have tried it). I tend to not declare variables when the pointer is used deep into a struct because I find the back-and-forth in the editor to be bad. I usually resort to a pointer to an inline anonymous function, e.g.: a := SomeStruct{ Field: func() *int64 { x := int64(13); return &x }(), } It's ugly and verbose but after seeing it 2 or 3 times you immediately know what it's about the next time.
- fanf2 5y agoThis reminds me a lot of C99 compound literals: one of the Go suggestions looks like &int(3) which in C99 is spelled &(int){ 3 }. (I was slightly surprised when I learned that C99 compound literals are not just for structs: you can use any complete object type, and the result is an lvalue so you can take its address.)
- kevincox 5y agoI was surprised that you can't apply & to any value. I thought it was gut an ordinary operator and it would ensure that the value it was applied to would be put onto the heap. s := S{} sp := &s // Works _ = sp _ = &S{} // Works i := int32(1) ip := &i // Works! _ = ip _ = &int32(1) // Doesn't work! https://play.golang.org/p/fdgvbEwJWgh https://play.golang.org/p/fdgvbEwJWgh It seems odd that you can't apply & to a function's return value. I think the best approach would be making & work in basically any scenario. For example the following also doesn't currently work. &(int32(1) + int32(1)) It seems like it should be possible to "desugar" &X to `_tmp = X; &_tmp` and solve this weirdness.
- jerf 5y agoOne of the things I think the Go tutorials don't make a big enough deal of is that Go is relatively explicit about allocations. := isn't just a shortcut for declaring variables, it's an allocation, and an error to use it when it doesn't allocate. var X Sometype isn't just a declaration, it's an allocation. := kinda smears the clarity by not allocating if you have a variable on the left that is already allocated, and there's some other places where it kinda smears things up, but at the core, Go makes you explicitly allocate.
- gowld 5y agoI think the way to say it is that Go requires you to declare every allocation, but allows over-declaration in the case of copying. > := [...] an error to use it when it doesn't allocate. > := [...] not allocating if you have a variable on the left that is already allocated, This appears to be a contradiction. I suppose you mean something like "error to use it when there's no possible context where that line of code would allocate"; what's an example of that?
- fred256 5y agoa, b := 1, 2 If either a or b (but not both) were already defined, this won't re-define (and reallocate space for) them.
- darksaints 5y agoFor a language that has taken extreme measures to exclude generics because they are deemed to complex, this proposal is absolutely surprising to me. And I'm still not sure what practical benefit comes from it.
- jerf 5y agoI'm not sure why this would be posted to HN, honestly; it's a very "inside baseball" thing. In my personal experience this would save a lot less than one line per module. I've encountered this, but it's infrequent. The benefit is very minimal in practice.
- emodendroket 5y agoImagine you want to create an instance of a struct with many string and int pointer fields. This is actually a big pain in the ass in Go (the AWS SDK offers an aws.String helper for this reason).
- dpatterbee 5y agoFor a language that has taken extreme measures to exclude generics, Go seems to have an awful lot of accepted design proposals for generics.
- coldtea 5y agoPractical benefit in the sense of "you get a free pony" or "before you didn't have closures and now you do"? None. Practical benefit in the sense of "you get to express something in a shorter, more uniform way"? Some.
- pjmlp 5y agoWhile true, generics are on the way to be released on the end of the year as first step.
- wejick 5y ago>How would we measure it? >Eyeballing. Love this one
- dang- 5y agoPlease don't use HN comments for posting low-quality jokes, even if (perhaps "especially if") they're considered acceptable/appropriate for other communities.
- uh_uh 5y agoWhy can't &3 work? Rob says 3 does not have a type and that's a problem. Would it be possible to change the Go compiler such that 3 has a type? (I'm guessing no, at least not easily, otherwise he'd be suggesting it, but I'm curious about the reason)
- fred256 5y agoFrom the language specification: > Numeric constants represent exact values of arbitrary precision and do not overflow.
- friseurtermin 5y agoOk I think I'm not understanding this correctly then. Why does this return an error? package main import ( "fmt" ) const tst = 1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 func main() { fmt.Println("%v", tst) } Error: ./prog.go:16:17: constant 1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 overflows int See: https://play.golang.org/p/47l5qAsXD5r https://play.golang.org/p/47l5qAsXD5r
- howeyc 5y agohttps://golang.org/ref/spec#Constants https://golang.org/ref/spec#Constants > An untyped constant has a default type which is the type to which the constant is implicitly converted in contexts where a typed value is required. The default type for a number (integer) is int. If you were to add a period in that long string of zeros, the default for floating-point is float64.
- HALtheWise 5y agoIf you look closely, that error happens at the print line statement, not at the constant declaration. The constant is perfectly legal to exist as written, and you can even do constant operations like mathematics on it, you just can't legally assign it to a variable (implicitly in this case as part of the function call) if it's value is too large for the type of that variable.
- haolez 5y ago> What other languages do you have experience with? > Fortran, C, Forth, Basic, C, C++, Java, Python, and probably more. Just not JavaScript Forth is a "top-of-mind" language for Rob Pike. That's unexpected and incredibly cool :)
- dang- 5y agocxr, I've been watching you for years, and you've got potential. You inspire me to be a better mod. If you're willing to take The Oath, you can be be part of the team enjoy the following benefits: * Freedom to shitpost on as many alts as you like. * Ever heard of a double upvote? Or a triple flag? Now you have. * Monthly yoga and mindfulness with pg (you are not to make eye contact). Fully understood if this is too great a responsibility, but you are truly one with the spirit of HN and its Guidelines.
- bigdubs 5y agoIt's interesting that this can be largely implemented oneself once type parameters are part of the language (as one thread commenter pointed out with `PointerOf(t T) *T`), I'm curious what other syntactical oddities become a thing of the past once we can create more expressive and typesafe functions for common kludges.
- dang- 5y agoPlease don't use HN comments for posting low-quality jokes, even if (perhaps "especially if") they're considered acceptable/appropriate for other communities.
- phoe-krk 5y ago> (...) that has the nasty problem that 3 does not have a type (...) How is that possible? At least in Common Lisp, all literal objects have types, and the same is true of C from what I have just checked.
- earhart 5y agoGo supports untyped constants -- https://golang.org/ref/spec#Constants https://golang.org/ref/spec#Constants. It's useful for defining a named constant, and then using the name to initialize variable values of any compatible type.
- Smaug123 5y agoIt doesn't have a type in Haskell, from a certain point of view. `3` is polymorphic. Prelude> :t 3 3 :: Num p => p
- tome 5y agoIt does have a type. You just wrote it down!
- Smaug123 5y agoHence "from a certain point of view" - I would argue, in fact, that it's extremely similar to the sense in which 3 doesn't have a type in Go. Haskell's type system can express that sense, whereas Go's can't; but it's the same sense. > It is an error if the constant value cannot be represented as a value of the respective type. An untyped constant has a default type which is the type to which the constant is implicitly converted in contexts where a typed value is required, for instance, in a short variable declaration such as i := 0 where there is no explicit type. The default type of an untyped constant is bool, rune, int, float64, complex128 or string respectively, depending on whether it is a boolean, rune, integer, floating-point, complex, or string constant.
- whateveracct 5y agoI have so many BS helpers in my project to do this util.StrPtr("hello") util.BoolPtr(false) util.Int64Ptr(7) // etc This is just a gap in Go's design, so I'm glad this proposal exists :)
- gher-shyu3i 5y agoGenerics would solve the issue.
- Groxx 5y agoWell. It would reduce it to 1 (PtrTo) instead of [however many]. And unless they also add a new top-level func like that, it's still a `package.PtrTo` rather than `&`. And `&`'s special abilities on only composite literals remains.
- majewsky 5y agoNot entirely. Someone in the comments of the issue suggests to implement this with generics as: func PointerOf[T any](t T) *T { return &t } But that has a nasty gotcha: func Process(x *int32) { if (x != nil) { fmt.Println(*x + 5); } } func main() { Process(nil); //ok x := i32(5) Process(&x); //ok Process(PointerOf(5)); //BOOM: cannot use PointerOf(5) (value of //type *int) as *int32 value in argument to Process } Go's type coercion is quite primitive. It strictly works inside-out (propagating types strictly upwards in the AST), with the only exception that a numeric literal can be coerced into a specific numeric type by considering the immediate parent in the AST. So when you have `func f(x int32)` and you call it as `f(5)`, the literal 5 gets coerced into int32 to match the context it appears in. (The same strategy is also applied to determine the type of a nil literal.) However, in `Process(PointerOf(5))`, the immediate surrounding of the literal 5 (the PointerOf call) does not coerce the literal into a specific type, so it takes on its default type, int. The proposal (or, to be exact, both proposals) avoids this gotcha by requiring a type to be stated explicitly. Process(new(i32, 5)); Process(&i32(5));
- 5y ago
- sylvinus 5y agoBest part of this proposal from Go's co-creator: > Would you consider yourself a novice, intermediate, or experienced Go programmer? I have some experience.
- nemo1618 5y agoPersonally, I've only seen this crop up in one place: structs that signal optional fields via pointers. Are there other usecases?
- BrissyCoder 5y agoThis is why we need to stop inventing new languages.