+(define (ast-collect f x)
+ (define (inner y) (ast-collect f y))
+ (case (ast-type x)
+ ['let (append (f x)
+ (fold-map inner (let-bindings x))
+ (fold-map inner (let-body x)))]
+ ['app (append (f x)
+ (fold-map inner x))]
+ ['lambda (append (f x)
+ (inner (lambda-body x)))]
+ ['if (append (f x)
+ (fold-map inner (cdr x)))]
+ [else (f x)]))
+
+(define (ast-find p x)
+ (define (inner y) (ast-find p y))
+ (define (any p x) (fold-left
+ (lambda (acc y) (if acc #t (p y)))
+ #f
+ x))
+ (define (either . fs)
+ (if (null? fs) #f
+ (if (car fs) (car fs)
+ (apply either (cdr fs)))))
+
+ (case (ast-type x)
+ ['let (either (p x)
+ (any inner (let-bindings x))
+ (any inner (let-body x)))]
+ ['app (either (p x)
+ (any inner x))]
+ ['lambda (either (p x)
+ (inner (lambda-body x)))]
+ ['if (either (p x) (any inner (cdr x)))]
+ [else (p x)]))
+