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

Inconsistent behaviour of Lit with slices #117

Open
kendfss opened this issue Oct 28, 2024 · 0 comments
Open

Inconsistent behaviour of Lit with slices #117

kendfss opened this issue Oct 28, 2024 · 0 comments

Comments

@kendfss
Copy link

kendfss commented Oct 28, 2024

This could well be better placed in the Go issue tracker, sorry if so.

// gen.go
package main

import (
	"fmt"

	. "github.com/dave/jennifer/jen"
)

func main() {
	c := Id("perms").Op(":=").Map(String()).String().Values(DictFunc(func(d Dict) {
		for _, perm := range [][]int{{0, 1}, {1, 0}} {
			d[Lit(fmt.Sprint(perm))] = Lit(perm)
			d[Lit(fmt.Sprint(perm))] = Index().Int().Values(spell(Cast(Lit, Anify(perm)))...)
		}
	}))
	fmt.Printf("%#v", c)
}

// Cast behaves like "map" methods/functions in functional languages
func Cast[E, V any](f func(E) V, s []E) []V {
	out := make([]V, len(s))
	for i, e := range s {
		out[i] = f(e)
	}
	return out
}

// Convert a slice of any type into a []interface{}
func Anify[E any](slice []E) []any {
	out := make([]any, len(slice))
	for i := range out {
		out[i] = slice[i]
	}
	return out
}

// spell converts a slice of Statement pointers into a slice of Code objects
func spell(arg []*Statement) []Code {
	out := make([]Code, len(arg))
	for i, e := range arg {
		out[i] = e
	}
	return out
}

playground

If I run the code I, usually (see the bullet), get the following output:

perms := map[string]string{
        "[0 1]": []int{0, 1},
        "[0 1]": []int{0, 1},
        "[1 0]": []int{1, 0},
        "[1 0]": []int{1, 0},
}
  • even less consistently in the playground but it still happens every 2nd run, the other half of outputs is the same as the next step
  • always the same on my home machine

If I comment out the line d[Lit(fmt.Sprint(perm))] = Index().Int().Values(spell(Cast(Lit, Anify(perm)))...), I get:

%!v(PANIC=GoString method: unsupported type for literal: []int)
  • which may also be output in playground with both lines uncommented
  • I don't think this should happen at all if it can actually print a slice literal, maybe this is a language issue, but maybe there's something worth exploiting here?

this part is a little less relevant, mainly just shows
If I, instead, comment out the line d[Lit(fmt.Sprint(perm))] = Lit(perm), I get:

perms := map[string]string{
        "[0 1]": []int{0, 1},
        "[1 0]": []int{1, 0},
}

Which is what I wanted all along


May I also suggest adding conversion functions func([]T)[]interface{} and func([]*Statement)[]Code to the library (assuming they aren't already there)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants
@kendfss and others