;
;    @file       factorial.scm
;    @brief      Scheme language primer
;    @date       April 2012
;    @copyright  © 2012 <okertanov@gmail.com>
;

;
; Language
;
#lang scheme

;
; Declarative factorial function in Scheme
;


;
; Syntactic sugar
;

(define-syntax-rule (the a b)
  (begin (define a b) a))

(define-syntax-rule (is e) e)

(define-syntax-rule (to e) e)

(define less/than? (λ (a b)
  (< a b)))
 

;
; Formal description
;

#|
    http://en.wikipedia.org/wiki/Factorial

    The factorial of a non-negative integer n, denoted by n!,
    is the product of all positive integers less than or equal to n.
    The value of 0! is 1.
|#

;
; Definition
;

(the factorial/of
  (λ (a)
    (let ((n a))
      (cond
        ((and (not (negative? n)) (integer? n))
          "denoted by n!"
          (is
            (the of/all
              (for/product
                ((i ((λ (s)
                  (stop-before (in-naturals)
                    (λ (i)(not (or (less/than? i s) (equal? i s))))
                  )
                )(to n))))
                (cond
                  ((and (positive? i) (integer? i)) i)
                  ((zero? i) "the value of 0! is 1" 1)
                  (else -inf.0)
                )
              )
            )
          )
        )
      )
    )
  )
)
 

;
; Application
;
(factorial/of 5)

;
; Result
;

#|
    #<procedure:factorial/of>
    120
|#