Re: [go-nuts] Generics: after type lists

2020-09-07 Thread targe...@gmail.com
Sorry for interfering. I've gathered statements and expressions which look 
like candidates for interface-based generalization. Interface and method 
names are just placeholders. Generic interfaces for collections like slice 
or map are different beasts. Will post thoughts on them later. 

I personally think that most used interface wrappers for predefined types 
would be range support and generalized collections. Maybe custom key types 
for maps and custom map hasher.

*Comparison operators*

 "==", "!=", "<", ">", "<=", ">="

These can be split into two groups - equatable and ordered. Not all types 
which may be compared equals can be ordered

type Equatable[T] interface {
Equals(T, T) bool
}
type Ordered[T] interface {
Compare(T, T) int // < 0 if less, > 0 if greater, 0 if equals
}

Equals can be easily implemented through Ordered via

func[T] (Ordered[T]* self) Equals(left, right T) bool {
return self.Compare(left right) == 0
}

Possible application for default interface methods but off-topic here

*Arithmetic operators*

*Unary operators "+", "-", "^"*

type UnaryOp[T] interface {
Op(T) T
}

where Op can be Plus, Minus, BitwiseComplement

*Binary operators "+", "-", "*", "/", "%", "&", "|", "^", "&^"*

type BinaryOp[T] interface {
Op(T, T) T
}

where Op is "Add", "Sub", "Mul", "Div", "Mod", "BitAnd", "BitOr", "BitXor", 
"BitAndNot"

Bit-shift operators look almost the same except having different second 
argument

type BinaryOp[T] interface {
Op(T, uint) T
}

where "Op" is "ShiftLeft" or "ShiftRight"

*Assign-op operators "+=", "-=", "*=", "/=", "%=", "&=", "|=", "^=", "&^="*

type BinaryOpAssign[T] interface {
OpAssign(T)
}

where Op is "Add", "Sub", "Mul", "Div", "Mod", "BitAnd", "BitOr", "BitXor", 
"BitAndNot"

Default implementation through normal operation would  look like

func[T] (BinaryOp[T]* self) OpAssign(right T) {
*self = self.Op(*self, right)
}

Except shift operators which would look like

type BinaryOpAssign[T] interface {
OpAssign(uint)
}

where "Op" is "ShiftLeft" or "ShiftRight"

*String concatenation*

Uses interfaces "BinaryAdd" and "BinaryAddAssign"

*Logical operators*

Applied only to booleans, so I see no good reason to add generic interfaces 
for them

*Address operators*

Should not have their own interface since they don't assume any kind of 
type-specific behavior

*Receive operator and send statement*

May be considered in future. ATM I don't see good application for 
channel-like types except channels themselves

*Increment and decrement*

type Incrementable[T] interface {
Increment()
}
type Decrementable[T] interface {
Decrement()
}

*Assignment*

Not subject for generalization since it shouldn't be overridden

*For statements with range clause*

type Range[K, V] interface {
Next() K, V, bool
}

Slice's or string's key would be respective index
Channel looks more like exception here since it introduces asynchronous 
iteration and produces single value.



On Saturday, August 15, 2020 at 3:14:30 PM UTC+3 rog wrote:

> On Sat, 15 Aug 2020 at 04:57, Patrick Smith  wrote:
>
>> On Thu, Aug 13, 2020 at 11:25 PM Patrick Smith  
>> wrote:
>> > I tried out a few different implementations, evaluating the polynomial
>> > instead of finding roots,
>> > at https://go2goplay.golang.org/p/g8bPHdg5iMd . As far as I can tell,
>> > there is no sensible way to
>> > do it with an interface that is implemented directly by *big.Float; we
>> > need to wrap *big.Float
>> > in a wrapper type in any case.
>>
>> After looking at the draft again, and seeing the Settable example
>> there, I realized we can do it using big.Float directly, but it needs
>> two interfaces, one matching big.Float and one matching *big.Float. I
>> have updated my examples at https://go2goplay.golang.org/p/auSkvhWSNHn
>
>
> I think that works pretty well, and seems to be the direction that things 
> are going in.
> Here's your example cleaned up a bit to show just that latest example, and 
> also
> showing how it looks when adapting a built-in type:
>
> https://go2goplay.golang.org/p/eFIvHocOC75
>
> It's possible to build a generic adaptor type from the value-style 
> interface to the pointer-style interface, which you might find interesting:
>
>   https://go2goplay.golang.org/p/NiQY_-kWvu8
>
> This could *almost* work on image.Point, except that Point.Mul has the 
> wrong signature.
>
>   cheers,
> rog.
>
>>
>> .
>
>
>>
>> -- 
>> You received this message because you are subscribed to the Google Groups 
>> "golang-nuts" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to golang-nuts...@googlegroups.com.
>>
> To view this discussion on the web visit 
>> https://groups.google.com/d/msgid/golang-nuts/CAADvV_vxU7nUJ16X5xwBYhiOPVrzp%3DzrX%3DU4UTgBsOQJ2RnMuQ%40mail.gmail.com
>> .
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop 

Re: [go-nuts] Re: How to know if interface{} data is nil w/o reflecting?

2020-09-02 Thread targe...@gmail.com
> I gave you a third solution: Having a separate identifier for the zero 
value of interfaces. 

