Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/go2go: anonymous func with generics #39632

Closed
mattn opened this issue Jun 17, 2020 · 13 comments
Closed

cmd/go2go: anonymous func with generics #39632

mattn opened this issue Jun 17, 2020 · 13 comments
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone

Comments

@mattn
Copy link
Member

mattn commented Jun 17, 2020

Anonymous function with generics does not work.

What did you do?

https://go2goplay.golang.org/p/5DSE8QCPltv

package main

import (
    "fmt"
)

func main() {
    x := func(type T interface{type int, string}) (v []T) T {
        max := v[0]
        for _, vv := range v {
            if vv > max {
                max = vv
            }
        }
        return max
    }
    fmt.Println(x([]int{1, 2, 3}))
    fmt.Println(x([]string{"bar", "foo"}))
}

What did you expect to see?

Anonymous function x works well.

What did you see instead?

Compilation error

I'm not sure the spec well but I hope this work.

@mattn mattn changed the title go2:go: anonymous func with generics go2go: anonymous func with generics Jun 17, 2020
@fhs
Copy link
Contributor

fhs commented Jun 17, 2020

This is the example with the syntax fixed: https://go2goplay.golang.org/p/5DSE8QCPltv
The correct syntax is:

...
    x := func(type T interface{type int, string}) (v []T) T {
...

The error:

prog.go:8:14: function type must have no type parameters

@ianlancetaylor ianlancetaylor changed the title go2go: anonymous func with generics cmd/go2go: anonymous func with generics Jun 17, 2020
@ianlancetaylor ianlancetaylor added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Jun 17, 2020
@ianlancetaylor ianlancetaylor added this to the Unplanned milestone Jun 17, 2020
@mattn
Copy link
Member Author

mattn commented Jun 17, 2020

@fhs Thanks. Updated summary.

@ianlancetaylor
Copy link
Contributor

CC @griesemer

My first take on this is that this is a bad error message from the parser. At least at the moment, generic function literals are not supported. It might be nice to support them just for orthogonality. I don't see a convincing reason why we need them, but I also don't see a convincing reason why we can't implement them.

That said, even if we fix the parser and type checker to handle them, they won't be supported by the translation tool.

@griesemer
Copy link
Contributor

griesemer commented Jun 17, 2020

Sure, it is easy to accept type parameters in function literal syntax.

Edited: The parser already accepts type parameters in function literals, but then reports an error (that error could perhaps be clearer). For the reasons discussed below we had decided that it's not super useful to permit generic function literals.

@bcmills
Copy link
Contributor

bcmills commented Jun 17, 2020

In this example, since x is a variable in local scope, it should be valid to use as a value.

What would it mean to pass x to some other function as a value of type interface{}? (For example, what would reflect.TypeOf(x) report?)

@ianlancetaylor
Copy link
Contributor

I agree with @bcmills that this does seem fairly problematic. I think the only thing you could do with a generic function literal is instantiate it or call it. That's not completely useless...but it's almost entirely useless.

@dolmen
Copy link
Contributor

dolmen commented Jun 24, 2020

Function literals stored in variables are currently the only way to have function-scoped functions.

I often use function-scoped function variables to reduce code redundancy without polluting the package scope. I would use macros instead if we had that.

Generics are kind of strongly typed macros. I would be sad if I couldn't use generics to define a function inside a function.

@bcmills
Copy link
Contributor

bcmills commented Jun 24, 2020

@dolmen, it would arguably be more consistent to allow a function declaration at local scope, which could then be parameterized. (A function declaration — unlike a function literal — is not a value, so the questions about the type of that value would be moot.)

@leaanthony
Copy link

leaanthony commented Sep 1, 2020

I just encountered this issue and wondering if there has been any movement on this?

My use case is fairly simple: Receive a function that transforms the data given to it and returns the result. My attempt is here:
https://go2goplay.golang.org/p/_JbH_7uPrTX

Is there a workaround for this scenario?

EDIT: I just got this working. Hopefully this will help others: https://go2goplay.golang.org/p/qpZOGSAwxEG

@griesemer
Copy link
Contributor

Yes, that's one way to solve this. Btw., here's the updated example code: https://go2goplay.golang.org/p/mUWfsZPHs5h (now working with the latest type parameter syntax).

@dnmfarrell
Copy link

If they can't declare type parameters, will anonymous functions be allowed to use in-scope type parameters? (they are allowed in go2go):

// Qsort takes a list of Ordered elements and returns a list of the elements in
// ascending order
func Qsort[T Ordered](xs List[T]) List[T] {
	if xs.Empty() || xs.Tail().Empty() {
		return xs
	}
	h := xs.Head()
	lt := Qsort(xs.Tail().Filter(func (x T) bool { return x < h }))
	ge := Qsort(xs.Tail().Filter(func (x T) bool { return x >= h }))
	return lt.Concat(Cons[T]{h, ge})
}

@ianlancetaylor
Copy link
Contributor

@dnmfarrell Yes, that is fine.

@griesemer
Copy link
Contributor

go2go is now defunct. Closing.

@golang golang locked and limited conversation to collaborators Jun 23, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
None yet
Development

No branches or pull requests

9 participants