Code

#lang racket

;; This solution is partly taken from comments at
;; http://www.billthelizard.com/2012/04/sicp-256-258-symbolic-differentiation.html
;; It can be improved by extending simplifications

; df/dx, expression f, variable x
(define (deriv f x)
  (cond ((number? f) 0)
        ((variable? f)
         (if (same-variable? f x) 1 0))
        ((sum? f)
         (make-sum (deriv (addend f) x)
                   (deriv (augend f) x)))
        ((product? f)
         (make-sum
          (make-product (multiplier f)
                        (deriv (multiplicand f) x))
          (make-product (deriv (multiplier f) x)
                        (multiplicand f))))
        ((exponentiation? f) ; dn/dx = 0
         (let ((u (base f))
               (n (exponent f)))
           (make-product (make-product
                          n
                          (make-exponentiation u (make-sum n -1)))
                         (deriv u x))))
        (else
         (error "unknown expression type -- DERIV" f))))

;; very clever thing
;; Return the operation on the LEVEL of expression ACCORDING to priorities
;; Parentheses are automatically out of the LEVEL!
(define (operation f)
  (cond ((memq '+ f) '+)
        ((memq '* f) '*)
        ((memq '** f) '**)))

;; clever thing
;; returns all before op (operation)
;; this is a first argument of that operation
(define (prefix op f)
  (define (iter f result)
    (if (eq? (car f) op)
        (reverse result)
        (iter (cdr f) (cons (car f) result))))
  (iter f '()))

;; returns all after op (operation)
;; this is a second argument of that operation
(define (postfix op f)
  (cdr (memq op f)))

;; simple simplification
(define (simplify f)
  (if (and (pair? f) (null? (cdr f)))
      (simplify (car f))
      f))

;; (first_arg op) procedure extracts first argument of the operation op in the expression f
;; (second_arg op) procedure extracts second argument of the operation op in the expression f
;; it is handy to combine first/second arg functions with simplification
(define (first-arg op) (lambda (f) (simplify (prefix op f))))
(define (second-arg op) (lambda (f) (simplify (postfix op f))))

;;; representing algebraic expressions

(define (variable? x) (symbol? x))

(define (same-variable? v1 v2)
  (and (variable? v1) (variable? v2) (eq? v1 v2)))

(define (=number? exp num)
  (and (number? exp) (= exp num)))

;; sum

(define (sum? x) (eq? '+ (operation x)))

(define (make-sum a1 a2)
  (cond ((=number? a1 0) a2)
        ((=number? a2 0) a1)
        ((and (number? a1) (number? a2)) (+ a1 a2))
        (else (list a1 '+ a2)))) ; order changed

(define addend (first-arg '+))

(define augend (second-arg '+))

;; product

(define (product? x) (eq? '* (operation x)))

(define (make-product m1 m2)
  (cond ((or (=number? m1 0) (=number? m2 0)) 0)
        ((=number? m1 1) m2)
        ((=number? m2 1) m1)
        ((and (number? m1) (number? m2)) (* m1 m2))
        (else (list m1 '* m2)))) ; order changed

(define multiplier (first-arg '*))

(define multiplicand (second-arg '*))

;; exponentiation

(define (exponentiation? x) (eq? '** (operation x)))

(define (make-exponentiation base exp)
  (cond ((=number? exp 0) 1)
        ((=number? base 1) 1)
        ((=number? exp 1) base)
        ((and (number? base) (number? exp)) (expt base exp))
        (else (list base '** exp))))

(define base (first-arg '**))

(define exponent (second-arg '**))

; tests

(operation '(x * x + 2))
(operation '((x + 1) ** 2 * x))
(operation '((x + 1) ** 2))

(newline)

(prefix
 '*
 '((x + 1) * (x * (y + 2))))

((first-arg '*)
 '((x + 1) * (x * (y + 2))))

(postfix
 '+
 '(x * x + (y + 2)))

((second-arg '+)
 '(x * x + (y + 2)))

(newline)

(simplify '((())))
(simplify '(((7))))
(simplify '(((x))))
(simplify '(((x + 1))))

(newline)

(deriv '(x + x + x) 'x)
(deriv '(x + x + x + x) 'x)
(deriv '(x * x * x) 'x)
(deriv '((x + 1) * x ** 2 * x) 'x)
(deriv '(x * (x + x) * x) 'x)
(deriv '(x + x * x) 'x)
(deriv '(x * x + x) 'x)
(deriv '((x + 2) * (x + 4)) 'x)
(deriv '(x * 3 + 5 * (x + y + 2)) 'x)

Output

'+
'*
'**

'((x + 1))
'(x + 1)
'((y + 2))
'(y + 2)

'()
7
'x
'(x + 1)

3
4
'((x * (x + x)) + (x * x))
'(((x + 1) * ((x ** 2) + ((2 * x) * x))) + (x ** 2 * x))
'((x * ((x + x) + (2 * x))) + ((x + x) * x))
'(1 + (x + x))
'((x + x) + 1)
'((x + 2) + (x + 4))
8