It doesn't solve issue at hand. The issue is, conversion from typed nil 
pointer to interface results in non-nil interface with valid vtable pointer 
and nil receiver. And only limited set of specifically crafted 
implementations supports nil receiver. What would be the meaning of "none" 
interface? If it's nil data pointer, it would result in false-negatives for 
implementations which support nil receiver.

On Thursday, August 27, 2020 at 3:13:14 PM UTC+3 axel.wa...@googlemail.com 
wrote:

> On Thu, Aug 27, 2020 at 12:53 PM targe...@gmail.com  
> wrote:
>
>> Because you then must remember about this specific case *every time *you 
>> cast potentially nil pointer variable to interface. Every time you must 
>> write `if x != nil { return x; } else { return nil; }` instead of just 
>> `return x;`
>>
>
> This is true, but that alone is not indicative of a problem. You have to 
> remember that `select` does a pseudo-random selection of cases everytime 
> you use it, that you can't write to nil-maps, that dereferencing a 
> nil-pointer might panic, that an index-expression might panic, that 
> integer-addition might overflow, that floating-point math has 
> counter-intuitive edge-cases, that init-functions run before main… you have 
> to remember a *lot* of things every time you need them.
>
> I don't want to sound dismissive (as I said, I do think there is obviously 
> *some* problem) but I don't run into cases where I would even be *tempted* 
> to do this. Like, in your example, you'd need to a) have a declared 
> pointer, b) would need to be oblivious to the fact on whether or not it's 
> nil and c) it would have to be an invalid value if so and d) it would have 
> to be a problem not caught by other means (e.g. returning a non-nil error 
> alongside it). And when I am tempted to do this, I just know that the 
> interface value will still be non-nil. And even when I don't, the most 
> trivial of testing catches the problem.
>
> Like, I'm not saying it *never* happens or even that it never happens *to 
> me*. But it seems very rarely cause significant problems and I don't 
> understand why people put it so high up their list of being confusing or 
> hard to remember.
>
>  
>
>> > But solutions that try to give special treatment to nil-values when 
>> they are put into interfaces just seem wrong to me. 
>>
>> Because nils or null pointers are indeed special. They mean "Points to no 
>> data". So dereference operation on such pointer leads to exceptional state. 
>> In fact, nullable pointer in terms of richer type systems is a sum-type 
>> `nil|*T` where `*T` always points to some valid object
>>
>
> Okay. But even in those languages, `nil` (or `None` or `Nothing` or 
> whatever you call it is still a perfectly acceptable value, with 
> significant semantic meaning. Yes, in those languages the compiler is able 
> to prevent you from dereferencing it, but the value is still just a value 
> like any other. If anything, the fact that even languages with very rich 
> type-systems include types like `Maybe` shows how important `nil` as a 
> possible value is. Otherwise you wouldn't have to put it in artificially.
>
> > The rule is very simple: A nil-interface is one that has no dynamic 
>> value. All values are treated the same for this purpose. All types are 
>> treated the same. I don't understand how that is anything but simple and 
>> consistent. It might be less understandable for some other reason, but I 
>> don't think it's simplicity or consistency.
>>
>> Please don't forget that interface pointer isn't simple. It's a so-called 
>> "fat pointer" which consists of pointer to data and pointer to methods 
>> table. Thus, we have 4 potential states
>>
>
> That's one way to look at it. And you are trying to make that way look 
> pretty complicated. But you are talking about implementation details. It's 
> like arguing strings are very complicated, because they can a) be 
> string-constants held in read-only memory, b) be heap-allocated or c) be 
> stack-allocated.
>
> Another way to look at it is that an interface is a type, that may or may 
> not contain a dynamic value of some other type and allows calling methods 
> on it. If it doesn't, the interface-value is nil. If it does, it isn't. 
> That's the way interfaces are defined in the spec.
>
> I am still against teaching interfaces to newcomers as "two pointers, one 
> to a type and one to a value". It leads to exactly the kinds of 
> confusion you are expressing here, because people think about the 
> representation and 

Re: [go-nuts] Re: How to know if interface{} data is nil w/o reflecting?

2020-09-02 Thread targe...@gmail.com
> Other people have said this too, but I want to emphasize that there 
are not 4 potential states of an interface value. There are 2 
potential states: 1) interface does not hold any value, and is == nil; 
2) interface holds a value, and is != nil. 

Indeed, there are 2 states of interface observable from outside. Although 
one of these observable states gets expressed through 2 states invisible to 
outer world. Which isn't a problem on its own.

> When you start talking about an interface as a fat pointer you are 
talking about how those 2 states are implemented. There are other 
possible implementations 

Yes. And that's not an issue on its own. The issue is, such implementation 
detail kind of "leaks" sometimes and bites you when you don't expect. And 
it does so because the way it gets constructed omits one specific detail of 
conversion from pointer to interface.

On Thursday, August 27, 2020 at 9:58:21 PM UTC+3 Ian Lance Taylor wrote:

