Hi,

I'm not really a language designer and i don't use Go extensively, so
please take my words with a grain of salt. But I like Go and would
like to use it, and I'd like to put my 2 cents into the jar. I'm sorry
if this was already discussed, I checked the mailing list but didn't
find this.

I've read the updated draft (sorry i'm late) and the thing that really
rubbed me the wrong way was this one:

"We need a way to write a constraint that accepts only types that
support <. In order to do that, we observe that, aside from two
exceptions that we will discuss later, all the arithmetic, comparison,
and logical operators defined by the language may only be used with
types that are predeclared by the language, or with defined types
whose underlying type is one of those predeclared types. That is, the
operator < can only be used with a predeclared type such as int or
float64, or a defined type whose underlying type is one of those
types. Go does not permit using < with a composite type or with an
arbitrary defined type."

This is a good observation, but what if Go changes in the future and
this observation is no longer true?

I think I somewhat understand the underlying problem, interface is a
concept from the Java world and in Java "everything is object", and
classic interface is limited to describing methods, etc etc. But
interface is a form of constraint, so it does make a lot of sense to
use it as a constraint for generic types. However, I thought that
intention was to describe a constraint on objects composition, but
instead it describes constraints on object types. This doesn't feel
quite right.

"If C++ and Java are about type hierarchies and the taxonomy of types,
Go is about composition." Am i right?

Was it considered to decouple constraints into 1) constraints and 2)
constraints requirement expression? Something like this (here and
below everything is pseudocode):

type comparable interface {
  require (a, b) {
    a < b
  }
}

When constraint is checked, this requirement can be rewritten as a
function for a concrete type, for example, for interface{}:

func comparableRequireInterface(a, b interface{}) {
  _ = (a < b) // this won't compile, as expected, there is no operator
<, requirement isn't satisfied
}

For struct{}:

func comparableRequireStruct(a, b struct{}) {
  _ = (a < b) // this won't compile either
}

For numeric types, specifically for int:

func comparableRequireInt(a, b int) {
  _ = (a < b) // this will compile for other numeric types too
}

Playground link: https://play.golang.org/p/vzk6l7zvBY_J

Note that `require (a, b) { a == b }` will be satisfied for structs,
interfaces, numerics and strings.

This may (or may not) eliminate the need for predeclared `comparable`
constraint and it might (or might not) answer this: "It's not clear
that we fully understand the use of composite types in type lists":

type IncrementX interface {
  require (a) {
    a.x++
  }
}

Which can be rewritten for a concrete type:

type ConcreteStruct struct {
  x float64
}

As

func checkIncrementXConcreteStruct(a ConcreteStruct) {
  a.x++ // note that it can not be rewritten to _ = (a.x++)
}

With empty `struct{}` it will give a sensible error message:
"./prog.go:28:3: a.x undefined (type struct {} has no field or method
x)" and it will detect error when ++ can not be applied:
"./prog.go:24:5: invalid operation: a.x++ (non-numeric type string)"

Does any of this make any sense?

P.S. Yeah, it looks like C++, full disclosure, this is why I'm writing
this email, I thought maybe Go could borrow something from there. I
believe GCC 10+ can compile C++ concepts and there is a "playground"
available at godbolt.org.

-- 
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/CAMteYTbyeYKV55dLja%2BYqtGELA_4vh%3DnsvJRuaa6RUoTZ_Nx_A%40mail.gmail.com.

Reply via email to