From: Trent Buck
Subject: debugging
Date: 
Message-ID: <20050326194426.0d673f37@harpo.marx>
Several times recently I've made the same mistake:

	(defun entropy (P &optional (K 2))
	  "Take a probability alist and a base, return the overall entropy."
	  (if (null P)
	      0
	      (+ (* (cdar P)
		    (- (log (cdar P) K)))
		 (entropy (cdr P)))))

instead of

	(defun entropy (P &optional (K 2))
	  "Take a probability alist and a base, return the overall entropy."
	  (if (null P)
	      0
	      (+ (* (cdar P)
		    (- (log (cdar P) K)))
		 (entropy (cdr P) K))))

That is, forgetting to include the optional argument when recursing.
Is there an easy way to detect this error?

-- 
Trent Buck, Student Errant
For their next act, they'll no doubt be buying a firewall running under NT,
which makes about as much sense as building a prison out of meringue.
 -- Tanuki

From: Fred Gilham
Subject: Re: debugging
Date: 
Message-ID: <u7fyyi1lqs.fsf@snapdragon.csl.sri.com>
Instead of

	(defun entropy (P &optional (K 2))
	  "Take a probability alist and a base, return the overall entropy."
	  (if (null P)
	      0
	      (+ (* (cdar P)
		    (- (log (cdar P) K)))
		 (entropy (cdr P) K))))


You could do something like the following:

        (defun entropy (P &optional (K 2))
          "Take a probability alist and a base, return the overall
          entropy."
          (labels ((entropy-1 (P K)
                     (if (null P)
                         0
                         (+ (* (cdar P)
                               (- (log (cdar P) K)))
                            (entropy-1 (cdr P) K)))))
            (entropy-1 P K)))

At least then you will get a warning (i.e. with CMU Lisp) when you
forget the second argument in the recursive call.


-- 
Fred Gilham                                       ······@csl.sri.com
The leading scholar who argued that millions starved during Stalin's
man-made famine was Robert Conquest of the Hoover Institution, often
described in the media as a right-wing think tank. When Mikhail
Gorbachev finally opened the official records in the last days of the
Soviet Union, it turned out that even more people had died during the
famine than Dr. Conquest had estimated.              -- Thomas Sowell
From: Alan Crowe
Subject: Re: debugging
Date: 
Message-ID: <861xa2gogi.fsf@cawtech.freeserve.co.uk>
Fred Gilham offered:

        (defun entropy (P &optional (K 2))
          "Take a probability alist and a base, return the overall
          entropy."
          (labels ((entropy-1 (P K)
                     (if (null P)
                         0
                         (+ (* (cdar P)
                               (- (log (cdar P) K)))
                            (entropy-1 (cdr P) K)))))
            (entropy-1 P K)))

If you use labels, the inner function definition is within
the scope of the argument list, so you can exploit the fact
it is not changing thus:

  (defun entropy (p &optional (base-of-logarithm 2))
    (labels ((ent(p)
		 (if (endp p) 0
		   (+ (* (cdar p)
			 (log (cdar p) base-of-logarithm))
		      (ent (cdr p))))))
       (- (ent p))))

Since we are only going to type it twice instead of three
times, we can afford to give it a more descriptive name :-)

Alan Crowe
Edinburgh
Scotland
From: David Smith
Subject: Re: debugging
Date: 
Message-ID: <f2ua41tg5quteieh8nsvg0vn5viok8fcsq@4ax.com>
On Sat, 26 Mar 2005 08:44:23 GMT, Trent Buck <·········@gmail.com>
wrote:

>	(defun entropy (P &optional (K 2))
>	  "Take a probability alist and a base, return the overall entropy."
>	  (if (null P)
>	      0
>	      (+ (* (cdar P)
>		    (- (log (cdar P) K)))
>		 (entropy (cdr P) K))))

To make it easier to read and easier to notice bugs, change it to
something like this:

(defun entropy (alist &optional (base 2))
  "Take a probability alist and a base, return the overall entropy."
  (loop as (s . p) in alist sum
    (* p (- (log p base)))))
From: Trent Buck
Subject: Re: debugging
Date: 
Message-ID: <20050327020032.2935db00@harpo.marx>
Spake David Smith:
> To make it easier to read and easier to notice bugs, change it to
> something like this:
> 
> (defun entropy (alist &optional (base 2))
>   "Take a probability alist and a base, return the overall entropy."
>   (loop as (s . p) in alist sum
>     (* p (- (log p base)))))

Intriguing.  You've convinced me to learn LOOP.

-- 
Trent Buck, Student Errant
Hmm.  Perhaps sometime next week I will go outside.
From: Wade Humeniuk
Subject: Re: debugging
Date: 
Message-ID: <qif1e.74220$KI2.38965@clgrps12>
Trent Buck wrote:
> 
> That is, forgetting to include the optional argument when recursing.
> Is there an easy way to detect this error?
> 

You should probably deal with the faulty source of the problem.  Tie
some electric paddles to your feet, and when you make an error....

:)

Another way would be to write a error checking function. That
will walk your source and flag potential errors like that. (functions
which call themsleves and have optional arguments.  However this
a temporary problem, as there is still the faulty source of the
problem generating errors.  (One note, all errors are not bad).

Wade
From: Pascal Bourguignon
Subject: Re: debugging
Date: 
Message-ID: <87mzsqw3gi.fsf@thalassa.informatimago.com>
Wade Humeniuk <··················@telus.net> writes:

> Trent Buck wrote:
> > That is, forgetting to include the optional argument when recursing.
> > Is there an easy way to detect this error?
> >
> 
> You should probably deal with the faulty source of the problem.  Tie
> some electric paddles to your feet, and when you make an error....
> 
> :)
> 
> Another way would be to write a error checking function. That
> will walk your source and flag potential errors like that. (functions
> which call themsleves and have optional arguments.  However this
> a temporary problem, as there is still the faulty source of the
> problem generating errors.  (One note, all errors are not bad).

You'd need to add a declaration:

    (declare (all-recursive-calls-must-include-optional-arguments k))

or:

    (declare (all-calls-must-include-optional-arguments entropy k))


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

Nobody can fix the economy.  Nobody can be trusted with their finger
on the button.  Nobody's perfect.  VOTE FOR NOBODY.
From: Wade Humeniuk
Subject: Re: debugging
Date: 
Message-ID: <Mln1e.111328$fc4.73925@edtnps89>
Pascal Bourguignon wrote:

> 
> You'd need to add a declaration:
> 
>     (declare (all-recursive-calls-must-include-optional-arguments k))
> 
> or:
> 
>     (declare (all-calls-must-include-optional-arguments entropy k))
> 

A more encompassing declaration would be in order

(declare (tolerate-programmer-stupidity -3))

Wade
From: Pascal Bourguignon
Subject: Re: debugging
Date: 
Message-ID: <87r7i2wif7.fsf@thalassa.informatimago.com>
Trent Buck <·········@gmail.com> writes:

> Several times recently I've made the same mistake:
> 
> 	(defun entropy (P &optional (K 2))
> 	  "Take a probability alist and a base, return the overall entropy."
> 	  (if (null P)
> 	      0
> 	      (+ (* (cdar P)
> 		    (- (log (cdar P) K)))
> 		 (entropy (cdr P)))))
> 
> instead of
> 
> 	(defun entropy (P &optional (K 2))
> 	  "Take a probability alist and a base, return the overall entropy."
> 	  (if (null P)
> 	      0
> 	      (+ (* (cdar P)
> 		    (- (log (cdar P) K)))
> 		 (entropy (cdr P) K))))
> 
> That is, forgetting to include the optional argument when recursing.
> Is there an easy way to detect this error?

Perhaps don't use an optional parameter?

(defvar *base* 2)

(defun entropy (P)
  "Take a probability alist, return the overall entropy given the *base*."
 	  (if (null P)
 	      0
 	      (+ (* (cdar P) (- (log (cdar P) *base*))) (entropy (cdr P)))))


(entropy p)                    ; with default *base*
(let ((*base* 3)) (entropy p)) ; with a different *base*


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
Our enemies are innovative and resourceful, and so are we. They never
stop thinking about new ways to harm our country and our people, and
neither do we. -- Georges W. Bush
From: Trent Buck
Subject: Re: debugging
Date: 
Message-ID: <20050327025842.7f795d9b@harpo.marx>
Spake Pascal Bourguignon:
> > 	(defun entropy (P &optional (K 2))
> > 	  "Take a probability alist and a base, return the overall entropy."
> > 	  (if (null P)
> > 	      0
> > 	      (+ (* (cdar P)
> > 		    (- (log (cdar P) K)))
> > 		 (entropy (cdr P) K))))
> > 
> > That is, forgetting to include the optional argument when recursing.
> > Is there an easy way to detect this error?
> 
> Perhaps don't use an optional parameter?

Simply omitting &optional, even.  Good idea.

> (defvar *base* 2)
> 
> (defun entropy (P)
>   "Take a probability alist, return the overall entropy given the *base*."
>  	  (if (null P)
>  	      0
>  	      (+ (* (cdar P) (- (log (cdar P) *base*))) (entropy (cdr P)))))
> 
> 
> (entropy p)                    ; with default *base*
> (let ((*base* 3)) (entropy p)) ; with a different *base*

-- 
Trent Buck, Student Errant
Hang on, this is no WENDIGO... It's some kind of HAPPY LOLLIPOP designed
by JAPANESE SCIENTISTS!
 -- Bob the Angry Flower, Wendigo
From: Alan Crowe
Subject: Re: debugging
Date: 
Message-ID: <86y8caf8g6.fsf@cawtech.freeserve.co.uk>
Trent Buck seeks an insecticide for a particular kind of bug

     Several times recently I've made the same mistake:

	(defun entropy (P &optional (K 2))
	  "Take a probability alist and a base, return the overall entropy."
	  (if (null P)
	      0
	      (+ (* (cdar P)
		    (- (log (cdar P) K)))
		 (entropy (cdr P) ))))
                                 ^
                                 |
                                 `--  Whoops forgot the K

A general idea is to separate out the sequence-engine and
the code it is sequencing.  For example

sequence-engine:

(defun expectation (discrete-probability-distribution
		    pointwise-function)
    (loop for (item . prob) in discrete-probability-distribution
	  sum (* prob (funcall pointwise-function item prob))))

Build the application by providing a function to the sequence-engine:

(defun entropy (discrete-distribution
                &optional (base-of-logarithm 2))
    (- (expectation discrete-distribution
		    (lambda(i p)
		     (declare (ignore i))
		     (log p base-of-logarithm)))))

Alan Crowe
Edinburgh
Scotland