> On Thu, Aug 27, 2020 at 3:53 AM targe...@gmail.com  
> wrote:
> >
> > Please don't forget that interface pointer isn't simple. It's a 
> so-called "fat pointer" which consists of pointer to data and pointer to 
> methods table. Thus, we have 4 potential states - (nil, nil), (nil, 
> pointer), (pointer, nil) and (pointer,pointer). First one is just ordinary 
> nil interface. Last one is just ordinary interface pointer with all 
> operations callable without issue (as long as they're properly implemented, 
> of course). Third one with valid data pointer and nil table pointer can be 
> AFAIK created only through reflection and is safely considered "invalid 
> state". We're left with second state with nil data pointer and valid table 
> pointer, making interface methods callable on it. It wouldn't be a problem 
> - if such state couldn't be created by merely casting typed nil pointer 
> (typed pointer variable with nil value) to interface. Why is this an issue? 
> Because most interface implementations require valid data pointer. "Static" 
> (i.e. not needing data) implementations can be considered corner case.
>
> Other people have said this too, but I want to emphasize that there
> are not 4 potential states of an interface value. There are 2
> potential states: 1) interface does not hold any value, and is == nil;
> 2) interface holds a value, and is != nil.
>
> When you start talking about an interface as a fat pointer you are
> talking about how those 2 states are implemented. There are other
> possible implementations, and in fact the implementation in gccgo used
> to be different. And even the implementation in the gc compiler has
> changed; at one time ints and other small values were stored directly
> in the interface value, but now we instead store a pointer to the
> data.
>
> Ian
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/5de71d2c-958b-47e5-8bd2-4e54b3d14150n%40googlegroups.com.


Re: [go-nuts] Re: How to know if interface{} data is nil w/o reflecting?

2020-08-27 Thread targe...@gmail.com
> And for different types this is pretty normal as you can have
>x == 0.2   //  true
>y = int(x)
>float64(y) != 0.2  // true too

A more correct analogy would've been:
var x := 0.2
var y := float32(x)
math.IsNaN(float64(y)) // true in this analogy

> It is a property of all float types
I used floats as an example of type with such "kaboom" value.

> For the rest of the argument: It _really_ isn't  an actual problem. In 10 
years of Go this happened maybe three time to me and was dead simple to 
identify.

I faced this issue twice. Once caused by my code and the other by not mine. 
Second time it wasn't that simple to identify because Schroedingerface 
travelled quite a long distance from its birthplace. Anyway, this issue 
seems to get raised repeatedly. 

On Thursday, August 27, 2020 at 2:16:34 PM UTC+3 Volker Dobler wrote:

> On Thursday, 27 August 2020 11:39:11 UTC+2, targe...@gmail.com wrote:
>>
>> To me, if `x == nil` and then `y != nil` after `y = x` is much more 
>> confusing.
>>
>
> This can happen only if x and y have different  types.
> And for different types this is pretty normal as you can have
> x == 0.2   //  true
> y = int(x)
> float64(y) != 0.2  // true too
> With the only difference that you have explicit type conversions
> where interface assignment is implicit.
>
> And this is not even the strangest thing that can happen:
> NaN floats are especially peculiar. You can have
>x := y
>x != y  // true
>x != x  // also true
>  
> That is something everybody has to learn once. It is a
> property of all float types. Different types behave differently.
> And this is true not only for operators like +, - or / but also
> for operators like =, == and !=.
>
> For the rest of the argument: It _really_ isn't  an actual
> problem. In 10 years of Go this happened maybe three
> time to me and was dead simple to identify.
>
> V.
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/3efd9d39-0360-4efc-b47e-54482cd7dd35n%40googlegroups.com.


Re: [go-nuts] Re: How to know if interface{} data is nil w/o reflecting?

2020-08-27 Thread targe...@gmail.com
> I'm mostly form C++ land 
from of course :)

On Thursday, August 27, 2020 at 2:01:33 PM UTC+3 targe...@gmail.com wrote:

