The following comes again from Genlt introduction to Symbolic Computation p. 257, Exercise 4. Given a list of symbols (A T G C), representing a strand of DNA, count the number of DNA bases in the strand in a function called COUNT-BASES. The catch is that the DNA strand could be either a single strand or a double strand (since DNA is double-stranded, except during replication). Thus the function could be called as
The function works properly under both Clozure and LispWorks, though I get a warning from LispWorks when I compile it:
Moreover, is it good Lisp style to do something like this?
(COUNT-BASES '((G C) (A T) (T A) (T A) (C G)))
which would return((A 3) (T 3) (G 2) (C 2))
or it could be called as(COUNT-BASES '(A G T A C T C T))
which would return((A 2) (T 3) (G 1) (C 2))
I wrote it up as(defun count-bases (dna)
(let ((num-a 0)
(num-t 0)
(num-g 0)
(num-c 0))
(defun count-nucleotides (x)
(cond ((eq x 'a) (incf num-a))
((eq x 't) (incf num-t))
((eq x 'g) (incf num-g))
((eq x 'c) (incf num-c))))
(dolist (base-pair dna
(list (list 'a num-a) (list 't num-t) (list 'g num-g) (list 'c num-c)))
(cond ((listp base-pair) (count-nucleotides (car base-pair))
(count-nucleotides (cadr base-pair)))
(t (count-nucleotides base-pair))))))
I defined the function COUNT-NUCLEOTIDES within the body of the function COUNT-BASES in order to take advantage of the lexical environment of the LET block; the alternative would have been to either use as global variables NUM-A. NUM-T, NUM-G, NUM-C; or to define a(defstruct base-count
(num-a 0)
(num-t 0)
(num-g 0)
(num-c 0))
and pass the structure by value along with the variable X to update the count of the components in each iteration. For simplicity's sake I chose to define the sub-function COUNT-NUCLEOTIDES within COUNT-BASES. The function works properly under both Clozure and LispWorks, though I get a warning from LispWorks when I compile it:
The following function is undefined:
COUNT-NUCLEOTIDES which is referenced by COUNT-BASES
Is the warning legitimate? Are nested function definitions allowed in Common Lisp?Moreover, is it good Lisp style to do something like this?