From: ·············@gmail.com
Subject: Lisp Question
Date: 
Message-ID: <1184795447.888665.194370@i38g2000prf.googlegroups.com>
Hi everyone,

I'm a new Lisp learner. I'm doing the DNA problem. The function is
supposed to count the bases A, T, G, C in either a single dna
(represented as a list, e.g (a a t t)) or a complement dna
(represented as a table, e.g ((a t) (a t)
(t a) (c g))). My function count rights but the viriable result get
accumulated on subsequent calls. I don't understand why. Could you
shed some light?

Thanks very much.

(defun count-bases (strand)
  (let ((result '((a 0) (t 0) ( g 0) (c 0))))
    (dolist (base strand result)
      (cond ((atom base)(incf (second (assoc base result))))
	    (t (incf (second (assoc (first base) result)))
	       (incf (second (assoc (second base) result))))))))

From: Kent M Pitman
Subject: Re: Lisp Question
Date: 
Message-ID: <u644h1f6j.fsf@nhplace.com>
·············@gmail.com writes:

> Hi everyone,
> 
> I'm a new Lisp learner.

Welcome!

(Btw, if this is homework you should have said so, and should say so
in the future.  People don't mind helping you get started homework,
but they answer differently when it is so they don't end up doing it
all for you.  I've answered less directly in some ways than I might
do otherwise, being not sure.)

> I'm doing the DNA problem. The function is
> supposed to count the bases A, T, G, C in either a single dna
> (represented as a list, e.g (a a t t)) or a complement dna
> (represented as a table, e.g ((a t) (a t)
> (t a) (c g))). My function count rights but the viriable result get
> accumulated on subsequent calls. I don't understand why. Could you
> shed some light?
> 
> Thanks very much.
> 
> (defun count-bases (strand)
>   (let ((result '((a 0) (t 0) ( g 0) (c 0))))
>     (dolist (base strand result)
>       (cond ((atom base)(incf (second (assoc base result))))
> 	    (t (incf (second (assoc (first base) result)))
> 	       (incf (second (assoc (second base) result))))))))

You're modifying the constant structure.  QUOTE just returns the object
(think of it as a pointer to a constantly allocated language if you're
used to that in other languages).  On subsequent calls, this will have
the modified results. (Actually, in some implementations you may get an
error before that point, but if you don't, that's the most likely result.
From a language point of view, what you've done is simply undefined and
pretty much anything that happens is valid from the implementation's point
of view since you violated your contract as a user when you did that.)

You'll want to use calls to LIST, as in (list (list 'a ...) ...) rather
than that quoted structure.

In fact, if this is not homework, or some other form of learning
exercise specifically aimed at figuring out ASSOC, this is not how I'd
recommend you do this.  All those calls to ASSOC are high overhead for
the value you're getting.  I'd suggest the following.  I'll show the code
since no one ever seems to make homework that allows one to use really
useful primitives--sigh.

(defun count-bases (strand)
  (let ((na 0) (nc 0) (ng 0) (nt 0))
    (macrolet ((notice (ref)
                 `(let ((r ,ref))
                    (ecase r
                      ((a) (incf na))
                      ((c) (incf nc))
                      ((g) (incf ng))
                      ((t) (incf nt))))))
      (dolist (base strand)
        (cond ((atom base) (notice base))
              (t
               (notice (first base))
               (notice (second base)))))
      (values na nc ng nt))))

Note, too, that this solution doesn't involve any consing.  If you
were going to use the solution you had, you'd at least have to cons
the list to be returned.  Instead what I've done here is return four
values that can be picked up with MULTIPLE-VALUE-BIND in the caller.
From: Ron Garret
Subject: Re: Lisp Question
Date: 
Message-ID: <rNOSPAMon-C47380.00010819072007@news.gha.chartermi.net>
In article <·············@nhplace.com>,
 Kent M Pitman <······@nhplace.com> wrote:

> no one ever seems to make homework that allows one to use really
> useful primitives--sigh.

What would you consider to be an example of such homework?  And (or?) 
what would you consider to be a really useful primitive?

rg
From: Kent M Pitman
Subject: Re: Lisp Question
Date: 
Message-ID: <uhco0qu1h.fsf@nhplace.com>
Ron Garret <·········@flownet.com> writes:

> In article <·············@nhplace.com>,
>  Kent M Pitman <······@nhplace.com> wrote:
> 
> > no one ever seems to make homework that allows one to use really
> > useful primitives--sigh.
> 
> What would you consider to be an example of such homework?  And (or?) 
> what would you consider to be a really useful primitive?

I think they use us a lot to teach recursion, even though CL
doesn't have tail calling.  You could say this was a weakness of CL
but in practice it isn't a huge impediment, in part because there are
a lot of good iteration tools and they are largely not taught.  This
is somewhat what I was talking about.  Places where you ought to use
DOLIST or LOOP with an appropriately named keyword aren't taught.  You
can be sure that the result wants to be some icky, unreadable
recursion and that if it comes out looking like
  (LOOP FOR (A . B) IN FOO WHEN (ODDP X) COLLECT B)
are going to look a lot worse in recursion.  That's partly what I meant.
And the thing is that even though some disagree with LOOP as an avenue of
first resort for programming [though I've come to like it over time], the
things it has to teach are lost [usefully named component-wise idioms that
say what they mean, an illustration of a truly powerful macro that doesn't
just work by trivial substitution but by something that really calls for
Turing power in your macro processor step, etc.]

And I think there's a strong emphasis in classes on overwhelming students
by repeated uses of CADR and such, instead of naming the operators something
useful and using abstractions, such that people come away thinking we like
seeing weirdly named operators and we have no abstraction capability.
So lists are mostly what they teach, and then not well, and people come away
thinking our lists are confused because they don't have the same structure
as lists in C++.

I doubt many in school are teaching DEFCLASS or DEFMETHOD in classes,
since they already teach Java or C#, and so probably that means people
aren't learning useful concepts like method combination or
CHANGE-CLASS or multiple inheritance or idiomatic issues like before
and after methods.  Some people fortunately seek out CLOS eventually to
learn these things on their own--certainly AMOP is a worthy teaching 
document.

I could probably name more, but I'm in a hurry.  I hope that gives you the
idea.
From: Ron Garret
Subject: Re: Lisp Question
Date: 
Message-ID: <rNOSPAMon-EBBF6B.09593419072007@news.gha.chartermi.net>
In article <·············@nhplace.com>,
 Kent M Pitman <······@nhplace.com> wrote:

> Ron Garret <·········@flownet.com> writes:
> 
> > In article <·············@nhplace.com>,
> >  Kent M Pitman <······@nhplace.com> wrote:
> > 
> > > no one ever seems to make homework that allows one to use really
> > > useful primitives--sigh.
> > 
> > What would you consider to be an example of such homework?  And (or?) 
> > what would you consider to be a really useful primitive?
> 
> I think they use us a lot to teach recursion, even though CL
> doesn't have tail calling.  You could say this was a weakness of CL
> but in practice it isn't a huge impediment, in part because there are
> a lot of good iteration tools and they are largely not taught.  This
> is somewhat what I was talking about.  Places where you ought to use
> DOLIST or LOOP with an appropriately named keyword aren't taught.  You
> can be sure that the result wants to be some icky, unreadable
> recursion and that if it comes out looking like
>   (LOOP FOR (A . B) IN FOO WHEN (ODDP X) COLLECT B)
> are going to look a lot worse in recursion.  That's partly what I meant.
> And the thing is that even though some disagree with LOOP as an avenue of
> first resort for programming [though I've come to like it over time], the
> things it has to teach are lost [usefully named component-wise idioms that
> say what they mean, an illustration of a truly powerful macro that doesn't
> just work by trivial substitution but by something that really calls for
> Turing power in your macro processor step, etc.]
> 
> And I think there's a strong emphasis in classes on overwhelming students
> by repeated uses of CADR and such, instead of naming the operators something
> useful and using abstractions, such that people come away thinking we like
> seeing weirdly named operators and we have no abstraction capability.
> So lists are mostly what they teach, and then not well, and people come away
> thinking our lists are confused because they don't have the same structure
> as lists in C++.
> 
> I doubt many in school are teaching DEFCLASS or DEFMETHOD in classes,
> since they already teach Java or C#, and so probably that means people
> aren't learning useful concepts like method combination or
> CHANGE-CLASS or multiple inheritance or idiomatic issues like before
> and after methods.  Some people fortunately seek out CLOS eventually to
> learn these things on their own--certainly AMOP is a worthy teaching 
> document.
> 
> I could probably name more, but I'm in a hurry.  I hope that gives you the
> idea.

Yes, thanks.

rg
From: ·············@gmail.com
Subject: Re: Lisp Question
Date: 
Message-ID: <1184882968.213142.266410@x35g2000prf.googlegroups.com>
On Jul 18, 5:10 pm, Kent M Pitman <······@nhplace.com> wrote:
> ·············@gmail.com writes:
> > Hi everyone,
>
> > I'm a new Lisp learner.
>
> Welcome!
>
> (Btw, if this is homework you should have said so, and should say so
> in the future.  People don't mind helping you get started homework,
> but they answer differently when it is so they don't end up doing it
> all for you.  I've answered less directly in some ways than I might
> do otherwise, being not sure.)
>
>
>
> > I'm doing the DNA problem. The function is
> > supposed to count the bases A, T, G, C in either a single dna
> > (represented as a list, e.g (a a t t)) or a complement dna
> > (represented as a table, e.g ((a t) (a t)
> > (t a) (c g))). My function count rights but the viriable result get
> > accumulated on subsequent calls. I don't understand why. Could you
> > shed some light?
>
> > Thanks very much.
>
> > (defun count-bases (strand)
> >   (let ((result '((a 0) (t 0) ( g 0) (c 0))))
> >     (dolist (base strand result)
> >       (cond ((atom base)(incf (second (assoc base result))))
> >        (t (incf (second (assoc (first base) result)))
> >           (incf (second (assoc (second base) result))))))))
>
> You're modifying the constant structure.  QUOTE just returns the object
> (think of it as a pointer to a constantly allocated language if you're
> used to that in other languages).  On subsequent calls, this will have
> the modified results. (Actually, in some implementations you may get an
> error before that point, but if you don't, that's the most likely result.
> From a language point of view, what you've done is simply undefined and
> pretty much anything that happens is valid from the implementation's point
> of view since you violated your contract as a user when you did that.)
>
> You'll want to use calls to LIST, as in (list (list 'a ...) ...) rather
> than that quoted structure.
>
> In fact, if this is not homework, or some other form of learning
> exercise specifically aimed at figuring out ASSOC, this is not how I'd
> recommend you do this.  All those calls to ASSOC are high overhead for
> the value you're getting.  I'd suggest the following.  I'll show the code
> since no one ever seems to make homework that allows one to use really
> useful primitives--sigh.
>
> (defun count-bases (strand)
>   (let ((na 0) (nc 0) (ng 0) (nt 0))
>     (macrolet ((notice (ref)
>                  `(let ((r ,ref))
>                     (ecase r
>                       ((a) (incf na))
>                       ((c) (incf nc))
>                       ((g) (incf ng))
>                       ((t) (incf nt))))))
>       (dolist (base strand)
>         (cond ((atom base) (notice base))
>               (t
>                (notice (first base))
>                (notice (second base)))))
>       (values na nc ng nt))))
>
> Note, too, that this solution doesn't involve any consing.  If you
> were going to use the solution you had, you'd at least have to cons
> the list to be returned.  Instead what I've done here is return four
> values that can be picked up with MULTIPLE-VALUE-BIND in the caller.

Hi!

Thanks. Your answer is very helpful and detailed. By the way this is
not a homework problem; I've been learning Lisp from the book: Common
Lisp, A Simple Introduction to .... This is just one of the keyboard
exercises I've been doing.

Thanks again.

Mark.
From: Alan Crowe
Subject: Re: Lisp Question
Date: 
Message-ID: <86ps2nufqu.fsf@cawtech.freeserve.co.uk>
···············@gmail.com writes:

> By the way this is
> not a homework problem; I've been learning Lisp from the book: Common
> Lisp, A Simple Introduction to .... This is just one of the keyboard
> exercises I've been doing.
> |#

;;; Welcome to c.l.l. You will find the language is packed full of goodies,
;;; There are some very pretty and under taught techniques for making your
;;; code read nicely.

;;; One of my favourites is to define your own types

(deftype single-base () '(member a c t g))

(deftype base-pair ()
  '(cons single-base
         (cons single-base null)))

;;; and then use typecase and friends instead of if and cond

(format t "~&Printing (a (c t))~%~%")

(dolist (x '(a (c t)))
  (etypecase x
    (single-base (print x))
    (base-pair (print (first x))
               (print (second x)))))


#|  That should print 
A
C
T

if you save this post to a file and load it into your CL
image (which is why I'm using comments) |#

;;; Is it really a good idea to have lists that mix single bases with
;;; base pairs? If it is, you could define your own version of dolist,
;;; specific to strands

(defmacro dostrand ((variable strand-form &optional result-form) &body code)
  (let ((function-name (gensym)))
    `(flet ((,function-name (,variable) ,@code))
      (dolist (base ,strand-form)
        (etypecase base
          (single-base (,function-name base))
          (base-pair
           (,function-name (first base))
           (,function-name (second base)))))
      ,result-form)))

(format t "~&Printing (a (c t)) again.")

(dostrand (x '(a (c t)))
  (print x))

;;; Part of the attraction of doing things this way is that
;;; it automatically adds copious error checking, which is
;;; very handy when you are learning a language

(restart-case
    (dostrand (x '(a (c t g) t))
      (print x))
  (continue ()
    :report "Continue loading tutorial post"
    'skipping))

(restart-case
    (dostrand (x '(a g (c d) t g))
      (print x))
  (continue ()
    :report "Press on with load."
    nil))
            
;;; The restart-case's mean that you can load this file,
;;; and see what I mean about error messages, and yet
;;; not have to abort loading the file.  
 
(defun count-base (strand)
  (let ((result (copy-tree '((a 0)(c 0)(g 0)(t 0)))))
    (dostrand (base strand result)
      (incf (second (assoc base result))))))

(format t "~%~%Counting bases~%~%")

(print (count-base '(a (c t)(g a))))

;;; Alan Crowe
;;; Edinburgh
;;; Scotland
From: ·············@gmail.com
Subject: Re: Lisp Question
Date: 
Message-ID: <1184883098.842763.269570@x35g2000prf.googlegroups.com>
On Jul 18, 5:10 pm, Kent M Pitman <······@nhplace.com> wrote:
> ·············@gmail.com writes:
> > Hi everyone,
>
> > I'm a new Lisp learner.
>
> Welcome!
>
> (Btw, if this is homework you should have said so, and should say so
> in the future.  People don't mind helping you get started homework,
> but they answer differently when it is so they don't end up doing it
> all for you.  I've answered less directly in some ways than I might
> do otherwise, being not sure.)
>
>
>
> > I'm doing the DNA problem. The function is
> > supposed to count the bases A, T, G, C in either a single dna
> > (represented as a list, e.g (a a t t)) or a complement dna
> > (represented as a table, e.g ((a t) (a t)
> > (t a) (c g))). My function count rights but the viriable result get
> > accumulated on subsequent calls. I don't understand why. Could you
> > shed some light?
>
> > Thanks very much.
>
> > (defun count-bases (strand)
> >   (let ((result '((a 0) (t 0) ( g 0) (c 0))))
> >     (dolist (base strand result)
> >       (cond ((atom base)(incf (second (assoc base result))))
> >        (t (incf (second (assoc (first base) result)))
> >           (incf (second (assoc (second base) result))))))))
>
> You're modifying the constant structure.  QUOTE just returns the object
> (think of it as a pointer to a constantly allocated language if you're
> used to that in other languages).  On subsequent calls, this will have
> the modified results. (Actually, in some implementations you may get an
> error before that point, but if you don't, that's the most likely result.
> From a language point of view, what you've done is simply undefined and
> pretty much anything that happens is valid from the implementation's point
> of view since you violated your contract as a user when you did that.)
>
> You'll want to use calls to LIST, as in (list (list 'a ...) ...) rather
> than that quoted structure.
>
> In fact, if this is not homework, or some other form of learning
> exercise specifically aimed at figuring out ASSOC, this is not how I'd
> recommend you do this.  All those calls to ASSOC are high overhead for
> the value you're getting.  I'd suggest the following.  I'll show the code
> since no one ever seems to make homework that allows one to use really
> useful primitives--sigh.
>
> (defun count-bases (strand)
>   (let ((na 0) (nc 0) (ng 0) (nt 0))
>     (macrolet ((notice (ref)
>                  `(let ((r ,ref))
>                     (ecase r
>                       ((a) (incf na))
>                       ((c) (incf nc))
>                       ((g) (incf ng))
>                       ((t) (incf nt))))))
>       (dolist (base strand)
>         (cond ((atom base) (notice base))
>               (t
>                (notice (first base))
>                (notice (second base)))))
>       (values na nc ng nt))))
>
> Note, too, that this solution doesn't involve any consing.  If you
> were going to use the solution you had, you'd at least have to cons
> the list to be returned.  Instead what I've done here is return four
> values that can be picked up with MULTIPLE-VALUE-BIND in the caller.

Hi,

Thanks a lot. Your answer is very helpful and detailed. By the way
this is not a homework problem; I've been learning Lisp myself from
the book "Common Lisp: A Simple Introduction to Symbolic Computation."
This is just one of the keyboard exercises that I've been doing.

Thanks again.

Mark.
From: Robert Uhl
Subject: Re: Lisp Question
Date: 
Message-ID: <m3zm1rln5q.fsf@latakia.dyndns.org>
Kent M Pitman <······@nhplace.com> writes:
>
> (defun count-bases (strand)
>   (let ((na 0) (nc 0) (ng 0) (nt 0))
>     (macrolet ((notice (ref)
>                  `(let ((r ,ref))
>                     (ecase r
>                       ((a) (incf na))
>                       ((c) (incf nc))
>                       ((g) (incf ng))
>                       ((t) (incf nt))))))
>       (dolist (base strand)
>         (cond ((atom base) (notice base))
>               (t
>                (notice (first base))
>                (notice (second base)))))
>       (values na nc ng nt))))
>
> Note, too, that this solution doesn't involve any consing.

Is that why you use MACROLET instead of FLET or LABELS?  Or is that a
stupid question?

-- 
Robert Uhl <http://public.xdi.org/=ruhl>
Quidquid latine dictum sit, altum viditur.
Whatever is said in Latin sounds profound.
From: Kent M Pitman
Subject: Re: Lisp Question
Date: 
Message-ID: <ulkdbptp9.fsf@nhplace.com>
Robert Uhl <·········@NOSPAMgmail.com> writes:

> Kent M Pitman <······@nhplace.com> writes:
> >
> > (defun count-bases (strand)
> >   (let ((na 0) (nc 0) (ng 0) (nt 0))
> >     (macrolet ((notice (ref)
> >                  `(let ((r ,ref))
> >                     (ecase r
> >                       ((a) (incf na))
> >                       ((c) (incf nc))
> >                       ((g) (incf ng))
> >                       ((t) (incf nt))))))
> >       (dolist (base strand)
> >         (cond ((atom base) (notice base))
> >               (t
> >                (notice (first base))
> >                (notice (second base)))))
> >       (values na nc ng nt))))
> >
> > Note, too, that this solution doesn't involve any consing.
> 
> Is that why you use MACROLET instead of FLET or LABELS?

Well, I didn't try it in several implementations to see how it varies,
but I suspect in most compilers, an internal FLET that is easily shown
not to escape will give you no consing either.  With some compilers,
using FLET will not get you inlining, even if you ask for it, but
probably many will.  Using MACROLET makes it hard for it not to
inline, but the choice was pretty arbitrary.  It would look like this
with a FLET...

(defun count-bases (strand)
  (let ((na 0) (nc 0) (ng 0) (nt 0))
    (flet ((notice (ref)
             (ecase ref
               ((a) (incf na))
               ((c) (incf nc))
               ((g) (incf ng))
               ((t) (incf nt)))))
      (declare (inline notice))
      (dolist (base strand)
        (cond ((atom base) (notice base))
              (t
               (notice (first base))
               (notice (second base)))))
      (values na nc ng nt))))

As nearly as I can tell from a m-x compare-windows in Emacs, LispWorks
generates identical assembly code whether you write it as a macro or an
inline fucntion.

Not that I think fussing over the speed and consing is a big deal
until you've got a delivered application that's running too slowly.
Often times worrying about these kinds of things too early is a waste
of time.  But you asked, so I'm answering.  I often have reasons for
doing things, but that doesn't mean they're rules I'd recommend others
necessarily follow... the trouble is one has to make SOME decision and
so one develops rules of thumb for all kinds of arbitrary things.

Btw, I tend not to use LABELS unless there's a recursion or
interdependency among the established functions, sort of like many
people don't use LET* unless there's a dependency, but that's a
personal style choice.

> Or is that a stupid question?

If one doesn't understand something about the tools they're using, I
don't think it's ever stupid to ask.  Programming is not supposed to
be an exercise in mysticism.
From: Jon Harrop
Subject: Re: Lisp Question
Date: 
Message-ID: <469f396f$0$1627$ed2619ec@ptn-nntp-reader02.plus.net>
·············@gmail.com wrote:
> I'm a new Lisp learner. I'm doing the DNA problem. The function is
> supposed to count the bases A, T, G, C in either a single dna
> (represented as a list, e.g (a a t t)) or a complement dna
> (represented as a table, e.g ((a t) (a t)
> (t a) (c g))). My function count rights but the viriable result get
> accumulated on subsequent calls. I don't understand why. Could you
> shed some light?
> 
> Thanks very much.
> 
> (defun count-bases (strand)
>   (let ((result '((a 0) (t 0) ( g 0) (c 0))))
>     (dolist (base strand result)
>       (cond ((atom base)(incf (second (assoc base result))))
> (t (incf (second (assoc (first base) result)))
> (incf (second (assoc (second base) result))))))))

You may be interested in an OCaml equivalent:

# let count_bases =
    List.fold_left (fun (a, t, g, c) -> function
      | `A -> a+1, t, g, c
      | `T -> a, t+1, g, c
      | `G -> a, t, g+1, c
      | `C -> a, t, g, c+1) (0, 0, 0, 0);;
val count_bases : _[< `A | `C | `G | `T ] list -> int * int * int * int =
  <fun>

Note the inferred type.

-- 
Dr Jon D Harrop, Flying Frog Consultancy
OCaml for Scientists
http://www.ffconsultancy.com/products/ocaml_for_scientists/?usenet
From: Raffael Cavallaro
Subject: Re: Lisp Question
Date: 
Message-ID: <200707191354448930-raffaelcavallaro@pasdespamsilvousplaitmaccom>
On 2007-07-19 06:04:48 -0400, Jon Harrop <···@ffconsultancy.com> said:

> You may be interested in an OCaml equivalent:

He might be interested in a George Foreman Grill - why don't you sell 
him one of those too.

Spammer.
From: jayessay
Subject: Re: Lisp Question
Date: 
Message-ID: <m3r6n4s0o3.fsf@sirius.goldenthreadtech.com>
Raffael Cavallaro <················@pas-d'espam-s'il-vous-plait-mac.com> writes:

> On 2007-07-19 06:04:48 -0400, Jon Harrop <···@ffconsultancy.com> said:
> 
> > You may be interested in an OCaml equivalent:
> 
> He might be interested in a George Foreman Grill - why don't you sell
> him one of those too.

It would at least have the advantage of actually being useful.[1]


/Jon

1. This is the first Harrop turd I've seen in quite some time.  The
   frog (toad) is actually the only person I've ever KF'd and the
   result has indeed been bliss!

-- 
'j' - a n t h o n y at romeo/charley/november com
From: Andras Simon
Subject: Re: Lisp Question
Date: 
Message-ID: <vcd1wf4extg.fsf@csusza.math.bme.hu>
Jon Harrop <···@ffconsultancy.com> writes:

> ·············@gmail.com wrote:
> > I'm a new Lisp learner. I'm doing the DNA problem. The function is
> > supposed to count the bases A, T, G, C in either a single dna
> > (represented as a list, e.g (a a t t)) or a complement dna
> > (represented as a table, e.g ((a t) (a t)
> > (t a) (c g))). My function count rights but the viriable result get
> > accumulated on subsequent calls. I don't understand why. Could you
> > shed some light?
> > 
> > Thanks very much.
> > 
> > (defun count-bases (strand)
> >   (let ((result '((a 0) (t 0) ( g 0) (c 0))))
> >     (dolist (base strand result)
> >       (cond ((atom base)(incf (second (assoc base result))))
> > (t (incf (second (assoc (first base) result)))
> > (incf (second (assoc (second base) result))))))))
> 
> You may be interested in an OCaml equivalent:
> 
> # let count_bases =
>     List.fold_left (fun (a, t, g, c) -> function
>       | `A -> a+1, t, g, c
>       | `T -> a, t+1, g, c
>       | `G -> a, t, g+1, c
>       | `C -> a, t, g, c+1) (0, 0, 0, 0);;
> val count_bases : _[< `A | `C | `G | `T ] list -> int * int * int * int =
>   <fun>
> 
> Note the inferred type.

Note also that it's not what the OP wanted. (Hint: it's applicable
only to a list of `As,...,`Ts.)

Andras
From: Jon Harrop
Subject: Re: Lisp Question
Date: 
Message-ID: <46a03eda$0$1622$ed2619ec@ptn-nntp-reader02.plus.net>
Andras Simon wrote:
> Note also that it's not what the OP wanted. (Hint: it's applicable
> only to a list of `As,...,`Ts.)

I see no merit in dynamically typing this. If you want a nested list,
flatten it first.

-- 
Dr Jon D Harrop, Flying Frog Consultancy
OCaml for Scientists
http://www.ffconsultancy.com/products/ocaml_for_scientists/?usenet
From: Andras Simon
Subject: Re: Lisp Question
Date: 
Message-ID: <vcdwswvdvek.fsf@csusza.math.bme.hu>
Jon Harrop <···@ffconsultancy.com> writes:

> Andras Simon wrote:
> > Note also that it's not what the OP wanted. (Hint: it's applicable
> > only to a list of `As,...,`Ts.)
> 
> I see no merit in dynamically typing this. If you want a nested list,
> flatten it first.

But you do see merit in offering an OCaml program as an answer to a
Lisp question, claiming it's equivalent when it's quite clearly not.

Andras
From: Ken Tilton
Subject: Poor Harrop [was Re: Lisp Question]
Date: 
Message-ID: <2S3oi.13$Q81.0@newsfe12.lga>
Andras Simon wrote:
> Jon Harrop <···@ffconsultancy.com> writes:
> 
> 
>>Andras Simon wrote:
>>
>>>Note also that it's not what the OP wanted. (Hint: it's applicable
>>>only to a list of `As,...,`Ts.)
>>
>>I see no merit in dynamically typing this. If you want a nested list,
>>flatten it first.
> 
> 
> But you do see merit in offering an OCaml program as an answer to a
> Lisp question, claiming it's equivalent when it's quite clearly not.

Well, it occurred to me that Lisp Legend Richard Gabriel himself at LUGM 
99 (when the then Erann Gat was leading a sobfest over Lisp's 
unpopularity) suggested "pick a fight" with some more popular language, 
so it is hard to fault Poor Harrop.

Also, as one of the few still clinging to static typing as in any way a 
positive I think he has endangered species status going for him, heavy 
fines if we rough him up too badly.

kzo