gen

command module
v2.3.122 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 2, 2026 License: Apache-2.0 Imports: 7 Imported by: 0

README

fp-go gen/v2

Code generator for fp-go/v2 — produces lenses and prisms for Go struct types.


Commands

Command Purpose
lens Generate lenses and prisms for struct fields
mcp MCP server utilities
cp Copy utilities
embed Embed utilities
examples Examples utilities

lens — Lens & Prism Generation

Two invocation modes
1. Annotation mode (default)

Add the comment annotation // fp-go:Lens directly above a struct declaration. Then run the generator against the directory that contains it.

// fp-go:Lens
type Address struct {
    Street  string
    City    string
    ZipCode string
    Tags    []string
}
fp-go lens --dir ./mypkg --filename gen_lens.go
2. Type-name mode (--type, stringer-style)

Name the struct explicitly on the command line without modifying the source. A package pattern (default .) is passed as a positional argument. This mode uses go/packages for full type resolution — generics, external field types, and struct tags all work without source annotations.

# Single type in the current package
fp-go lens --type Server --dir ./mypkg --filename gen_lens.go .

# Type from an external package
fp-go lens --type Server --dir ./out net/http

# Multiple types, names read from a file (one per line, # = comment)
fp-go lens --type @types.txt --dir ./mypkg --filename gen_lens.go .
Flags
Flag Default Description
--dir . Directory to scan / write output to
--filename gen.go Name of the generated file
--type (unset) Comma-separated struct names, or @file
--package (derived) Package name for the generated file
--include-test-files / -t false Include *_test.go files in annotation scan
--verbose / -v false Print progress to stderr

What gets generated

For every annotated (or named) struct, the generator emits three layers of output into the target file:

Layer What Why
Struct types <TYPE>Lenses, <TYPE>RefLenses, <TYPE>Prisms, <TYPE>RefPrisms Collect all lenses/prisms for a type in one value
Standalone functions Make<TYPE><FIELD>Lens(), Make<TYPE><FIELD>LensO(), Make<TYPE><FIELD>RefLens(), Make<TYPE><FIELD>RefLensO(), Make<TYPE><FIELD>Prism(), Make<TYPE><FIELD>RefPrism() Importable one-by-one — the linker only includes what is called
Bulk constructors Make<TYPE>Lenses(), Make<TYPE>RefLenses(), Make<TYPE>Prisms(), Make<TYPE>RefPrisms() Convenience: create all lenses/prisms at once; delegate to standalone functions
Field rules
Field characteristic Lens LensO Ref variant Prism / RefPrism
Comparable (e.g. string, int, pointer) ✓ (MakeLensStrictWithName) ✓ (FromNonZero)
Non-comparable (e.g. []T, map, func) ✓ (MakeLensRefWithName) ✓ (Some)
Already an option.Option[A] — (would produce Option[Option[A]])

LensO (optional lens) treats the zero value of a field as "absent" (None) and any non-zero value as "present" (Some). It is only generated for comparable field types where the zero/non-zero distinction is meaningful.


Complete example

Input (address.go)
package mypkg

// fp-go:Lens
type Address struct {
    Street  string
    City    string
    ZipCode string
    Tags    []string
}
Command
fp-go lens --dir ./mypkg --filename gen_lens.go
Output (gen_lens.go) — verbatim output of the tool
package mypkg

// Code generated by go generate; DO NOT EDIT.
// This file was generated by robots.

import (
	__iso_option "github.com/IBM/fp-go/v2/optics/iso/option"
	__lens "github.com/IBM/fp-go/v2/optics/lens"
	__lens_option "github.com/IBM/fp-go/v2/optics/lens/option"
	__prism "github.com/IBM/fp-go/v2/optics/prism"
	__option "github.com/IBM/fp-go/v2/option"
)

// AddressLenses provides [lenses] for accessing fields of [Address]
//
// [lenses]: __lens.Lens
type AddressLenses struct {
	// Street is a [__lens.Lens] for the Street field of [Address]
	Street __lens.Lens[Address, string]
	// City is a [__lens.Lens] for the City field of [Address]
	City __lens.Lens[Address, string]
	// ZipCode is a [__lens.Lens] for the ZipCode field of [Address]
	ZipCode __lens.Lens[Address, string]
	// Tags is a [__lens.Lens] for the Tags field of [Address]
	Tags __lens.Lens[Address, []string]
	// StreetO is a [__lens_option.LensO] for the Street field of [Address], treating the zero value as absent
	StreetO __lens_option.LensO[Address, string]
	// CityO is a [__lens_option.LensO] for the City field of [Address], treating the zero value as absent
	CityO __lens_option.LensO[Address, string]
	// ZipCodeO is a [__lens_option.LensO] for the ZipCode field of [Address], treating the zero value as absent
	ZipCodeO __lens_option.LensO[Address, string]
}