> I know this. I'm mostly form C++ land, so you may imagine how many warts 
> are there "on the top of the index finger" :)
> I'm merely speaking against opinion that Shroedingerface is not a problem 
> at all.
> On Thursday, August 27, 2020 at 1:55:54 PM UTC+3 ren...@ix.netcom.com 
> wrote:
>
>> This will be a Go wart that will never go away. All languages have warts. 
>> This one just happens to be on the top of the index finger  There is so 
>> little utility in a nil interface but it’s there. 
>>
>> On Aug 27, 2020, at 5:14 AM, 'Axel Wagner' via golang-nuts <
>> golan...@googlegroups.com> wrote:
>>
>> 
>>
>>
>> On Thu, Aug 27, 2020 at 11:39 AM targe...@gmail.com  
>> wrote:
>>
>>> > I'm saying the current situation is less confusing than what you 
>>> describe, yes.
>>> > AIUI, with what you describe, if I have a variable `x` of type `*T` 
>>> and an interface variable `y`, then `y = x` and `y = (*T)(x)` have 
>>> different semantics. I think it is strange to have a conversion of `x` *to 
>>> its own type* have any sort of semantic implication. It should be a no-op.
>>>
>>> It may be expressed in some different way. To me, if `x == nil` and then 
>>> `y != nil` after `y = x` is much more confusing.
>>>
>>
>> And obviously you are not alone. Even though I really don't understand 
>> why this isn't just one of those "you learn about it, you know about it, 
>> you never run into any problems again" type of things. It does seem to come 
>> up sufficiently often to be a problem. And there are solutions that I think 
>> are fine. For example, using a different identifier (say `none`) to denote 
>> the zero-value of interfaces would be fine by me.
>>
>> But solutions that try to give special treatment to nil-values when they 
>> are put into interfaces just seem wrong to me. They single out nil-values 
>> as somehow special or less valid than other values. They single out 
>> pointer/slice/map/chan types as somehow special over int/bool/string/… 
>> types. It just seems undeniable to me, that they make the language *less* 
>> consistent.
>>
>> If you ask my opinion, I would make interfaces compare to nil on just 
>>> data pointer. If one wanted interface which doesn't require data, he 
>>> could've easily created one with static stub variable. No additional 
>>> checks, no "semi-nil" fat pointers, everything simple and consistent.
>>>
>>
>> The rule is very simple: A nil-interface is one that has no dynamic 
>> value. All values are treated the same for this purpose. All types are 
>> treated the same. I don't understand how that is anything but simple and 
>> consistent. It might be less understandable for some other reason, but I 
>> don't think it's simplicity or consistency.
>>
>>
>>> On Thursday, August 27, 2020 at 12:20:59 PM UTC+3 
>>> axel.wa...@googlemail.com wrote:
>>>
>>>> On Thu, Aug 27, 2020 at 11:10 AM targe...@gmail.com  
>>>> wrote:
>>>>
>>>>> it would definitely. Though price for consistency looks very much 
>>>>> acceptable.
>>>>
>>>>
>>>> I don't think "consistency" is at all the right word here. If anything, 
>>>> things would get *less* consistent, not more.
>>>>
>>>> > Personally, I would also find it very confusing, if converting a T to 
>>>>> a T changed program behavior
>>>>> Sorry, didn't get it. Are you saying that nil pointer -> nil interface 
>>>>> is more confusing?
>>>>>
>>>>
>>>> I'm saying the current situation is less confusing than what you 
>>>> describe, yes.
>>>>
>>>> AIUI, with what you describe, if I have a variable `x` of type `*T` and 
>>>> an interface variable `y`, then `y = x` and `y = (*T)(x)` have different 
>>>> semantics. I think it is strange to have a conversion of `x` *to its own 
>>>> type* have any sort of semantic implication. It should be a no-op.
>>>>
>>>>
>>>>> On Thursday, August 27, 2020 at 11:49:16 AM UTC+3 
>>>>> axel.wa...@googlemail.com wrote:
>>>>>
>>>>>> On Thu, Aug 27, 2020 at 10:06 AM targe...@gmail.com <
>>>>>> targe...@gmail.com> wrote:
>>>>&

Re: [go-nuts] Re: How to know if interface{} data is nil w/o reflecting?

2020-08-27 Thread targe...@gmail.com
I know this. I'm mostly form C++ land, so you may imagine how many warts 
are there "on the top of the index finger" :)
I'm merely speaking against opinion that Shroedingerface is not a problem 
at all.
On Thursday, August 27, 2020 at 1:55:54 PM UTC+3 ren...@ix.netcom.com wrote:

> This will be a Go wart that will never go away. All languages have warts. 
> This one just happens to be on the top of the index finger  There is so 
> little utility in a nil interface but it’s there. 
>
> On Aug 27, 2020, at 5:14 AM, 'Axel Wagner' via golang-nuts <
> golan...@googlegroups.com> wrote:
>
> 
>
>
> On Thu, Aug 27, 2020 at 11:39 AM targe...@gmail.com  
> wrote:
>
>> > I'm saying the current situation is less confusing than what you 
>> describe, yes.
>> > AIUI, with what you describe, if I have a variable `x` of type `*T` and 
>> an interface variable `y`, then `y = x` and `y = (*T)(x)` have different 
>> semantics. I think it is strange to have a conversion of `x` *to its own 
>> type* have any sort of semantic implication. It should be a no-op.
>>
>> It may be expressed in some different way. To me, if `x == nil` and then 
>> `y != nil` after `y = x` is much more confusing.
>>
>
> And obviously you are not alone. Even though I really don't understand why 
> this isn't just one of those "you learn about it, you know about it, you 
> never run into any problems again" type of things. It does seem to come up 
> sufficiently often to be a problem. And there are solutions that I think 
> are fine. For example, using a different identifier (say `none`) to denote 
> the zero-value of interfaces would be fine by me.
>
> But solutions that try to give special treatment to nil-values when they 
> are put into interfaces just seem wrong to me. They single out nil-values 
> as somehow special or less valid than other values. They single out 
> pointer/slice/map/chan types as somehow special over int/bool/string/… 
> types. It just seems undeniable to me, that they make the language *less* 
> consistent.
>
> If you ask my opinion, I would make interfaces compare to nil on just data 
>> pointer. If one wanted interface which doesn't require data, he could've 
>> easily created one with static stub variable. No additional checks, no 
>> "semi-nil" fat pointers, everything simple and consistent.
>>
>
> The rule is very simple: A nil-interface is one that has no dynamic value. 
> All values are treated the same for this purpose. All types are treated the 
> same. I don't understand how that is anything but simple and consistent. It 
> might be less understandable for some other reason, but I don't think it's 
> simplicity or consistency.
>
>
>> On Thursday, August 27, 2020 at 12:20:59 PM UTC+3 
>> axel.wa...@googlemail.com wrote:
>>
>>> On Thu, Aug 27, 2020 at 11:10 AM targe...@gmail.com  
>>> wrote:
>>>
>>>> it would definitely. Though price for consistency looks very much 
>>>> acceptable.
>>>
>>>
>>> I don't think "consistency" is at all the right word here. If anything, 
>>> things would get *less* consistent, not more.
>>>
>>> > Personally, I would also find it very confusing, if converting a T to 
>>>> a T changed program behavior
>>>> Sorry, didn't get it. Are you saying that nil pointer -> nil interface 
>>>> is more confusing?
>>>>
>>>
>>> I'm saying the current situation is less confusing than what you 
>>> describe, yes.
>>>
>>> AIUI, with what you describe, if I have a variable `x` of type `*T` and 
>>> an interface variable `y`, then `y = x` and `y = (*T)(x)` have different 
>>> semantics. I think it is strange to have a conversion of `x` *to its own 
>>> type* have any sort of semantic implication. It should be a no-op.
>>>
>>>
>>>> On Thursday, August 27, 2020 at 11:49:16 AM UTC+3 
>>>> axel.wa...@googlemail.com wrote:
>>>>
>>>>> On Thu, Aug 27, 2020 at 10:06 AM targe...@gmail.com <
>>>>> targe...@gmail.com> wrote:
>>>>>
>>>>>> Not sure if it was mentioned here, but IMO the main issues isn't nil 
>>>>>> data itself, but how easy it's created. It'd be much less of a surprise 
>>>>>> if 
>>>>>> creating nil-data required explicit cast from nil struct pointer to 
>>>>>> interface pointer and resulted in just nil interface pointer in case of 
>>>>>> implicit cast. Though such change is almost certainly breaking one.
>&

