On Sun, Nov 4, 2018 at 11:45 AM roger peppe <rogpe...@gmail.com> wrote:

> One thing to consider: at any point in your program, someone might call
> something like the following function with any value in scope:
>
>    var vals []interface{}
>    func save(x interface{}) {
>        vals = append (vals, x)
>    }
>
> For the semantics of the generic program to be consistent, the values in
> vals must have the exact concrete types of the instantiated generic values.
>

> I don't see that that is possible if a boxing approach is used like your
> code snippets.
>

> For example, in your sum function, if save was called with the address of
> x, the saved value would have type *interface{}, not *int.
>

I don't understand your point. The sum function doesn't contain anything
like that and I'm not sure about the context you're implying. If someone
writes to the slice, you'd obviously pass more functions to it for those
operations and the compiler can create appropriate closures to pass. Like,
a generic sort could be written like

contract comparable(v T) {
    v < v
}
func (type T comparable) Sort(s []T) {
    sort.Slice(s, func (i, j int) bool { return s[i] < s[j] })
}

and the compiler could generate

func Sort(s interface{}, _less func(a, b interface{}) bool, _idx func(int)
interface{}) {
    // Compiler knows it needs _less because of the contract and knows it
needs
    // _idx because Sort takes a slice
    sort.Slice(s, func(i, j int) bool { return _less(_idx(i), _idx(j)) })
}

and at the call site

Sort(s) // s has type []T

can generate

// Compiler knows the concrete type to instantiate the generic call with
Sort(s, func(a, b int) bool { return a.(T) < b.(T) }, func(i int)
interface{} { return s[i] })


I genuinely do not understand why you think the compiler can't know that a
function contains an `append` and, instead of emitting instructions to
append, just add another implicit argument that is then instantiated at the
call-site with the concrete type. As far as I can tell, any single specific
example you came up, I answered with a very simple and straight forward
solution of what code to generate. I can't really talk about, say, your
save, because there is no generic code to translate to illustrate further.
But as far as I can tell, the approach is obviously generalizable.

I mean - apparently it's not obvious, but I genuinely don't understand why.


>
> On Thu, 25 Oct 2018, 9:11 am Axel Wagner <axel.wagner...@googlemail.com
> wrote:
>
>> Sorry, should've added what I consider the source:
>> https://play.golang.org/p/3_um7p3IxwK
>>
>> On Thu, Oct 25, 2018 at 10:09 AM Axel Wagner <
>> axel.wagner...@googlemail.com> wrote:
>>
>>> Sure: https://play.golang.org/p/W_ruqI22Vhv
>>> Seems a fairly straight-forward transformation to me - and again easy to
>>> devirtualize.
>>>
>>> On Thu, Oct 25, 2018 at 8:56 AM roger peppe <rogpe...@gmail.com> wrote:
>>>
>>>>
>>>> On Thu, 25 Oct 2018, 12:52 am Axel Wagner, <
>>>> axel.wagner...@googlemail.com> wrote:
>>>>
>>>>> On Thu, Oct 25, 2018 at 12:39 AM roger peppe <rogpe...@gmail.com>
>>>>> wrote:
>>>>>
>>>>>> I understand this argument. By putting some smarts into the compiler,
>>>>>> we would hope that we can see benefits not just in our generated generic
>>>>>> code, but also in other code that we've already written that uses 
>>>>>> generics.
>>>>>> This would be great if it wasn't very hard to do.
>>>>>>
>>>>>
>>>>> We disagree here. I still maintain that it is not harder. My intention
>>>>> above was to illustrate that, by assuming we have the generics-problem
>>>>> (including a heuristic to decide what to specialize) solved and then
>>>>> solving the devirtualization-problem using that solution. Unfortunately,
>>>>> that still seems to be unconvincing to you, though.
>>>>>
>>>>> For example (I got a little carried away here), here's an idea of what
>>>>>> some generated code using a reflect-based approach might look like:
>>>>>>
>>>>>>
>>>>>> https://github.com/rogpeppe/genericdemo/blob/master/naive/naive.go
>>>>>>
>>>>>
>>>>> I'm sorry, but this seems like a strawman. This is how a realistic
>>>>> dynamic approach would look like:
>>>>> https://play.golang.org/p/Fbs0cpAnE43
>>>>>
>>>>
>>>> Try that again with the generic sum function instead of addPair, which
>>>> I only included so I could explore what it looked like when one generic
>>>> function calls another.
>>>>
>>>> or, if you prefer, using methods:
>>>>> https://play.golang.org/p/6YsyJaVQ789
>>>>> And yeah, I maintain that it's easy to devirtualize that. Especially
>>>>> if we can give the compiler hints, like for example,
>>>>> https://play.golang.org/p/TZNQRlvofw2
>>>>>
>>>>> Anyway. I give up, I guess :)
>>>>>
>>>>>
>>>>>>
>>>>>> Imagine how smart the compiler would have to be in order to
>>>>>> reverse-engineer that back to the equivalent inline code!
>>>>>> You'd end up having to write patterns for the exact code that is
>>>>>> produced from the compiler, with the danger that you wouldn't hit any 
>>>>>> real
>>>>>> code at all (and also, coming up with sound optimisations for small
>>>>>> variations in reflect code is likely to be really hard).
>>>>>> I suspect you'd end up with a very slow and very fragile compiler.
>>>>>>
>>>>>> FWIW I went a bit further and experimented with some more potential
>>>>>> representations of generic Go code so I could get an idea of the likely
>>>>>> overheads. The approach of sharing implementations that use the same
>>>>>> size/pointer layout seems to work ok, with about a 3 or 4 ns overhead per
>>>>>> generic call on my machine (about half the speed of a direct function
>>>>>> call). My experimentation is here:
>>>>>> https://github.com/rogpeppe/genericdemo/blob/master/generated.go .
>>>>>> It actually shouldn't be that hard to write some code to produce that 
>>>>>> kind
>>>>>> of code automatically, "gofront" if you like, without updating the 
>>>>>> compiler
>>>>>> wholesale. I need to stop now :)
>>>>>>
>>>>>>
>>>>>>

-- 
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.
For more options, visit https://groups.google.com/d/optout.

Reply via email to