// AddressRefLenses provides [lenses] for accessing fields of [Address] via a pointer to [Address]
//
// [lenses]: __lens.Lens
type AddressRefLenses struct {
	// Street is a [__lens.Lens] for the Street field of [Address] via a pointer receiver
	Street __lens.Lens[*Address, string]
	// City is a [__lens.Lens] for the City field of [Address] via a pointer receiver
	City __lens.Lens[*Address, string]
	// ZipCode is a [__lens.Lens] for the ZipCode field of [Address] via a pointer receiver
	ZipCode __lens.Lens[*Address, string]
	// Tags is a [__lens.Lens] for the Tags field of [Address] via a pointer receiver
	Tags __lens.Lens[*Address, []string]
	// StreetO is a [__lens_option.LensO] for the Street field of [Address] via a pointer receiver, treating the zero value as absent
	StreetO __lens_option.LensO[*Address, string]
	// CityO is a [__lens_option.LensO] for the City field of [Address] via a pointer receiver, treating the zero value as absent
	CityO __lens_option.LensO[*Address, string]
	// ZipCodeO is a [__lens_option.LensO] for the ZipCode field of [Address] via a pointer receiver, treating the zero value as absent
	ZipCodeO __lens_option.LensO[*Address, string]
}

// AddressPrisms provides [prisms] for accessing fields of [Address]
//
// [prisms]: __prism.Prism
type AddressPrisms struct {
	// Street is a [__prism.Prism] for the Street field of [Address]
	Street __prism.Prism[Address, string]
	// City is a [__prism.Prism] for the City field of [Address]
	City __prism.Prism[Address, string]
	// ZipCode is a [__prism.Prism] for the ZipCode field of [Address]
	ZipCode __prism.Prism[Address, string]
	// Tags is a [__prism.Prism] for the Tags field of [Address]
	Tags __prism.Prism[Address, []string]
}

// AddressRefPrisms provides [prisms] for accessing fields of [Address] via a pointer to [Address]
//
// [prisms]: __prism.Prism
type AddressRefPrisms struct {
	// Street is a [__prism.Prism] for the Street field of [Address] via a pointer receiver
	Street __prism.Prism[*Address, string]
	// City is a [__prism.Prism] for the City field of [Address] via a pointer receiver
	City __prism.Prism[*Address, string]
	// ZipCode is a [__prism.Prism] for the ZipCode field of [Address] via a pointer receiver
	ZipCode __prism.Prism[*Address, string]
	// Tags is a [__prism.Prism] for the Tags field of [Address] via a pointer receiver
	Tags __prism.Prism[*Address, []string]
}

// MakeAddressStreetLens returns a [__lens.Lens] for the Street field of [Address]
func MakeAddressStreetLens() __lens.Lens[Address, string] {
	return __lens.MakeLensWithName(
		func(s Address) string { return s.Street },
		func(s Address, v string) Address { s.Street = v; return s },
		"Address.Street",
	)
}

// MakeAddressStreetLensO returns a [__lens_option.LensO] for the Street field of [Address]
func MakeAddressStreetLensO() __lens_option.LensO[Address, string] {
	return __lens_option.FromIso[Address](__iso_option.FromZero[string]())(MakeAddressStreetLens())
}

// MakeAddressStreetRefLens returns a [__lens.Lens] for the Street field of [Address] via a pointer receiver
func MakeAddressStreetRefLens() __lens.Lens[*Address, string] {
	return __lens.MakeLensStrictWithName(
		func(s *Address) string { return s.Street },
		func(s *Address, v string) *Address { s.Street = v; return s },
		"(*Address).Street",
	)
}

// MakeAddressStreetRefLensO returns a [__lens_option.LensO] for the Street field of [Address] via a pointer receiver
func MakeAddressStreetRefLensO() __lens_option.LensO[*Address, string] {
	return __lens_option.FromIso[*Address](__iso_option.FromZero[string]())(MakeAddressStreetRefLens())
}