Re: [go-nuts] Re: How to know if interface{} data is nil w/o reflecting?

2020-08-27 Thread targe...@gmail.com
> Even though I really don't understand why this isn't just one of those 
"you learn about it, you know about it, you never run into any problems 
again" type of things.

Because you then must remember about this specific case *every time *you 
cast potentially nil pointer variable to interface. Every time you must 
write `if x != nil { return x; } else { return nil; }` instead of just 
`return x;` Does this make language simpler?

> But solutions that try to give special treatment to nil-values when they 
are put into interfaces just seem wrong to me. 

Because nils or null pointers are indeed special. They mean "Points to no 
data". So dereference operation on such pointer leads to exceptional state. 
In fact, nullable pointer in terms of richer type systems is a sum-type 
`nil|*T` where `*T` always points to some valid object, and thus 
dereferencing it is valid. map/slice/chan types are pointers in disguise. 
By the way, AFAIK string isn't "special" here because "" and nil are 
treated equally. As for comparison to int/bool, you can safely perform all 
the operations on 0 the same way as on non-zero integers, except dividing 
by it. Same for `false`. nil can be vaguely compared to floats' NaN - 
except NaN is a potential (albeit rare) result of any operation on floats, 
while pointer cannot become invalid through dereference.

> The rule is very simple: A nil-interface is one that has no dynamic 
value. All values are treated the same for this purpose. All types are 
treated the same. I don't understand how that is anything but simple and 
consistent. It might be less understandable for some other reason, but I 
don't think it's simplicity or consistency.

Please don't forget that interface pointer isn't simple. It's a so-called 
"fat pointer" which consists of pointer to data and pointer to methods 
table. Thus, we have 4 potential states - (nil, nil), (nil, pointer), 
(pointer, nil) and (pointer,pointer). First one is just ordinary nil 
interface. Last one is just ordinary interface pointer with all operations 
callable without issue (as long as they're properly implemented, of 
course). Third one with valid data pointer and nil table pointer can be 
AFAIK created only through reflection and is safely considered "invalid 
state". We're left with second state with nil data pointer and valid table 
pointer, making interface methods callable on it. It wouldn't be a problem 
- if such state couldn't be created by merely casting typed nil pointer 
(typed pointer variable with nil value) to interface. Why is this an issue? 
Because most interface implementations require valid data pointer. "Static" 
(i.e. not needing data) implementations can be considered corner case.

So if we're hypothetically designing language with such fat pointers, how 
can we solve this issue?

One way is golang's way, where interface is nil when both components are 
nil. In such case, implicit casts mentioned above can easily lead to 
invalid state. To circumvent this, such state (nil, pointer) is better 
created only explicitly, "I know what I'm doing".

The other way is to check interface against nil only by its data pointer. 
When it's created from typed pointer, it always gets valid table pointer 
and data pointer from original typed one. When it's compared to nil, it's 
compared only with its data pointer. Thus, nil translates to nil, and we 
avoid second Shroedinger's state. If we wanna static implementation, we 
just create static variable which is `struct{}` and return pointer to it. 
Alas, this approach is no-go because it involves breakage too deep.
On Thursday, August 27, 2020 at 1:14:17 PM UTC+3 axel.wa...@googlemail.com 
wrote:

