Package builder provides a method for writing fluent immutable builders.
package builder

import (
	
	
	
)
Builder stores a set of named values. New types can be declared with underlying type Builder and used with the functions in this package. See example. Instances of Builder should be treated as immutable. It is up to the implementor to ensure mutable values set on a Builder are not mutated while the Builder is in use.
type Builder struct {
	builderMap ps.Map
}

var (
	EmptyBuilder      = Builder{ps.NewMap()}
	emptyBuilderValue = reflect.ValueOf(EmptyBuilder)
)

func ( interface{}) ps.Map {
	 := convert(, Builder{}).(Builder)

	if .builderMap == nil {
		return ps.NewMap()
	}

	return .builderMap
}
Set returns a copy of the given builder with a new value set for the given name. Set (and all other functions taking a builder in this package) will panic if the given builder's underlying type is not Builder.
func ( interface{},  string,  interface{}) interface{} {
	 := Builder{getBuilderMap().Set(, )}
	return convert(, )
}
Delete returns a copy of the given builder with the given named value unset.
func ( interface{},  string) interface{} {
	 := Builder{getBuilderMap().Delete()}
	return convert(, )
}
Append returns a copy of the given builder with new value(s) appended to the named list. If the value was previously unset or set with Set (even to a e.g. slice values), the new value(s) will be appended to an empty list.
func ( interface{},  string,  ...interface{}) interface{} {
	return Extend(, , )
}
Extend behaves like Append, except it takes a single slice or array value which will be concatenated to the named list. Unlike a variadic call to Append - which requires a []interface{} value - Extend accepts slices or arrays of any type. Extend will panic if the given value is not a slice, array, or nil.
func ( interface{},  string,  interface{}) interface{} {
	if  == nil {
		return 
	}

	,  := getBuilderMap().Lookup()

	var  ps.List
	if  {
		,  = .(ps.List)
	}
	if ! {
		 = ps.NewList()
	}

	forEach(, func( interface{}) {
		 = .Cons()
	})

	return Set(, , )
}

func ( ps.List,  reflect.Type) reflect.Value {
	 := .Size()
	 := reflect.MakeSlice(, , )
	for  :=  - 1;  >= 0; -- {
		 := reflect.ValueOf(.Head())
		.Index().Set()
		 = .Tail()
	}
	return 
}

var anyArrayType = reflect.TypeOf([]interface{}{})
Get retrieves a single named value from the given builder. If the value has not been set, it returns (nil, false). Otherwise, it will return (value, true). If the named value was last set with Append or Extend, the returned value will be a slice. If the given Builder has been registered with Register or RegisterType and the given name is an exported field of the registered struct, the returned slice will have the same type as that field. Otherwise the slice will have type []interface{}. It will panic if the given name is a registered struct's exported field and the value set on the Builder is not assignable to the field.
func ( interface{},  string) (interface{}, bool) {
	,  := getBuilderMap().Lookup()
	if ! {
		return nil, false
	}

	,  := .(ps.List)
	if  {
		 := anyArrayType

		if ast.IsExported() {
			 := getBuilderStructType(reflect.TypeOf())
			if  != nil {
				,  := (*).FieldByName()
				if  {
					 = .Type
				}
			}
		}

		 = listToSlice(, ).Interface()
	}

	return , true
}
GetMap returns a map[string]interface{} of the values set in the given builder. See notes on Get regarding returned slices.
func ( interface{}) map[string]interface{} {
	 := getBuilderMap()
	 := getBuilderStructType(reflect.TypeOf())

	 := make(map[string]interface{}, .Size())

	.ForEach(func( string,  ps.Any) {
		,  := .(ps.List)
		if  {
			 := anyArrayType

			if  != nil {
				,  := (*).FieldByName()
				if  {
					 = .Type
				}
			}

			 = listToSlice(, ).Interface()
		}

		[] = 
	})

	return 
}
GetStruct builds a new struct from the given registered builder. It will return nil if the given builder's type has not been registered with Register or RegisterValue. All values set on the builder with names that start with an uppercase letter (i.e. which would be exported if they were identifiers) are assigned to the corresponding exported fields of the struct. GetStruct will panic if any of these "exported" values are not assignable to their corresponding struct fields.
func ( interface{}) interface{} {
	 := newBuilderStruct(reflect.TypeOf())
	if  == nil {
		return nil
	}
	return scanStruct(, )
}
GetStructLike builds a new struct from the given builder with the same type as the given struct. All values set on the builder with names that start with an uppercase letter (i.e. which would be exported if they were identifiers) are assigned to the corresponding exported fields of the struct. ScanStruct will panic if any of these "exported" values are not assignable to their corresponding struct fields.
func ( interface{},  interface{}) interface{} {
	 := reflect.New(reflect.TypeOf()).Elem()
	return scanStruct(, &)
}

func ( interface{},  *reflect.Value) interface{} {
	getBuilderMap().ForEach(func( string,  ps.Any) {
		if ast.IsExported() {
			 := .FieldByName()

			var  reflect.Value
			switch v := .(type) {
			case nil:
				switch .Kind() {
				case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
					 = reflect.Zero(.Type())
nil is not valid for this Type; Set will panic
			case ps.List:
				 = listToSlice(, .Type())
			default:
				 = reflect.ValueOf()
			}
			.Set()
		}
	})

	return .Interface()