// MakeAddressStreetPrism returns a [__prism.Prism] for the Street field of [Address]
func MakeAddressStreetPrism() __prism.Prism[Address, string] {
	_fromNonZero := __option.FromNonZero[string]()
	return __prism.MakePrismWithName(
		func(s Address) __option.Option[string] { return _fromNonZero(s.Street) },
		func(v string) Address {
			return Address{Street: v}
		},
		"Address.Street",
	)
}

// MakeAddressStreetRefPrism returns a [__prism.Prism] for the Street field of [Address] via a pointer receiver
func MakeAddressStreetRefPrism() __prism.Prism[*Address, string] {
	_fromNonZero := __option.FromNonZero[string]()
	return __prism.MakePrismWithName(
		func(s *Address) __option.Option[string] { return _fromNonZero(s.Street) },
		func(v string) *Address {
			return &Address{Street: v}
		},
		"(*Address).Street",
	)
}

// MakeAddressCityLens returns a [__lens.Lens] for the City field of [Address]
// MakeAddressCityLensO, MakeAddressCityRefLens, MakeAddressCityRefLensO,
// MakeAddressCityPrism, MakeAddressCityRefPrism — identical pattern to Street.

// MakeAddressZipCodeLens, …ZipCodeLensO, …ZipCodeRefLens, …ZipCodeRefLensO,
// …ZipCodePrism, …ZipCodeRefPrism — identical pattern to Street.

// MakeAddressTagsLens returns a [__lens.Lens] for the Tags field of [Address]
func MakeAddressTagsLens() __lens.Lens[Address, []string] {
	return __lens.MakeLensWithName(
		func(s Address) []string { return s.Tags },
		func(s Address, v []string) Address { s.Tags = v; return s },
		"Address.Tags",
	)
}

// MakeAddressTagsRefLens returns a [__lens.Lens] for the Tags field of [Address] via a pointer receiver
func MakeAddressTagsRefLens() __lens.Lens[*Address, []string] {
	return __lens.MakeLensRefWithName( // []string is not comparable → MakeLensRefWithName
		func(s *Address) []string { return s.Tags },
		func(s *Address, v []string) *Address { s.Tags = v; return s },
		"(*Address).Tags",
	)
}

// MakeAddressTagsPrism returns a [__prism.Prism] for the Tags field of [Address]
func MakeAddressTagsPrism() __prism.Prism[Address, []string] {
	return __prism.MakePrismWithName(
		func(s Address) __option.Option[[]string] { return __option.Some(s.Tags) }, // not comparable → Some
		func(v []string) Address {
			return Address{Tags: v}
		},
		"Address.Tags",
	)
}

// MakeAddressTagsRefPrism returns a [__prism.Prism] for the Tags field of [Address] via a pointer receiver
func MakeAddressTagsRefPrism() __prism.Prism[*Address, []string] {
	return __prism.MakePrismWithName(
		func(s *Address) __option.Option[[]string] { return __option.Some(s.Tags) },
		func(v []string) *Address {
			return &Address{Tags: v}
		},
		"(*Address).Tags",
	)
}

// MakeAddressLenses creates a new [AddressLenses] with [lenses] for all fields
//
// [lenses]: __lens.Lens
func MakeAddressLenses() AddressLenses {
	return AddressLenses{
		// mandatory lenses
		Street:  MakeAddressStreetLens(),
		City:    MakeAddressCityLens(),
		ZipCode: MakeAddressZipCodeLens(),
		Tags:    MakeAddressTagsLens(),
		// optional lenses
		StreetO:  MakeAddressStreetLensO(),
		CityO:    MakeAddressCityLensO(),
		ZipCodeO: MakeAddressZipCodeLensO(),
	}
}

// MakeAddressRefLenses creates a new [AddressRefLenses] with [lenses] for all fields via a pointer to [Address]
//
// [lenses]: __lens.Lens
func MakeAddressRefLenses() AddressRefLenses {
	return AddressRefLenses{
		// mandatory lenses
		Street:  MakeAddressStreetRefLens(),
		City:    MakeAddressCityRefLens(),
		ZipCode: MakeAddressZipCodeRefLens(),
		Tags:    MakeAddressTagsRefLens(),
		// optional lenses
		StreetO:  MakeAddressStreetRefLensO(),
		CityO:    MakeAddressCityRefLensO(),
		ZipCodeO: MakeAddressZipCodeRefLensO(),
	}
}

