This is a task for a parser - and the parser can be type safe -but the 
constraints for something as complex as html aren’t typically  expressed in 
types but rather bnf or similar. 

You can look at the Java html renderer/parser and it uses type safe nodes but 
it still has a resilient parser layer to produce the nodes. 



> On Dec 20, 2021, at 3:06 PM, Michael Ellis <michael.f.el...@gmail.com> wrote:
> 
> 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, 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.
>>>> 
>>>> -- 
>>>> 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.
> 
> -- 
> 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.

-- 
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/261AF334-7F5C-4C0C-8D34-DF248ACA6A0D%40ix.netcom.com.

Reply via email to