
;; Question 1:

(define pos-in-list-aux
  (lambda (pred lst pos)
    (if (null? lst) 
	'()
	(if (pred (car lst))
	    (cons pos (pos-in-list-aux pred (cdr lst) (+ pos 1)))
	    (pos-in-list-aux pred (cdr lst) (+ pos 1))))))

(define pos-in-list
  (lambda (pred lst)
    (pos-in-list-aux pred lst 0)))


;; Question 2:

(define pair2list
  (lambda (p)
	(merge (car p) (cdr p))))

(define merge
  (lambda (l1 l2)
    (if (null? l1)
	'()
	(cons (cons (car l1) (car l2))
	      (merge (cdr l1) (cdr l2))))))

(define list2pair
  (lambda (l)
    (if (null? l)
	'(().())
	(let ((p (car l))
	      (l2p (list2pair (cdr l))))
	  (cons (cons (car p) (car l2p))
		(cons (cdr p) (cdr l2p)))))))


;; Question 2 (another alternative):

(define pair2list
  (lambda (p)
    (map cons (car p) (cdr p))
  )
)

(define list2pair
  (lambda (l)
    (cons (map car l) (map cdr l))
  )
)


;; Question 3:

(define map-n-list
  (lambda (p nlst)
    (map (map-n-list-exp p) nlst)))

(define map-n-list-exp
  (lambda (p)
    (lambda (nle)
      (if (number? nle)
	  (p nle)
	  (map-n-list p nle)))))


;; Question 4:

(define not-in-env
  (lambda (sym)
     (eopl:error 'apply-env "No binding for ~s" sym)))

(define empty-env
  (lambda ()
    '()))

(define extend-env
  (lambda (syms vals env)
    (append (pair2list (cons syms vals)) env)))

(define apply-env
  (lambda (env sym) 
    (if (null? env)
	(not-in-env sym)
	(if (eqv? (caar env) sym)
	    (cdar env)
	    (apply-env (cdr env) sym)))))

; e.g.:

(apply-env (extend-env '(x y) '(0 1) (empty-env)) 'x)


;; Question 5:

(define not-in-env
  (lambda (sym)
          'free))

(define lexical-depth
  (lambda (exp)
    ((lexical-depth-env (empty-env)) exp)))

(define lexical-depth-env
  (lambda (env)
    (lambda (exp)
       (cond ((symbol? exp) (cons exp (apply-env env exp)))
          ((eq? 'lambda (car exp))
           (list 'lambda (cadr exp)
                 ((lexical-depth-env (update-env env (cadr exp))) 
		  (caddr exp))))
          (else (map (lexical-depth-env env) exp))))))

(define update-env
  (lambda (env formals)
    (extend-env formals (replicate 0 (length formals)) 
		(inc-depth env))))

(define inc-depth
  (lambda (env)
    (map
      (lambda (varref)
        (cons (car varref) (+ (cdr varref) 1)))
      env)))

(define replicate
  (lambda (val times)
    (if (= times 0)
        '()
        (cons val (replicate val (- times 1))))))

; e.g.:

(lexical-depth '(lambda (a)
		  ((lambda (c)
                          (a c))
                        (a b))))