// MakeAddressPrisms creates a new [AddressPrisms] with [prisms] for all fields
//
// [prisms]: __prism.Prism
func MakeAddressPrisms() AddressPrisms {
	return AddressPrisms{
		Street:  MakeAddressStreetPrism(),
		City:    MakeAddressCityPrism(),
		ZipCode: MakeAddressZipCodePrism(),
		Tags:    MakeAddressTagsPrism(),
	}
}

// MakeAddressRefPrisms creates a new [AddressRefPrisms] with [prisms] for all fields via a pointer to [Address]
//
// [prisms]: __prism.Prism
func MakeAddressRefPrisms() AddressRefPrisms {
	return AddressRefPrisms{
		Street:  MakeAddressStreetRefPrism(),
		City:    MakeAddressCityRefPrism(),
		ZipCode: MakeAddressZipCodeRefPrism(),
		Tags:    MakeAddressTagsRefPrism(),
	}
}

The City and ZipCode blocks are abridged with a comment — the real file contains the full six-function set for every field, identical to the Street pattern shown above.


Naming conventions

Generated symbol Pattern Example
Struct type — value lenses <TYPE>Lenses AddressLenses
Struct type — pointer lenses <TYPE>RefLenses AddressRefLenses
Struct type — value prisms <TYPE>Prisms AddressPrisms
Struct type — pointer prisms <TYPE>RefPrisms AddressRefPrisms
Standalone value lens Make<TYPE><FIELD>Lens() MakeAddressStreetLens()
Standalone optional value lens Make<TYPE><FIELD>LensO() MakeAddressStreetLensO()
Standalone pointer lens Make<TYPE><FIELD>RefLens() MakeAddressStreetRefLens()
Standalone optional pointer lens Make<TYPE><FIELD>RefLensO() MakeAddressStreetRefLensO()
Standalone value prism Make<TYPE><FIELD>Prism() MakeAddressStreetPrism()
Standalone pointer prism Make<TYPE><FIELD>RefPrism() MakeAddressStreetRefPrism()
Bulk value lens constructor Make<TYPE>Lenses() MakeAddressLenses()
Bulk pointer lens constructor Make<TYPE>RefLenses() MakeAddressRefLenses()
Bulk value prism constructor Make<TYPE>Prisms() MakeAddressPrisms()
Bulk pointer prism constructor Make<TYPE>RefPrisms() MakeAddressRefPrisms()

Binary-size note

The bulk constructors (Make<TYPE>Lenses() etc.) are convenient but pull in every field's lens/prism. If only a subset of fields is needed at a given call site, call the standalone functions directly — the Go linker will tree-shake the unused ones and produce a smaller binary.

// Only the Street lens is linked:
streetLens := MakeAddressStreetLens()

// All lenses are linked:
lenses := MakeAddressLenses()

Generic structs

Generic structs are fully supported. Type parameters are preserved in every generated symbol:

// fp-go:Lens
type Box[T any] struct {
    Content T
    Label   string
}

Generates (among others):

func MakeBoxContentLens[T any]() __lens.Lens[Box[T], T] { … }
func MakeBoxLabelLensO[T any]()  __lens_option.LensO[Box[T], string] { … }
func MakeBoxLenses[T any]()      BoxLenses[T] { … }

ContentO / ContentRefLensO are not generated when the type parameter is constrained by any (not comparable). They are generated when constrained by comparable.


Embedded structs

Fields promoted from embedded structs are included automatically (one level deep):

type Point struct{ X, Y float64 }

// fp-go:Lens
type Shape struct {
    Point        // promoted: X and Y appear as fields of Shape
    Color string
}

Generates MakeShapeXLens(), MakeShapeYLens(), MakeShapeColorLens(), etc.


go:generate integration

//go:generate fp-go lens --dir . --filename gen_lens.go

Or with the type-name mode (no annotation needed in the source):

//go:generate fp-go lens --type MyStruct --dir . --filename gen_lens.go .

Documentation

Overview

Package main contains the entry point for the code generator

Directories

Path Synopsis
cli
lenses
Package lenses contains the pure utility functions used by the lens code generator.
Package lenses contains the pure utility functions used by the lens code generator.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL