4 ms·
A difference between Go and Java is that a null Regex in Java will not be implicitly converted to a non-null Stringable containing a null Regex. If you'd like,
by anonymoushn 4y ago
A difference between Go and Java is that a null Regex in Java will not be implicitly converted to a non-null Stringable containing a null Regex.
If you'd like, I can post about "implicit conversion from nil pointers to non-nil interfaces containing nil pointers that can only be checked for nil using reflection, combined with interfaces that work by duck typing and an existing body of code that pervasively uses struct pointer receivers in methods that panic when passed a nil pointer, even if it was a nil pointer contained in a non-nil interface" but that's a bit of a mouthful.
- deleted 4y ago[deleted]
- throwaway894345 4y ago> A difference between Go and Java is that a null Regex in Java will not be implicitly converted to a non-null Stringable containing a null Regex. You have it exactly backwards--you're arguing that Go should implicitly convert a not-nil interface (that is implemented by a nil pointer) to a nil interface so that Go interfaces behave more like Java interfaces, but Go isn't doing any implicit conversions (unless you consider "assigning a concrete value to an interface" to be an "implicit conversion", but Java does this too). > implicit conversion from nil pointers to non-nil interfaces containing nil pointers Again, Go doesn't do any such implicit conversion, and you're arguing the position that it should. An interface is just a tuple containing a pointer to the data and a pointer to the type `(pdata, ptype)`. A nil interface is `(nil, nil)`, and an interface that is implemented by a nil pointer is `(nil, <pointer-to-concrete-type>)`. You're arguing the position that the latter should be implicitly converted to the former, but this would break code that uses nil as a valid value. The root cause of the problem isn't how Go handles nil pointers in interfaces, but rather that Go has nil pointers, interfaces, etc at all. Go gives you no way to express that a reference type can't be nil, but ideally it would have an enum system like Rust's that makes optionality an opt-in property via `Option<T>`. If an interface `Bar` is implemented by `*Foo` and neither `*Foo` nor `Bar` can be nil, then this problem largely goes away. If `Bar` is implemented by `Option<*Foo>`, then `Option<*Foo>`'s methods need to handle both the `Some(*Foo)` and `None` (i.e., nil) cases. > that can only be checked for nil using reflection You don't need reflection: i, ok := (iface).(*int) if !ok { fmt.Println("`iface` is not an `*int`") } if i == nil { fmt.Println("`iface` contains a nil pointer") } fmt.Printf("`iface` contains a pointer to `%d`", i)**
- anonymoushn 4y ago> Go isn't doing any implicit conversions What do you call it when you assign a value of one type to a variable of another type and the language creates a new value, different from the one you were assigning, and stores that new value in the variable? In C++ this is called "implicit conversion." Here's the tutorial again: var a Abser f := MyFloat(-math.Sqrt2) v := Vertex{3, 4} a = f // a MyFloat implements Abser a = &v // a *Vertex implements Abser The last two lines involve constructing a new value for the LHS of a type that differs from the type on the RHS without any function calls, constructors, "make" keywords, etc. What word would you like to use for this? You could just as well have a patch that changes the type of a single variable from *Vertex to Abser or changes the return type of a single function from a type that matches an interface to the interface, and that would also create an assignment that creates a new value of the new type that will panic in contexts the old one would not have panicked, even though the programmer has not added any code saying "please construct an Abser (type, pointer) tuple from my pointer." > Go should implicitly convert a not-nil interface (that is implemented by a nil pointer) to a nil interface I am not arguing for that. > unless you consider "assigning a concrete value to an interface" to be an "implicit conversion", but Java does this too I guess, but this is much less of a conversion than Go is performing because the runtime value does not change at all. It's the same pointer, not a tuple containing the pointer. Unlike in Go, this assignment may very often be correctly implemented by a sequence of 0 instructions! Importantly, the meaning of "foo == null" is unchanged. This is not because Java performs implicit conversions of interface types to specific pointer types at the null check. It's because in Java interfaces are unable to express having a concrete value of a specific class which is null, because they are just pointers. One might say "Java interfaces do not have inner and outer nil values" as a shorthand for this. > Go gives you no way to express that a reference type can't be nil I agree that this would solve the problem. > You don't need reflection: You don't need reflection if you statically build an exhaustive list of all pointer types that match the interface in the whole program but don't actually match the interface in the sense that the methods don't handle nil, then generate code to handle each of them. This just doesn't seem like a reasonable option because sometimes people make libraries so they can't necessarily do static analysis of the whole program at the point where they are writing the code. It also sort of defeats the purpose of interfaces, I guess.