whoops: "…because the first is a *defined* type", of course. On Sun, Jun 27, 2021 at 9:58 PM Axel Wagner <axel.wagner...@googlemail.com> wrote:
> On Sun, Jun 27, 2021 at 9:41 PM Victor Giordano <vitucho3...@gmail.com> > wrote: > >> Ok. Thanks for the insight again. Correction noted. I do get that types >> are named or not, and any not named type is a type of its own; and two not >> named types are different despite having the same definition (like in >> Pascal) >> > > Nit: The nomenclature is "defined", not "named" (it changed when type > aliases where introduced, which give a type a name, without defining a new > type - so "named" became confusing). > > With that, there are two aspects relative to this example: > • Type identity <https://golang.org/ref/spec#Type_identity>. A defined > type is different to any other type. So, `http.HandlerFunc` and > `func(http.ResponseWriter, *http.Request)` are not identical types, because > the first is an identical type and it's different from any other type. > • Assignability <https://golang.org/ref/spec#Assignability>. This is a > form of subtyping <https://en.wikipedia.org/wiki/Subtyping>. In this > case, the second rule is relevant: "x's type V and T have identical > underlying types and at least one of V or T is not a defined type". In this > case, `http.HandlerFunc` and `func(http.ResponseWriter, *http.Request)` > have the same underlying type (the latter is the underlying type of both) > and the latter is not a defined type. So a `http.HandlerFunc` is assignable > to a `func(http.ResponseWriter, *http.Request)` and vice-versa. Which is > why your example works - and the opposite example > <https://play.golang.org/p/O5R_YgMU19j> also does. > > The fact that the types are not identical is relevant, because it means > you can't convert a `[]http.HandlerFunc` into a > `[]func(http.ResponseWriter, *http.Request)`, for example. Which is also, > why doing this change would be a breaking change. For example, someone > might have defined > > type Mux interface { > Handle(pattern string, h http.Handler) > HandleFunc(pattern string, f func(http.ResponseWriter, *http.Request)) > } > var m Mux = http.NewServeMux() > > If the type of the `(*http.ServeMux) HandleFunc` parameter was changed to > `http.HandlerFunc`, this code would no longer compile, as the parameter > types must be identical, not just assignable, for interface satisfaction. > > >> >> Nice to clarify the issue. >> >> Now regarding our friendly discussion... >> >> > The question is "is it better". In my opinion, it isn't. >> mmmm my inner philosophical orc is wandering... 🤔... it's not my source >> code, what I can say... I will probably try to employ an unique type where >> possible, or the least quantity of types. At least that is what I tried in >> my source code. >> >> >> El dom, 27 jun 2021 a las 16:08, 'Axel Wagner' via golang-nuts (< >> golang-nuts@googlegroups.com>) escribió: >> >>> BTW, to be clear: You misuse the term "Untyped" in your example. Both >>> methods are fully typed. They just use different types. This is kind of >>> relevant, because you say "typed is better" - but both are typed to the >>> same degree. >>> >>> On Sun, Jun 27, 2021 at 8:55 PM Axel Wagner < >>> axel.wagner...@googlemail.com> wrote: >>> >>>> On Sun, Jun 27, 2021 at 8:17 PM Victor Giordano <vitucho3...@gmail.com> >>>> wrote: >>>> >>>>> But but but... just bear with me... cuz, in this specific case, I >>>>> guess you could employ both "approaches". See my example here >>>>> <https://play.golang.org/p/f2NOTHjffCm>. >>>>> >>>> >>>> Yes, I'm aware this works. That wasn't in doubt. The question is "is it >>>> better". In my opinion, it isn't. >>>> >>>> >>>>> Also I feel the need to clarify something about I stated... >>>>> > Thanks to all for the answer, i really try to see any actual reason >>>>> but i still don't get it. For me, to my humble acknowledgement, if I >>>>> define >>>>> a type I tend to use everywhere it appears. Period. End of the story. >>>>> I have to admit, although I follow this recipe as a compass, I may >>>>> pass by sometimes and leave redundant definitions. It is okay, after all, >>>>> we are humans and errors happen. >>>>> >>>>> El dom, 27 jun 2021 a las 13:28, Axel Wagner (< >>>>> axel.wagner...@googlemail.com>) escribió: >>>>> >>>>>> On Sun, Jun 27, 2021 at 6:05 PM Victor Giordano < >>>>>> vitucho3...@gmail.com> wrote: >>>>>> >>>>>>> Thanks to all for the answer, i really try to see any actual reason >>>>>>> but i still don't get it. For me, to my humble acknowledgement, if I >>>>>>> define >>>>>>> a type I tend to use everywhere it appears. Period. End of the story. >>>>>>> >>>>>> >>>>>>> > FWIW, arguing that `http.HandleFunc` should take a >>>>>>> `http.HandlerFunc` because there exists a defined type with the same >>>>>>> underlying type as the parameter is a bit like arguing every function >>>>>>> that >>>>>>> takes an `int64` should instead take a time.Duration >>>>>>> <https://golang.org/pkg/time/#Duration>. >>>>>>> >>>>>>> Allow me to put in different words: if you define `func >>>>>>> doSomething(duration int64)` at least i will argue why don't employ >>>>>>> time.Duration <https://golang.org/pkg/time/#Duration> as a type >>>>>>> there, if the parameter actually represents a Duration that is also a >>>>>>> defined type, ¿you don't?. >>>>>>> >>>>>> >>>>>> Yes. But that's the thing - if what the function actually takes a >>>>>> duration, then the correct type is a duration. But the type >>>>>> `http.HandleFunc` takes is *not* a `http.HandlerFunc`, it's a >>>>>> `func(http.ResponseWriter, *http.Request)`. It's a different type and >>>>>> it's >>>>>> the correct type to describe what that function is for. If the type was >>>>>> `http.HandlerFunc`, then `http.HandleFunc` wouldn't need to exist, >>>>>> because >>>>>> `http.Handle` would suffice. >>>>>> >>>>>> For example, if you had a function >>>>>> >>>>>> // DurationFromMS returns a time.Duration, based on a duration given >>>>>> as an integer in ms. >>>>>> func DurationFromMS(d int64) time.Duration { >>>>>> return time.Duration(d * 1000) >>>>>> } >>>>>> >>>>>> Would you make the parameter type `time.Duration`? After all, it >>>>>> represents a duration, right? But you wouldn't. It would be the wrong >>>>>> type >>>>>> to represent what the function does. >>>>>> >>>>>> Or, a different example: We could introduce a new type in the >>>>>> `filepath` package: >>>>>> >>>>>> // Path is a path, using the OS-specific delimiter >>>>>> type Path string >>>>>> >>>>>> // Verify makes sure that p is a path, using the correct, OS-specific >>>>>> delimiter. >>>>>> // It returns p as a Path, and an error, if p was invalid. >>>>>> func Verify(p string) (Path, error) >>>>>> >>>>>> We could then have `filepath.Join` etc. take `Path`s, instead of >>>>>> `string`s, to represent that the argument actually must be a valid path, >>>>>> using the OS-specific separator. Which would be different from >>>>>> `path.Path`, >>>>>> of course, which would always use "/" as a separator. Meaning you >>>>>> wouldn't >>>>>> be able to accidentally use one as the other, which would add >>>>>> type-safety. >>>>>> >>>>>> But should `Verify` take a `Path` here? Of course not. That would be >>>>>> the wrong type. It just returns its argument converted into the correct >>>>>> type, but semantically, it still takes *a plain string*. Before you pass >>>>>> the path into `Verify`, it doesn't have the semantic association of "this >>>>>> string is an OS-specific path" - that's exactly the semantic association >>>>>> that `Verify` creates. >>>>>> >>>>>> Your argument hinges on the assumption that `http.HandleFunc`s >>>>>> parameter has the semantic interpretation (not only the same underlying >>>>>> type as) as `http.HandlerFunc`. But it doesn't. The semantic >>>>>> interpretation >>>>>> of the argument to `http.HandleFunc` is a plain function. Otherwise, it >>>>>> wouldn't need to exist - because we already *have* a function that can >>>>>> take >>>>>> a `http.HandlerFunc`: `http.Handle`. >>>>>> >>>>>> The plain func is describing *exactly* the type that function should >>>>>> take. `http.HandlerFunc` would be the wrong type. >>>>>> >>>>>> >>>>>>> I won't say the same about other things that hold an int64 that >>>>>>> represents for example an ID of record in a database. >>>>>>> >>>>>>> >>>>>>> >>>>>>> El dom, 27 jun 2021 a las 12:56, 'Axel Wagner' via golang-nuts (< >>>>>>> golang-nuts@googlegroups.com>) escribió: >>>>>>> >>>>>>>> FWIW, arguing that `http.HandleFunc` should take a >>>>>>>> `http.HandlerFunc` because there exists a defined type with the same >>>>>>>> underlying type as the parameter is a bit like arguing every function >>>>>>>> that >>>>>>>> takes an `int64` should instead take a time.Duration >>>>>>>> <https://golang.org/pkg/time/#Duration>. That's just not how types >>>>>>>> tend to work. >>>>>>>> >>>>>>>> It makes no sense for `http.HandleFunc` to take a >>>>>>>> `http.HandlerFunc`, because it's purpose is specifically to work on a >>>>>>>> plain >>>>>>>> function. If you have an `http.HandlerFunc`, you can already just call >>>>>>>> `http.Handle` - there is no need to make a separate function that >>>>>>>> takes a >>>>>>>> *specific* implementation of `http.Handler`. >>>>>>>> >>>>>>>> On Sun, Jun 27, 2021 at 5:51 PM Axel Wagner < >>>>>>>> axel.wagner...@googlemail.com> wrote: >>>>>>>> >>>>>>>>> On Sun, Jun 27, 2021 at 5:25 PM Victor Giordano < >>>>>>>>> vitucho3...@gmail.com> wrote: >>>>>>>>> >>>>>>>>>> I keep wondering if they code that way for any reason. With "code >>>>>>>>>> that way" I mean: define a type and then not use it. >>>>>>>>>> >>>>>>>>> >>>>>>>>> As I said: It's used plenty of times. Both inside of `net/http` >>>>>>>>> and outside of it. >>>>>>>>> >>>>>>>>>> >>>>>>>>>> - So, ¿why not employ the type defined in the first place? >>>>>>>>>> >>>>>>>>>> I feel like I gave a bunch of reasons for this too. >>>>>>>>> >>>>>>>>> >>>>>>>>>> Don't get me wrong,but if I define a type I tend to use that type >>>>>>>>>> where it appears. That is in fact the basis of making types, to use >>>>>>>>>> them. >>>>>>>>>> So that feeds my questioning! >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> El dom, 27 jun 2021 a las 11:46, 'Axel Wagner' via golang-nuts (< >>>>>>>>>> golang-nuts@googlegroups.com>) escribió: >>>>>>>>>> >>>>>>>>>>> If I understand you correctly, you are suggesting to replace the >>>>>>>>>>> parameter type `func(http.ResponseWriter, *http.Request)` with the >>>>>>>>>>> parameter type `http.HandlerFunc`. You've been (correctly) told >>>>>>>>>>> that we >>>>>>>>>>> can't make that change, because it would break the Go 1 >>>>>>>>>>> compatibility >>>>>>>>>>> change (as there is code which currently compiles which wouldn't >>>>>>>>>>> compile >>>>>>>>>>> after that change). But you are wondering if, *ignoring* the >>>>>>>>>>> compatibility >>>>>>>>>>> guarantee, it would be a good change. Am I getting this right? >>>>>>>>>>> >>>>>>>>>>> If so: I don't think it would be a good change. >>>>>>>>>>> >>>>>>>>>>> First, it's important to realize that the *only* reason, >>>>>>>>>>> `http.HandlerFunc` exists at all, is so that you can write a >>>>>>>>>>> `func(http.ResponseWriter, *http.Request)` and use it as a >>>>>>>>>>> `http.Handler`, >>>>>>>>>>> in the places where `net/http` expects the latter. You say the type >>>>>>>>>>> isn't >>>>>>>>>>> used - but it is. It's used by *users* of the `net/http` package, >>>>>>>>>>> to make >>>>>>>>>>> their plain functions into `http.Handler`s. It is also used in >>>>>>>>>>> `net/http` >>>>>>>>>>> itself - in the exact function you are referring to >>>>>>>>>>> <https://golang.org/src/net/http/server.go?s=77627:77714#L2487>. >>>>>>>>>>> That is the exact and only purpose of that type, to make a plain >>>>>>>>>>> function >>>>>>>>>>> implement the `Handler` interface. So, taking a plain function as a >>>>>>>>>>> parameter *is the purpose of having the `HandlerFunc` type*. >>>>>>>>>>> >>>>>>>>>>> You also say that adding types is a good thing. I tend to >>>>>>>>>>> disagree with that as a general statement. Adding types is a good >>>>>>>>>>> thing, if >>>>>>>>>>> it serves as important documentation or if it serves to catch bugs. >>>>>>>>>>> I don't >>>>>>>>>>> think either of these would be happening with this change. In terms >>>>>>>>>>> of >>>>>>>>>>> documentation - well, you don't *have* to pass a >>>>>>>>>>> `http.HandlerFunc`, so >>>>>>>>>>> there is no reason for the documentation to make it clear that you >>>>>>>>>>> should. >>>>>>>>>>> You can (and should) just pass a plain `func`. So, using the >>>>>>>>>>> defined type >>>>>>>>>>> here wouldn't serve as documentation, it would document the *wrong* >>>>>>>>>>> thing. >>>>>>>>>>> >>>>>>>>>>> As for catching bugs: Making the parameter type a defined type >>>>>>>>>>> would only change one thing in terms of type-safety. It would mean >>>>>>>>>>> that if >>>>>>>>>>> you define a *different* type `type MyFunc func(http.ResponseWriter, >>>>>>>>>>> *http.Request)`, the compiler would prevent you from writing >>>>>>>>>>> `http.HandleFunc(…, MyFunc(f))`. Preventing a bug would thus >>>>>>>>>>> require that >>>>>>>>>>> your `MyFunc` type would have to be used semantically differently >>>>>>>>>>> from >>>>>>>>>>> `http.HandlerFunc`. But that seems *exceedingly* unlikely, given >>>>>>>>>>> that you >>>>>>>>>>> defined `MyFunc` in terms of the `net/http` package. And it would >>>>>>>>>>> then >>>>>>>>>>> appear *exceedingly* unlikely, that you'd accidentally mix the two >>>>>>>>>>> up - >>>>>>>>>>> almost all usages of `http.HandleFunc` will pass the name of some >>>>>>>>>>> defined >>>>>>>>>>> function and that will always work. >>>>>>>>>>> >>>>>>>>>>> But all of this discussion is really moot. It's a breaking >>>>>>>>>>> change, so it can't happen - whether it's a good change or not >>>>>>>>>>> doesn't >>>>>>>>>>> exactly matter at that point. Personally, *if* we could "go back in >>>>>>>>>>> time" >>>>>>>>>>> and wouldn't have to worry about backwards compatibility, my vote >>>>>>>>>>> would >>>>>>>>>>> rather be to change the language to make the HandlerFunc type >>>>>>>>>>> obsolete <https://github.com/golang/go/issues/21670> and remove >>>>>>>>>>> it altogether. >>>>>>>>>>> >>>>>>>>>>> On Sun, Jun 27, 2021 at 3:53 PM Victor Giordano < >>>>>>>>>>> vitucho3...@gmail.com> wrote: >>>>>>>>>>> >>>>>>>>>>>> Hello gophers! >>>>>>>>>>>> >>>>>>>>>>>> While studing at this source code >>>>>>>>>>>> <https://github.com/golang/go/blob/37f9a8f69d6299783eac8848d87e27eb563500ac/src/net/http/server.go> >>>>>>>>>>>> in search for some knowledge and enlightment, i do note that in >>>>>>>>>>>> some file a >>>>>>>>>>>> type is defined and then is not used in a place where it could be >>>>>>>>>>>> used. >>>>>>>>>>>> This open an interrogant for me, because tipification is often >>>>>>>>>>>> good thing, >>>>>>>>>>>> regardless the language I may state, and I express it via a >>>>>>>>>>>> ticket <https://github.com/golang/go/issues/46926>. I get the >>>>>>>>>>>> idea that due to language grammar changing the code would be a >>>>>>>>>>>> breaking >>>>>>>>>>>> change. >>>>>>>>>>>> >>>>>>>>>>>> But i keep wondering if they actually do this for a reason.. i >>>>>>>>>>>> mean, given the possiblity to get back in time, ¿does the team at >>>>>>>>>>>> golang >>>>>>>>>>>> will write the same source code, definiting a type with a name and >>>>>>>>>>>> then >>>>>>>>>>>> intenttionally not using it? i mean...i keep wondering if there is >>>>>>>>>>>> any >>>>>>>>>>>> reason for defined types and then not use it and using the gitlab >>>>>>>>>>>> channel i >>>>>>>>>>>> probably fail to express my initial intention. I do often read >>>>>>>>>>>> some third >>>>>>>>>>>> party code, in order to view others minds (or try at least..), >>>>>>>>>>>> what i'm >>>>>>>>>>>> asking here is a question in order to get another people point of >>>>>>>>>>>> view. >>>>>>>>>>>> >>>>>>>>>>>> Thanks again! >>>>>>>>>>>> >>>>>>>>>>>> -- >>>>>>>>>>>> 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/96369719-6200-4765-aee1-83befce04666n%40googlegroups.com >>>>>>>>>>>> <https://groups.google.com/d/msgid/golang-nuts/96369719-6200-4765-aee1-83befce04666n%40googlegroups.com?utm_medium=email&utm_source=footer> >>>>>>>>>>>> . >>>>>>>>>>>> >>>>>>>>>>> -- >>>>>>>>>>> You received this message because you are subscribed to a topic >>>>>>>>>>> in the Google Groups "golang-nuts" group. >>>>>>>>>>> To unsubscribe from this topic, visit >>>>>>>>>>> https://groups.google.com/d/topic/golang-nuts/VBQrlI6-zW0/unsubscribe >>>>>>>>>>> . >>>>>>>>>>> To unsubscribe from this group and all its topics, 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/CAEkBMfHnCTf_4G5ZhGX0EXBKJRN9LcEWbKWOdPiCTKdX6SDqPA%40mail.gmail.com >>>>>>>>>>> <https://groups.google.com/d/msgid/golang-nuts/CAEkBMfHnCTf_4G5ZhGX0EXBKJRN9LcEWbKWOdPiCTKdX6SDqPA%40mail.gmail.com?utm_medium=email&utm_source=footer> >>>>>>>>>>> . >>>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> -- >>>>>>>>>> V >>>>>>>>>> >>>>>>>>> -- >>>>>>>> You received this message because you are subscribed to a topic in >>>>>>>> the Google Groups "golang-nuts" group. >>>>>>>> To unsubscribe from this topic, visit >>>>>>>> https://groups.google.com/d/topic/golang-nuts/VBQrlI6-zW0/unsubscribe >>>>>>>> . >>>>>>>> To unsubscribe from this group and all its topics, 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/CAEkBMfHiQP0WEbGPrFkY5gSzaaiQ5OqisySiy8_yUdfVAE-v6w%40mail.gmail.com >>>>>>>> <https://groups.google.com/d/msgid/golang-nuts/CAEkBMfHiQP0WEbGPrFkY5gSzaaiQ5OqisySiy8_yUdfVAE-v6w%40mail.gmail.com?utm_medium=email&utm_source=footer> >>>>>>>> . >>>>>>>> >>>>>>> >>>>>>> >>>>>>> -- >>>>>>> V >>>>>>> >>>>>> >>>>> >>>>> -- >>>>> V >>>>> >>>> -- >>> You received this message because you are subscribed to a topic in the >>> Google Groups "golang-nuts" group. >>> To unsubscribe from this topic, visit >>> https://groups.google.com/d/topic/golang-nuts/VBQrlI6-zW0/unsubscribe. >>> To unsubscribe from this group and all its topics, 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/CAEkBMfFDgoq0OrR%3DDPgW9h4tGAmLXqO%3DQ52_kddgbctwORhGDw%40mail.gmail.com >>> <https://groups.google.com/d/msgid/golang-nuts/CAEkBMfFDgoq0OrR%3DDPgW9h4tGAmLXqO%3DQ52_kddgbctwORhGDw%40mail.gmail.com?utm_medium=email&utm_source=footer> >>> . >>> >> >> >> -- >> 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/CAEkBMfE1e3F9zX5VP3gwbSR6oRFdOsoW61tRi5gUVj14dpdQcg%40mail.gmail.com.