On Sun, 28 Apr 2024 at 12:10, Andrew Harris <harris...@spu.edu> wrote:

> Bouncing out from some recent discussions on the github issue tracker, it
> seems like there's some interest in tuples in Go. I thought the discussion
> in #66651 led to some interesting ideas, but it's also beginning to drift.
> Maybe this is a better place to brain-dump some ideas. (This could be a
> proposal but I'm not sure that's quite right either, that might be spammy.)
>
> Some recent issues:
> 1. #64457 "Tuple types for Go" <https://github.com/golang/go/issues/64457>
> (@griesemer)
> 2. #66651 "Variadic type parameters"
> <https://github.com/golang/go/issues/66651> (@ianlancetaylor)
> 3. "support for easy packing/unpacking of struct types"
> <https://github.com/golang/go/issues/64613> (@griesemer)
>
> Synthesizing from those discussions, and satisfying requirements framed
> by @rogpeppe
> <https://github.com/golang/go/issues/66651#issuecomment-2054198677>, the
> following is a design for tuples that comes in two parts. The first part
> explores tuples in non-generic code, resembling a restrained version of
> #64457. The second part explores tuple constraints for generic code,
> reframing some ideas from #66651 in terms of tuples. It's a fungal kingdom
> approach, where tuples occupy some unique niches but aren't intended to
> dominate the landscape.
>
> *TUPLES IN NON-GENERIC CODE*
>
> Tuples are evil
> <https://github.com/golang/go/issues/32941#issuecomment-509367113> because
> the naming schemes are deficient. To enjoy greater name abundancy, this
> design tweaks tuple *types* from #64457 in the direction of "super-lightweight
> structs"
> <https://github.com/golang/go/issues/64457#issuecomment-1834358907>. It
> still allows tuple *expressions* from #64457, for tuples constructed from
> bare values.
>
> *1. Tuple types*
> Outside of generics, tuple *type* syntax requires named fields.
>
> TupleType = "(" { IdentifierList Type [ ", " ] } ")" .
>
> // e.g.:
> type Point (X, Y int)
>
> More irregularly, the TupleType syntax is used *exclusively* to declare
> named types, and these named tuple types cannot implement methods. As a
> result, a named tuple type is entirely defined at the site of the type
> definition.
>

FWIW this kind of restriction has no precedent in Go. Currently any type
may be unnamed. This restriction seems arbitrary and irregular to me.

>
> *2. Tuple literals*
> The tuple *expression* syntax of #64457 remains valid. The result is an
> implicitly typed tuple value. Literals of a named tuple type are also
> valid, and resemble struct literals.
>
> point1 := (0, 0) // implicitly typed
> point2 := Point(X: 0, Y: 0) // explicitly typed
>
>
> *3. Promotion and expansion*
> There is no way to capture the type of an implicitly typed tuple value -
> the result of a bare tuple *expression* - with tuple *type* syntax.
> However, promotion and expansion are available as way to leverage tuple
> values.
>
> - Promotion: An implicitly typed tuple value is freely and automatically
> promoted to a value of a named tuple type, if and only if the sequence of
> types is congruent (same types, same order, same arity) between the
> implicit and named type:
>
> type T (string, string)
>
Isn't this illegal according to your TupleType syntax above?

> var t T
> t := ("foo", "bar")
>
> The RHS of the assignment is implicitly typed (string, string), so the
> value can be promoted to the LHS's congruent type T without further
> ceremony.
>
> - Any tuple value can, under the condition of congruence, expand with ... 
> "wherever
> a list of values is expected" (#66651). This means places like assignments,
> function calls, function returns, struct/slice/array literals, for/range
> loops, and channel receives. Each of the github issues (#64457, #64613,
> #66651) explores this in more detail. Qualifications and some subjectivity
> are involved, and a full proposal would explore this more completely and
> sharply, but the intuitive notion is pretty straightforward.
>
>
> *TUPLE CONSTRAINTS*
> For generic code, this design's driving concept is tuple constraints. A
> tuple constraint describes type sets that are exclusively composed of tuple
> types. Loosely, where union-of-types or set-of-methods type constraints are
> currently, a tuple constraint would also be allowed. The rules for code
> parameterized on tuple constraints should resemble #66651 in many ways.
> Most essentially, it should be possible to substitute a tuple constraint
> "wherever a list of types is permitted", as suggested in #66651.
>
>
> *1. Non-variadic tuple constraints*
> The current TypeParamDecl production is:
>
> TypeParamDecl = IdentifierList TypeConstraint .
>
> Adding tuple constraints can be accomplished by extending TypeParamDecl syntax
> to include an alternative to the TypeConstraint, a TupleConstraint. Then,
> a tuple constraint is constructed from TypeConstraint elements.
>
> TypeParamDecl = IdentifierList ( TypeConstraint | TupleConstraint ) .
> TupleConstraint = "(" { TypeConstraint [ "," ] } ")" .
>
> Some examples:
> [T (any, any)] describes the type set consisting of any 2-ary tuple
>

By analogy with [T map[any]any] I'd expect the "any" there to be the
regular "any" type (as used outside generics) rather than the type
constraint "any". That is, my intuition would expect this to disallow a
(string, string) tuple, but my sense is that that's not what you're
suggesting.

In general, a type constraint can be either a regular type (a type set) or
an interface type, but this doesn't seem like either, and looks to me like
it would significantly complicate the generics specification.


> [T (K, any), K comparable] describes the type set of 2-ary tuples that
> begin with a comparable element.
>

How would you see that as different from [T (comparable, any)] ?


>
> Via tuple -> list-of-types substitution, the following would be equivalent:
>
> func F[K comparable, V any](f func(K, V)) { ... }
> func F[KV (comparable, any)](f func(KV)) { ... }


Would these two be equivalent too?

func FK comparable, V any](f []func(K, V)) {}
func F[KV (comparable, any)](f []func(KV)) {}


>
> *2. Variadic tuple constraints*
>
> A variadic tuple constraint is described with an extension to the
> TupleConstraint production: an optional VariadicTupleElement is appended
> to it.
>
> TupleConstraint = "(" { TypeConstraint [ "," ] } [ VariadicTupleElement ]
> ")" .
> VariadicTupleElement = "..." TypeConstraint .
>
> The identifier for a variadic tuple constraint may be still be substituted
> for a list of types. Drawing from use cases discussed in #66651, this leads
> to function signatures like:
>
> func Filter[V (... any)](f func(V), seq Seq[V]) Seq[V]
>
> func MergeFunc[V (... any)](xs, ys Seq[V], f func(V, V) int) Seq[V]
>

It sounds like by your explanation here that this code should be valid:

func main() {
        for x := range FSeq(strconv.Atoi) {
                fmt.Println(reflect.TypeOf(x))
        }
}

func FSeq[V (... any)](f func(string) V) iter.Seq[V] {
        return func(yield func(v V) bool)) {
                yield(f("1234"))
        }
}

If it wouldn't be valid, why not? If it's OK, what would it print?

-- 
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/CAJhgacgK9vgkJpxme3jrReKPaK0Lptx3d4aNgz7phmH2WQnztQ%40mail.gmail.com.

Reply via email to