Skip to content

Inconsistent behaviour of Lit with slices #117

Open
@kendfss

Description

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)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions