Important edit: You probably have a bug in your function. I do not know about Simpson’s method and can not correct it. But you are calculating some value into *summation*
but at the end you forget everything about your computing and only return the result like you had defined:
(defun simpsons (f a b n)
(let ((h (/ (- b a) n)))
(* (/ h 3.0) (+ (funcall f a) (funcall f (+ (* n h) a))))))
defparameter
and defvar
are meant to define so called “special” variables. Here you need bindings that are local to your function ; let
would be better suited.
What’s more defvar
only assigns the variable if it is not already assigned. That means that if you call your function multiple times with different values you will get wrong results.
Regarding style lispers would make the function return the value, not print it. Just calling it in the interactive environment will print the result. And you can also use (trace simpsons)
to see how your function is called and its output.
Do not put closing parentheses on a line by themselves.
Finally people usually use two semicolons for comments on a line by itself while they use a single semicolon for comments at the end of the line.
Here is your function with these applied:
;; Integration by Simpson's rule; CL code
;; Found to be working correctly with 'sbcl'
(defun simpsons (f a b n)
(let ((summation 0)
(h (/ (- b a) n)))
(loop for k from 2 below (- n 1) by 2
do (setf summation (+ summation (* 2 (funcall f (+ (* k h) a))))))
(loop for k from 1 below n by 2
do (setf summation (+ summation (* 4 (funcall f (+ (* k h) a))))))
(setf summation (+ (funcall f a) (funcall f (+ (* n h) a))))
(* (/ h 3.0) summation)))
(defun cube(x)
(* x x x))
;; Passing around the function to be integrated
(simpsons 'cube 2 3 8) ; demonstrating higher-order functions
Explaination on let
: let
defines a new lexical binding. That is
(let ((summation 0)) …)
makes the name summation
bound to the value 0
in the body of the let
expression. The setf
expressions changes a place which can be a bit complex to describe (see CLHS: Section 5.1 Generalized Reference). In the context
(let ((summation 0))
(setf summation (+ summation 1)))
it changes the binding of summation
from the value 0
to the value 1
. While using
(let ((summation 0))
(let ((summation (+ summation 1)))
;; Here summation is bound to the value 1
…)
;; Here summation is bound to the value 0
…)
makes two lexical bindings for summation
, the first to the value 0
and the second, shadowing the first for the extent of the second let
, to the value 1
.