Thanks, Axel & Robert.  As I said in the first post, the package already 
works well for my purposes (and apparently for the few others who use it).  
It allows defining web content more concisely than raw HTML and makes the 
full power of Go available for composing repetitive page structures.

I was mostly just curious about the possibility of detecting bad content at 
compile time instead of at run time. In practice, that's turned out not to 
be a significant problem so I'm ok with learning generics don't support a 
fix.

On Monday, December 20, 2021 at 2:31:32 PM UTC-5 axel.wa...@googlemail.com 
wrote:

> Oh, forgot the footnote:
>
> [1] Note that even that doesn't *actually* work, as `*HtmlNode` would 
> become a parametric type, so it would have to be instantiated to be used in 
> the constraint - you'd have to write `type HtmlNode[T string | 
> *HtmlNode[Something]]`. And the fact that there is no actual answer to what 
> "Something" would be should be a strong indicator for how much generics are 
> not what you want for this.
>
> On Mon, Dec 20, 2021 at 8:29 PM Axel Wagner <axel.wa...@googlemail.com> 
> wrote:
>
>>
>>
>> On Mon, Dec 20, 2021 at 7:07 PM Michael Ellis <michael...@gmail.com> 
>> wrote:
>>
>>> >Just to be clear, the way I understood you is that you want HtmlTree.C 
>>> to be a slice which has elements which can each either be a string or an 
>>> *HtmlTree - i.e. you want these to be mixed in a single slice. Correct?
>>>
>>> Actually, no.  An HtmlTree instance whose content is a string is a 
>>> terminal node.  The recursion in the Render() func looks like:
>>>
>>>       for _, c := range h.C {
>>>                 switch c := c.(type) {
>>>                 case string:
>>>                         b.WriteString(c)
>>>                 case *HtmlTree:
>>>                         err = Render(c, b, rindent)
>>>                         if err != nil {
>>>                                 return fmt.Errorf("%s : %v", h.T, err)
>>>                         }
>>>                 default:
>>>                         return fmt.Errorf("Bad content %v. Can't render 
>>> type %T! ", h.C, c)
>>>                 }
>>>         }
>>>
>>
>> That's pretty much what I meant, yes. You want a sum type (and in lieu of 
>> sum types, an interface), not generics. 
>> The "union" aspect of Go generics (the `a | b` syntax) only applies to 
>> using interfaces as *constraints*, not as *types* - you want to do the 
>> latter. You want to have a field which is either a string or an *HtmlNode - 
>> but Go only gives you a convenient way to write the two distinct types 
>> `type HtmlNodeString struct { /*…*/ C string }` and `type HtmlNodeNode 
>> struct { /* … */ C *HtmlNode }` into one¹ type declaration and write 
>> function which can work on either. It's just not what you want.
>>
>> The best option for you is (as Robert mentions) to use an interface, 
>> which is an "open sum" - meaning you can't have the guarantee that its 
>> dynamic type is of a limited set of options, but you *can* have a value 
>> whose actual type is dynamic. You can look at e.g. ast.Node 
>> <https://pkg.go.dev/go/ast#Node>, which is de-facto the same thing - 
>> it's supposed to be a limited set of options, but in lieu of sum types, 
>> it's an interface.
>>
>> Go might, at some point, allow the union-elements of constraint 
>> interfaces to be used as actual types, which *would* be a form of sum 
>> types. But probably not for a while - it's more complicated than it may 
>> seem.
>>
>>
>>>
>>> I suppose it's still a problem, though, since the compiler doesn't have 
>>> any way of knowing that's how trees of HtmlTree meant to be constructed. I 
>>> should have expressed the intended constraint on HtmlTree.C as `string | 
>>> []*HtmlTree`.  Does that make a difference?
>>> On Monday, December 20, 2021 at 10:25:26 AM UTC-5 
>>> axel.wa...@googlemail.com wrote:
>>>
>>>> Just to be clear, the way I understood you is that you want HtmlTree.C 
>>>> to be a slice which has elements which can each either be a string or an 
>>>> *HtmlTree - i.e. you wan these to be mixed in a single slice. Correct?
>>>> Because that is not a use case for generics, it's a use case for sum 
>>>> types (which Go does not have).
>>>>
>>>> On Mon, Dec 20, 2021 at 4:11 PM Michael Ellis <michael...@gmail.com> 
>>>> wrote:
>>>>
>>>>> > They can't, sorry.
>>>>> Ok. Thanks, Axel. 
>>>>> Saves me wasting more time.  In the past 3 years of using Go, this is 
>>>>> the only use case where I've  really wanted generics (other cases I've 
>>>>> encountered so far are easily handled with code generation). 
>>>>>
>>>>> -- 
>>>>>
>>>> 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/ac75dc32-733d-4a73-9735-619c33cb4cd4n%40googlegroups.com
>>>>>  
>>>>> <https://groups.google.com/d/msgid/golang-nuts/ac75dc32-733d-4a73-9735-619c33cb4cd4n%40googlegroups.com?utm_medium=email&utm_source=footer>
>>>>> .
>>>>>
>>>> -- 
>>> 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/2de22684-0263-465c-8ac0-ff288c535fb7n%40googlegroups.com
>>>  
>>> <https://groups.google.com/d/msgid/golang-nuts/2de22684-0263-465c-8ac0-ff288c535fb7n%40googlegroups.com?utm_medium=email&utm_source=footer>
>>> .
>>>
>>

-- 
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/34f509ae-1681-4bb4-8b54-ce0e5534fe87n%40googlegroups.com.

Reply via email to