> On Thu, Aug 27, 2020 at 11:39 AM targe...@gmail.com  
> wrote:
>
>> > I'm saying the current situation is less confusing than what you 
>> describe, yes.
>> > AIUI, with what you describe, if I have a variable `x` of type `*T` and 
>> an interface variable `y`, then `y = x` and `y = (*T)(x)` have different 
>> semantics. I think it is strange to have a conversion of `x` *to its own 
>> type* have any sort of semantic implication. It should be a no-op.
>>
>> It may be expressed in some different way. To me, if `x == nil` and then 
>> `y != nil` after `y = x` is much more confusing.
>>
>
> And obviously you are not alone. Even though I really don't understand why 
> this isn't just one of those "you learn about it, you know about it, you 
> never run into any problems again" type of things. It does seem to come up 
> sufficiently often to be a problem. And there are solutions that I think 
> are fine. For example, using a different identifier (say `none`) to denote 
> the zero-value of interfaces would be fine by me.
>
> But solutions that try to give special treatment to nil-values when they 
&

Re: [go-nuts] Re: How to know if interface{} data is nil w/o reflecting?

2020-08-27 Thread targe...@gmail.com
 > I'm saying the current situation is less confusing than what you 
describe, yes.
> AIUI, with what you describe, if I have a variable `x` of type `*T` and 
an interface variable `y`, then `y = x` and `y = (*T)(x)` have different 
semantics. I think it is strange to have a conversion of `x` *to its own 
type* have any sort of semantic implication. It should be a no-op.

It may be expressed in some different way. To me, if `x == nil` and then `y 
!= nil` after `y = x` is much more confusing. If you ask my opinion, I 
would make interfaces compare to nil on just data pointer. If one wanted 
interface which doesn't require data, he could've easily created one with 
static stub variable. No additional checks, no "semi-nil" fat pointers, 
everything simple and consistent.

On Thursday, August 27, 2020 at 12:20:59 PM UTC+3 axel.wa...@googlemail.com 
wrote:

> On Thu, Aug 27, 2020 at 11:10 AM targe...@gmail.com  
> wrote:
>
>> it would definitely. Though price for consistency looks very much 
>> acceptable.
>
>
> I don't think "consistency" is at all the right word here. If anything, 
> things would get *less* consistent, not more.
>
> > Personally, I would also find it very confusing, if converting a T to a 
>> T changed program behavior
>> Sorry, didn't get it. Are you saying that nil pointer -> nil interface is 
>> more confusing?
>>
>
> I'm saying the current situation is less confusing than what you describe, 
> yes.
>
> AIUI, with what you describe, if I have a variable `x` of type `*T` and an 
> interface variable `y`, then `y = x` and `y = (*T)(x)` have different 
> semantics. I think it is strange to have a conversion of `x` *to its own 
> type* have any sort of semantic implication. It should be a no-op.
>
>
>> On Thursday, August 27, 2020 at 11:49:16 AM UTC+3 
>> axel.wa...@googlemail.com wrote:
>>
>>> On Thu, Aug 27, 2020 at 10:06 AM targe...@gmail.com  
>>> wrote:
>>>
>>>> Not sure if it was mentioned here, but IMO the main issues isn't nil 
>>>> data itself, but how easy it's created. It'd be much less of a surprise if 
>>>> creating nil-data required explicit cast from nil struct pointer to 
>>>> interface pointer and resulted in just nil interface pointer in case of 
>>>> implicit cast. Though such change is almost certainly breaking one.
>>>>
>>>
>>> This would require to insert extra nil-checks when assigning a 
>>> pointer-value to an interface, as the compiler can't know if a pointer is 
>>> nil or not. Personally, I would also find it very confusing, if converting 
>>> a T to a T changed program behavior (though arguably, there is one such 
>>> case currently with `uintptr(uintptr(unsafe.Pointer))`. But usage of 
>>> `unsafe` seems sufficiently advanced).
>>>  
>>>
>>>>
>>>> On Monday, August 24, 2020 at 7:08:17 AM UTC+3 alex.be...@gmail.com 
>>>> wrote:
>>>>
>>>>> Can we at least move with the 
>>>>> https://github.com/golang/go/issues/22729 , please? Anything will 
>>>>> help with the current mess.
>>>>>
>>>>>
>>>>> On Sunday, August 23, 2020 at 8:52:30 PM UTC-7, Ian Lance Taylor wrote:
>>>>>
>>>>>> On Sun, Aug 23, 2020 at 1:16 PM Denis Cheremisov 
>>>>>>  wrote: 
>>>>>> > 
>>>>>> > You may use something like this 
>>>>>> > 
>>>>>> > value2 := 
>>>>>> *(*uint64)(unsafe.Pointer(uintptr(unsafe.Pointer()) + 8)) 
>>>>>> > if value2 == 0 { 
>>>>>> > return true 
>>>>>> > } 
>>>>>> > 
>>>>>> > on AMD64, should work also for any 64 bit architecture (at least I 
>>>>>> believe so). Remember though this is hacky and may stop working once. 
>>>>>>
>>>>>> You could do that, but please don't. 
>>>>>>
>>>>>> Ian 
>>>>>>
>>>>>>
>>>>>> > воскресенье, 23 августа 2020 г. в 22:58:51 UTC+3, Aviv Eyal: 
>>>>>> >> 
>>>>>> >> I was trying to show that the current behavior is confusing and 
>>>>>> that fmt.Print() needing to resort to panic-and-recover is kinda code 
>>>>>> smell, but I sorts-of convinced myself that the current behavior is 
>>>>>> right, 
>>>>>> or at least consistent. 
>&

