package lambda func Rename(expr Expression, target string, newName string) Expression { switch e := expr.(type) { case *Variable: if e.value == target { return NewVariable(newName) } return e case *Abstraction: newParam := e.parameter if e.parameter == target { newParam = newName } newBody := Rename(e.body, target, newName) if newParam == e.parameter && newBody == e.body { return e } return NewAbstraction(newParam, newBody) case *Application: newAbs := Rename(e.abstraction, target, newName) newArg := Rename(e.argument, target, newName) if newAbs == e.abstraction && newArg == e.argument { return e } return NewApplication(newAbs, newArg) default: return expr } }