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.

Reply via email to