Re: [go-nuts] Re: How to know if interface{} data is nil w/o reflecting?

2020-08-27 Thread targe...@gmail.com
 > This would require to insert extra nil-checks when assigning a 
pointer-value to an interface, as the compiler can't know if a pointer is 
nil or not.
it would definitely. Though price for consistency looks very much 
acceptable.

> Personally, I would also find it very confusing, if converting a T to a T 
changed program behavior
Sorry, didn't get it. Are you saying that nil pointer -> nil interface is 
more confusing?

On Thursday, August 27, 2020 at 11:49:16 AM UTC+3 axel.wa...@googlemail.com 
wrote:

> On Thu, Aug 27, 2020 at 10:06 AM targe...@gmail.com  
> wrote:
>
>> Not sure if it was mentioned here, but IMO the main issues isn't nil data 
>> itself, but how easy it's created. It'd be much less of a surprise if 
>> creating nil-data required explicit cast from nil struct pointer to 
>> interface pointer and resulted in just nil interface pointer in case of 
>> implicit cast. Though such change is almost certainly breaking one.
>>
>
> This would require to insert extra nil-checks when assigning a 
> pointer-value to an interface, as the compiler can't know if a pointer is 
> nil or not. Personally, I would also find it very confusing, if converting 
> a T to a T changed program behavior (though arguably, there is one such 
> case currently with `uintptr(uintptr(unsafe.Pointer))`. But usage of 
> `unsafe` seems sufficiently advanced).
>  
>
>>
>> On Monday, August 24, 2020 at 7:08:17 AM UTC+3 alex.be...@gmail.com 
>> wrote:
>>
>>> Can we at least move with the https://github.com/golang/go/issues/22729 
>>> , please? Anything will help with the current mess.
>>>
>>>
>>> On Sunday, August 23, 2020 at 8:52:30 PM UTC-7, Ian Lance Taylor wrote:
>>>
>>>> On Sun, Aug 23, 2020 at 1:16 PM Denis Cheremisov 
>>>>  wrote: 
>>>> > 
>>>> > You may use something like this 
>>>> > 
>>>> > value2 := 
>>>> *(*uint64)(unsafe.Pointer(uintptr(unsafe.Pointer()) + 8)) 
>>>> > if value2 == 0 { 
>>>> > return true 
>>>> > } 
>>>> > 
>>>> > on AMD64, should work also for any 64 bit architecture (at least I 
>>>> believe so). Remember though this is hacky and may stop working once. 
>>>>
>>>> You could do that, but please don't. 
>>>>
>>>> Ian 
>>>>
>>>>
>>>> > воскресенье, 23 августа 2020 г. в 22:58:51 UTC+3, Aviv Eyal: 
>>>> >> 
>>>> >> I was trying to show that the current behavior is confusing and that 
>>>> fmt.Print() needing to resort to panic-and-recover is kinda code smell, 
>>>> but 
>>>> I sorts-of convinced myself that the current behavior is right, or at 
>>>> least 
>>>> consistent. 
>>>> >> 
>>>> >> In my code, I got bit because I sometimes use v *Type to denote "I 
>>>> may or may not have a value here" (where Type is a value-type). 
>>>> >> This is probably a bad practice on my behalf, because I break the 
>>>> Liskov substitution principle: there is a value of `*Type` that is not a 
>>>> valid value of `Type`, and I let this value slip by. 
>>>> >> 
>>>> >> In this case, `v Type` implements Stringer (i.e. valid callee for 
>>>> `v.String()`, but `v *Type`, in the strictest sense, does not. 
>>>> >> The only reason we can write: 
>>>> >> 
>>>> >> func (Type) String() string {...} 
>>>> >> v *Type = {...} 
>>>> >> _ = v.String() 
>>>> >> 
>>>> >> and have it compile, is syntactic sugar: `v` gets implicitly 
>>>> de-referenced, and there's an implicit assumption that it's not nil. 
>>>> >> And there's a matching syntactic sugar for converting `Type` to a 
>>>> `*Type`. 
>>>> >> 
>>>> >> So, In the code: 
>>>> >> 
>>>> >> func (Type) String() string {...} 
>>>> >> 
>>>> >> v *Type = nil 
>>>> >> r interface{} = v 
>>>> >> _, ok = r.(Stringer) 
>>>> >> 
>>>> >> What I really want to ask is "Can I, at runtime, call r.String()?", 
>>>> whereas the question Go answers is "Is any of `r`, `*r`, or `` defines 
>>>> .String()?" - which matches the static semantics of `r.String()`. 
>>>> >>

Re: [go-nuts] Re: How to know if interface{} data is nil w/o reflecting?

2020-08-27 Thread targe...@gmail.com
Not sure if it was mentioned here, but IMO the main issues isn't nil data 
itself, but how easy it's created. It'd be much less of a surprise if 
creating nil-data required explicit cast from nil struct pointer to 
interface pointer and resulted in just nil interface pointer in case of 
implicit cast. Though such change is almost certainly breaking one.

On Monday, August 24, 2020 at 7:08:17 AM UTC+3 alex.be...@gmail.com wrote:

> Can we at least move with the https://github.com/golang/go/issues/22729 , 
> please? Anything will help with the current mess.
>
>
> On Sunday, August 23, 2020 at 8:52:30 PM UTC-7, Ian Lance Taylor wrote:
>
>> On Sun, Aug 23, 2020 at 1:16 PM Denis Cheremisov 
>>  wrote: 
>> > 
>> > You may use something like this 
>> > 
>> > value2 := 
>> *(*uint64)(unsafe.Pointer(uintptr(unsafe.Pointer()) + 8)) 
>> > if value2 == 0 { 
>> > return true 
>> > } 
>> > 
>> > on AMD64, should work also for any 64 bit architecture (at least I 
>> believe so). Remember though this is hacky and may stop working once. 
>>
>> You could do that, but please don't. 
>>
>> Ian 
>>
>>
>> > воскресенье, 23 августа 2020 г. в 22:58:51 UTC+3, Aviv Eyal: 
>> >> 
>> >> I was trying to show that the current behavior is confusing and that 
>> fmt.Print() needing to resort to panic-and-recover is kinda code smell, but 
>> I sorts-of convinced myself that the current behavior is right, or at least 
>> consistent. 
>> >> 
>> >> In my code, I got bit because I sometimes use v *Type to denote "I may 
>> or may not have a value here" (where Type is a value-type). 
>> >> This is probably a bad practice on my behalf, because I break the 
>> Liskov substitution principle: there is a value of `*Type` that is not a 
>> valid value of `Type`, and I let this value slip by. 
>> >> 
>> >> In this case, `v Type` implements Stringer (i.e. valid callee for 
>> `v.String()`, but `v *Type`, in the strictest sense, does not. 
>> >> The only reason we can write: 
>> >> 
>> >> func (Type) String() string {...} 
>> >> v *Type = {...} 
>> >> _ = v.String() 
>> >> 
>> >> and have it compile, is syntactic sugar: `v` gets implicitly 
>> de-referenced, and there's an implicit assumption that it's not nil. 
>> >> And there's a matching syntactic sugar for converting `Type` to a 
>> `*Type`. 
>> >> 
>> >> So, In the code: 
>> >> 
>> >> func (Type) String() string {...} 
>> >> 
>> >> v *Type = nil 
>> >> r interface{} = v 
>> >> _, ok = r.(Stringer) 
>> >> 
>> >> What I really want to ask is "Can I, at runtime, call r.String()?", 
>> whereas the question Go answers is "Is any of `r`, `*r`, or `` defines 
>> .String()?" - which matches the static semantics of `r.String()`. 
>> >> 
>> >> So, while I should probably not use *Type as a replacement for 
>> Optional, I think it might make sense to have some operator that can 
>> determine, at run-time, if a call `r.String()` is valid (including a 
>> nil-check). 
>> >> 
>> >> 
>> >> -- Aviv 
>> >> 
>> >> On Saturday, April 11, 2020 at 4:48:28 PM UTC+3 ren...@ix.netcom.com 
>> wrote: 
>> >>> 
>> >>> I agree with the OP. The usefulness of nil interfaces is pretty 
>> limited. Show me a useful case that cant easily be implemented with non-nil 
>> interfaces. 
>> >>> 
>> >>> I would argue that allowing nil interfaces causes more subtle latent 
>> bugs and makes it harder to reason about the correctness of code when 
>> reviewing it. 
>> >>> 
>> >>> It just feels wrong. I realize I’m probably in the minority here but 
>> the OP is not alone. 
>> >>> 
>> >>> On Apr 11, 2020, at 8:20 AM, 'Axel Wagner' via golang-nuts <
>> golan...@googlegroups.com> wrote: 
>> >>> 
>> >>> On Fri, Apr 10, 2020 at 7:17 PM  wrote: 
>>  
>>  I realize I'm reviving an age-old discussion here and apologize for 
>> bringing up the undead. I happend to run into this when my application 
>> panicked when some interfaces where initialized with nil mock objects 
>> instead of being left uninitialized as in production mode. 
>> >>> 
>> >>> 
>> >>> Let's imagine a world in which `foo == nil` also is true if `foo` is 
>> an interface-value containing a nil-pointer. Let's say in this world, 
>> someone sends a message to golang-nuts. They wrote a mock for the same 
>> code. And since it's just a mock, they just returned static value from its 
>> methods and didn't need to care if the pointer was nil or not. They are 
>> confused, because the passed in this mock, but the code just assumed the 
>> field was uninitialized and never called into their mock. What would you 
>> tell them? Why is their confusion less valid? 
>> >>> 
>>  This would be an example where a nil implementing fooer is never 
>> caught: 
>>  
>>  type fooer interface { 
>>   foo() 
>>  } 
>>  
>>  type other struct{} 
>>  
>>  func (o *other) foo() {} // implement fooer 
>>  
>>  func main() { 
>>   var f fooer 
>>  
>>   var p *other // nil 
>>