From: Tim Bradshaw
Subject: Spontaneous bad habits
Date: 
Message-ID: <ey3aewcs1i9.fsf@lostwithiel.tfeb.org>
I've long assumed that a lot of the bad habits one sees in academic
(particularly) Lisp (particularly) programs were due to poor and very
out of date teaching.  While this is certainly a characteristic of at
least some academic courses that teach Lisp, I've just had some direct
evidence that actually people will develop such habits all on their
own, even when taught by people (not me) who are very consciously
trying to instill good habits.

The particular example was some code that needed to end up calling
FORMAT with some unknown number of arguments.  The obvious technique
is something like:

	(defun format-args (string &rest args)
	  (apply #'format t string args))

But some people (possibly only one among a class of 30 or so, but it
spread) quite spontaneously came up with:

	(defun format-args (string &rest args)
	  (eval `(format t ,string ,@args)))

I have no reason to think that these people got it from preexisting
examples (but they might have).

I'm not sure what this says about Lisp, or people's minds.  Possibly
EVAL is more harmful than you'd think -- not because it's `bad' as
such but because it leads people horribly astray.

I'd be interested in knowing if anyone else has seen this kind of
thing happening.

--tim

From: Reini Urban
Subject: Re: Spontaneous bad habits
Date: 
Message-ID: <37136a7d.28369423@judy>
Maybe they worked with AutoCAD before?

I even saw AutoLISP programmer write
  (setq s "test")
  ...
  (eval s)

some perl people also got used to their eval, they have no apply.
eval is often used as unwind-protect and there's no performance loss or
memory waste in perl.

eval is also much simplier to understand than apply. (my experience with
newbies)

Tim Bradshaw <···@tfeb.org> wrote:
...
>But some people (possibly only one among a class of 30 or so, but it
>spread) quite spontaneously came up with:
>
>	(defun format-args (string &rest args)
>	  (eval `(format t ,string ,@args)))
...
>I'd be interested in knowing if anyone else has seen this kind of
>thing happening.

---
Reini Urban
http://xarch.tu-graz.ac.at/autocad/news/faq/autolisp.html
From: Reini Urban
Subject: Re: Spontaneous bad habits
Date: 
Message-ID: <3715be66.3415691@judy>
······@sbox.tu-graz.ac.at (Reini Urban) wrote:
>eval is also much simplier to understand than apply. (my experience with
>newbies)

this is my ordered list (teaching experiences) of the most difficult to
understand simple lisp functions. worst first:

1) LAMBDA
2) APPLY
3) every function taking functional arguments, such as SORT 
   or REMOVE-IF, see 1)
4) EVAL
5) MAPCAR
6) FUNCTION

leaving DEFMACRO and BACKQUOTE aside. 
The by far most abused function is SETQ, not EVAL. (In AutoLISP)
---
Reini Urban
http://xarch.tu-graz.ac.at/autocad/news/faq/autolisp.html
From: Barry Margolin
Subject: Re: Spontaneous bad habits
Date: 
Message-ID: <5doR2.12$oQ5.585@burlma1-snr2>
In article <················@judy>,
Reini Urban <······@sbox.tu-graz.ac.at> wrote:
>······@sbox.tu-graz.ac.at (Reini Urban) wrote:
>>eval is also much simplier to understand than apply. (my experience with
>>newbies)
>
>this is my ordered list (teaching experiences) of the most difficult to
>understand simple lisp functions. worst first:
>
>1) LAMBDA
>2) APPLY
>3) every function taking functional arguments, such as SORT 
>   or REMOVE-IF, see 1)
>4) EVAL
>5) MAPCAR
>6) FUNCTION
>
>leaving DEFMACRO and BACKQUOTE aside. 
>The by far most abused function is SETQ, not EVAL. (In AutoLISP)

While the underlying behavior of the evaluator is relatively complex, the
fact that EVAL is a function that provides an interface to it is a pretty
simple thing to understand.

I'm not sure what you mean by SETQ being most abused.  Do you mean that
programmers use SETQ on global variables rather than binding local
variables with LET?  I agree, that's a common mistake among novice
programmers; you see it frequently when Emacs users post their first
attempt at an extension of some kind.

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Reini Urban
Subject: Re: Spontaneous bad habits
Date: 
Message-ID: <37179421.40746350@judy>
Barry Margolin <······@bbnplanet.com> wrote:
>Reini Urban <······@sbox.tu-graz.ac.at> wrote:
>>The by far most abused function is SETQ, not EVAL. (In AutoLISP)

>I'm not sure what you mean by SETQ being most abused.  Do you mean that
>programmers use SETQ on global variables rather than binding local
>variables with LET?  I agree, that's a common mistake among novice
>programmers; you see it frequently when Emacs users post their first
>attempt at an extension of some kind.

Autolisp code is even worse.
We don't have LET.
Nobody uses the ugly LAMBDA construct, because it is reverse: code
before data, or in other words: the function before its parameters.

(let ((a 1) (b 2)) (func a b))		; something like this,
					; i'm not used to let 
<=> (lambda (a b)(func a b)) 1 2)	; brrh!


What I meant with overabuse of SETQ are typical beginner anti-patterns
like:
1) "spaghetti code",
the lack of nesting functions (thinking "iterative" instead of
"functional"),
no "abstraction" at all. 
the pattern people know (here subst and cdr assoc) will be used all the
time. "copy paste".

some very typical autolisp code:
an entity list: '((0 . "TYPE")(8 . "LAYER")(10 . pt)...)

;; change the name, layer and point of an entity
   (setq name (cdr (assoc 0 (entget ele))))	; totally useless...
   (setq lay  (cdr (assoc 8 (entget ele))))
   (setq pt   (cdr (assoc 10 (entget ele))))
   (setq newname (cons 0 "LINE")
   (setq newlay  (cons 8 "1")
   (setq newpt   (cons 10 '(0 0 0))
   (setq new  (subst (cons 0 newname) 
		     (assoc 0 (entget ele)) (entget ele)))
   (setq new  (subst (cons 8 newlay)  
		     (assoc 8 (entget ele)) (entget ele)))
   (setq new  (subst (cons 10 newpt)   
		     (assoc 10 (entget ele)) (entget ele)))
   (entmod new)
or similar.

Function nesting would eliminate some SETQ's because the return values
are passed to the next function:

   (setq elist (entget ele))
   (setq new (subst '(0 . "LINE") (assoc 0 elist) 
               (subst '(8 . "1") (assoc 8 elist) 
                 (subst '(10 . 0 0 0) (assoc 10 elist) 
                   elist))))

or some abstraction:
;; getters:
(defun getname (x e) (cdr (assoc 0 e)))
(defun getlay  (x e) (cdr (assoc 8 e)))
(defun getpt   (x e) (cdr (assoc 10 e)))
and below a setter function.


;; change an entity by its numbers (the accessors) and new values
(defun entchg (elist nr value &aux new old)  ; &aux is Autolisp style
  (if (atom nr) (setq nr (list nr) value (list value)))
  (setq new (mapcar #'cons nr value)
        old (mapcar #'(lambda (n)
              (cons n (cdr (assoc n elist))))) nr))
  (mapcar #'(lambda (n o)
    (setq elist (if (cdr o) 
		  (subst n o elist)
		  (append elist (list n)))))
    new old)
  (entmod elist))

(entchg (entget ele) '(0 8 10) '("name" "1" (0 0 0)))

Admitted, mapcar is not easy to understand here, but you have to write
this function only once, and use it then in one line of code.
5 of 10000 AutoLISP programmers would understand this function.
There are ~40000 at all so ~20 will get it :)

I forgot APPEND as hard to understand function in my previous list.
APPEND would be my number 7
The APPLY #'APPEND pattern is between 1 and 2. (leaving out nil)

2) The waste of global symbols.
   AutoLISP is dynamic, everything is put onto the global obarray.
   Even local parameters. Parameter lookup is costly because functions
   are not preanalysed. (well with the latest release this is done)

---
Reini Urban
http://xarch.tu-graz.ac.at/autocad/news/faq/autolisp.html
From: Johan Kullstam
Subject: Re: Spontaneous bad habits
Date: 
Message-ID: <ur9pl93pd.fsf@res.raytheon.com>
······@sbox.tu-graz.ac.at (Reini Urban) writes:

> ······@sbox.tu-graz.ac.at (Reini Urban) wrote:
> >eval is also much simplier to understand than apply. (my experience with
> >newbies)
> 
> this is my ordered list (teaching experiences) of the most difficult to
> understand simple lisp functions. worst first:
> 
> 1) LAMBDA
> 2) APPLY
> 3) every function taking functional arguments, such as SORT 
>    or REMOVE-IF, see 1)
> 4) EVAL
> 5) MAPCAR
> 6) FUNCTION
> 
> leaving DEFMACRO and BACKQUOTE aside. 
> The by far most abused function is SETQ, not EVAL. (In AutoLISP)

since i am just learning lisp, i feel i am somewhat of an expert at
being a newbie. ;-)  here's my take:

lambda was easy for me.  this might come from extensive math
experience.  stuff like functional analysis treats functions and
really cares less for any values at particular points.  also, passing
functions makes more sense in a number crunching context.  for
example, i posed myself a problem of developing a romberg-integration
routine (an *excellent* exercise for learning a lot about lisp if i do
say so myself) and passing a function to integrate made so much
sense.

having a way to say
(lambda (x) (* x x))
and have it *be* the *function* x-squared is just so incredibly
useful. perhaps it's something to do with many people being unfamiliar
with functions as being objects in their own right.

>> (romberg-integrate #'(lambda (x) (* x x)) 0 1)
1/3

>> (romberg-integrate #'(lambda (x) (* x x x)) 0 1)
1/4

look how easy and how powerful!  doing the type of same thing in
fortran would be fairly painful.

iirc lisp got its start in the math community for these types of
reasons.  perhaps its time to lay off the AI slant and reach for some
succinct numerical algorithm examples for use in teaching lisp?

mapcar wasn't hard since i am familiar with vector operations in
matlab.  i think mapcar is one of the more clever and useful things in
lisp.

i still do not know how to use eval.  as far as i can tell, you use
eval when macro fails.  perhaps eval should be banned until people
are familiar with defmacro?

one of the harder things, which i still do not fully understand, is
the whole eq vs eql vs equal business.  maybe one day it'll make more
sense.

-- 
johan kullstam
From: Dave Pearson
Subject: Re: Spontaneous bad habits
Date: 
Message-ID: <slrn7he1p4.av.davep.news@hagbard.demon.co.uk>
On 15 Apr 1999 13:46:38 -0400, Johan Kullstam <········@ne.mediaone.net> wrote:

> since i am just learning lisp, i feel i am somewhat of an expert at being
> a newbie. ;-) here's my take:

As someone else who is slowly dabbling with lisp I think I'm there with you.

> lambda was easy for me. this might come from extensive math experience.

Oddly enough lambda was dead easy for me too. However, this comes from the
fact that in "real life" I've done lots of coding in Clipper (Xbase derived
language) which, around 1991, introduced a thing called "code blocks" which
are similar (in a loose sense).

So, when I started to play with lisp (year or so back) I found myself
thinking "ooo, look, lisp has code blocks, just like Clipper". Don't worry,
a few moments later I corrected that statement.

As for `eval', well, the amusing thing is that Clipper's "version" of
`funcall' is `eval':

  ;; lisp
  (funcall (lambda () (format t "Hello, World~%")))

  // Clipper
  eval( {|| outstd( "Hello, World" + CRLF ) } )

Ok, waffle off...

-- 
Take a look in Hagbard's World: |   w3ng - The WWW Norton Guide reader.
http://www.acemake.com/hagbard/ |     eg - Norton Guide reader for Linux.
http://www.hagbard.demon.co.uk/ |    weg - Norton Guide reader for Windows.
Free software, including........| dgscan - DGROUP scanner for Clipper.
From: Greg
Subject: Re: Spontaneous bad habits
Date: 
Message-ID: <m3vhewobie.fsf@erols.com>
Ahh, I do miss code blocks and really nice arrays.  Maybe I'm a
weenie, but I haven't run across any language which offered those
things the way Clipper did.

Gregm



> On 15 Apr 1999 13:46:38 -0400, Johan Kullstam <········@ne.mediaone.net> wrote:
> 
> > since i am just learning lisp, i feel i am somewhat of an expert at being
> > a newbie. ;-) here's my take:
> 
> As someone else who is slowly dabbling with lisp I think I'm there with you.
> 
> > lambda was easy for me. this might come from extensive math experience.
> 
> Oddly enough lambda was dead easy for me too. However, this comes from the
> fact that in "real life" I've done lots of coding in Clipper (Xbase derived
> language) which, around 1991, introduced a thing called "code blocks" which
> are similar (in a loose sense).
> 
> So, when I started to play with lisp (year or so back) I found myself
> thinking "ooo, look, lisp has code blocks, just like Clipper". Don't worry,
> a few moments later I corrected that statement.
> 
> As for `eval', well, the amusing thing is that Clipper's "version" of
> `funcall' is `eval':
> 
>   ;; lisp
>   (funcall (lambda () (format t "Hello, World~%")))
> 
>   // Clipper
>   eval( {|| outstd( "Hello, World" + CRLF ) } )
> 
> Ok, waffle off...
> 
> -- 
> Take a look in Hagbard's World: |   w3ng - The WWW Norton Guide reader.
> http://www.acemake.com/hagbard/ |     eg - Norton Guide reader for Linux.
> http://www.hagbard.demon.co.uk/ |    weg - Norton Guide reader for Windows.
> Free software, including........| dgscan - DGROUP scanner for Clipper.
From: Dave Pearson
Subject: Re: Spontaneous bad habits
Date: 
Message-ID: <slrn7hg9p1.av.davep.news@hagbard.demon.co.uk>
On 16 Apr 1999 11:01:13 -0400, Greg <······@erols.com> wrote:

> Ahh, I do miss code blocks and really nice arrays. Maybe I'm a weenie, but
> I haven't run across any language which offered those things the way
> Clipper did.

lisp? Seriously, as a long-time Clipper programmer this is the reason I got
bitten by the lisp bug after a very short "play", I could see where some of
Clipper's "good ideas" really came from.

-- 
Take a look in Hagbard's World: |   w3ng - The WWW Norton Guide reader.
http://www.acemake.com/hagbard/ |     eg - Norton Guide reader for Linux.
http://www.hagbard.demon.co.uk/ |    weg - Norton Guide reader for Windows.
Free software, including........| dgscan - DGROUP scanner for Clipper.
From: Reini Urban
Subject: Re: Spontaneous bad habits
Date: 
Message-ID: <3717a93b.46148017@judy>
leaving the bad habits, coming to bad learning experiences...

Johan Kullstam <········@ne.mediaone.net> wrote:
>one of the harder things, which i still do not fully understand, is
>the whole eq vs eql vs equal business.  maybe one day it'll make more
>sense.

hmm, for myself coming from the c front the whole equality tree 
(eq, eql, equal, equalp, tree-equal, set-equal-p) is rather easy to
understand in terms of simple linked lists. (or other data objects
lateron: structs, hashes)

pointers -> plain data -> recurse into subtrees (with data) -> equal
shapes (recurse into subtrees without data comparison) -> unordered sets
(only data, ignore order) ...

but as lisper the whole type tree is quite hard to overlook because it
is soo huge compared to other languages (leaving C++ aside). 
it is easy to understand but just too big. same as with C++ and the STL
templates. i'm just feeling uncomfortable with it.
maybe it needs just fancy graphics, a nice tree as in the java or vb
books. but lisp books tend to be badly layouted. 

pitman draws nice trees. maybe he should write a lisp book instead of a
science fiction novel... (seriously!)
From: Kent M Pitman
Subject: Re: Spontaneous bad habits
Date: 
Message-ID: <sfwiuawryit.fsf@world.std.com>
······@sbox.tu-graz.ac.at (Reini Urban) writes:

> leaving the bad habits, coming to bad learning experiences...
> 
> Johan Kullstam <········@ne.mediaone.net> wrote:
> >one of the harder things, which i still do not fully understand, is
> >the whole eq vs eql vs equal business.  maybe one day it'll make more
> >sense.
> 
> hmm, for myself coming from the c front the whole equality tree 
> (eq, eql, equal, equalp, tree-equal, set-equal-p) is rather easy to
> understand in terms of simple linked lists. (or other data objects
> lateron: structs, hashes)

The thing to do is to decide never to consider EQ in trying to understand
it.  This will explain EQL and EQUAL and all others.  But to understand EQ
you must know things about the implementation you were never intended to know.
EQL should have been called EQ and what is now EQ never should have been part 
of Common Lisp becuase its effects are too unportable.  It's one of those
historical details like FIXNUM that are there more out of fear than need.
So if you want to have a discussion about EQ, make sure you separate it from
the others because it is largely indefensible together as part of this
other argument.

> pointers -> plain data -> recurse into subtrees (with data) -> equal
> shapes (recurse into subtrees without data comparison) -> unordered sets
> (only data, ignore order) ...

The point is that equality is about "equivalency for purpose".
You need as many equality predicates as you have data purposes.
You are my "equal" as a teacher if you can teach what I can teach
and vice versa.
You are my "equal" as a cook if you can cook what I can cook 
and vice versa.
But the same person can be equal for one purpose and not equal for
another.  
Some forms of equality imply others, and some don't.
Being equal as citizens means we can both vote.
Being equal as native born citizens of the US who are over 35 etc.
means we can both run for president, and IMPLIES equality
of other kinds--like citizenship, but doesn't imply that we are
both equal typists or runners or poets.

The other funny thing about EQUAL and EQUALP is that they are vague
and so figuring out how to feel about them is likewise vague.
They are, in effect, overloaded functions--not generic.  Their meaning
is the union of a number of arguably-unrelated meanings, and they
break easily under heavy stress.  It is better to use custom predicates
designed more specifically for the purpose.

EQUAL and EQUALP work for statistical reasons you don't want to think too
hard about pretty much like it works to say that one person can substitute
for another in virtually any human endeavor.  In general, people are very
different but human activities are such that there are a number of 
activities for which "any old person will do" and EQUAL and EQUALP are
both vague-ish primitives which aren't very principled even though they are
well-defined in some sense.  EQUAL is an approximate test for 
"prints the same" and EQUALP is an approximate test for "contains like
stuff".  When used in heavily recursive data, that's not much comfort, and
that's why most industrial-strength programs do not use them.  But they're
helpful in prototyping and in learning the language because they give
you something to play with.

> but as lisper the whole type tree is quite hard to overlook because it
> is soo huge compared to other languages (leaving C++ aside). 
> it is easy to understand but just too big. same as with C++ and the STL
> templates. i'm just feeling uncomfortable with it.

You're approaching it in the way you're not intended to.
It's not INTENDED that you know about it.  You're supposed to go look
at the chapter names and know that there are facilities for files,
numbers, strings, etc. but unless you need them you are supposed to
not look deeper.  No program requires you to know the lisp type tree.
Gads, I probably couldn't draw it for you without a lot of thought.
I don't keep it in my head because in practice it doesn't matter.

Lisp is about having an organization of things where it's ok to run
into something you don't understand.  In some language that is strongly
typed, you have to worry that you can't even connect your program to
someone else's because the connection part doesn't work unless all
the type connections match.  In Lisp, if you connect to something that passes
data you don't undersstand, you can detect that later.  The connection
can go through right away.  To write:

 (defun foo (x)
   (bar x))

you don't have to know what x is.  If you're going to do something that
is integerish to it, you might want to write

 (defun foo (x)
   (check-type x integer)
   (bar x))

or you might assume bar will do the check.  Other languages make you
learn the type tree because you need to be able to declare the type of
x in advance just in case someone wants to use your function in a more
general way than you intended.  Lisp's bigness is not supposed to matter.
The world is a big place, and potentially you should assume there is a lisp
datatype there for eery object in the whole world.  You don't reason about
the world by first learning its type tree.  You learn that the world HAS
a type tree and you learn how to ask what something is, and then you get on
with things from that point.  In Lisp you can ask "is this an X or not"
without having to enumerate all the things that are not X.  That is
critically important to understanding the world.

You can never discover anything about the world unless you can be surprised.
You can never be surprised unless you have no foreknowledge.
You cannot be absent foreknowledge if you must predeclare or "preknow"
everything.
Other languages are about getting you to know everything before you can
write down anything.  Lisp is about getting you to write down what you
know and then work with the machine in thinking about what you might learn
from there.

> maybe it needs just fancy graphics, a nice tree as in the java or vb
> books. but lisp books tend to be badly layouted. 

uh, maybe.
 
> pitman draws nice trees. maybe he should write a lisp book instead of a
> science fiction novel... (seriously!)

i'm working on the lisp books too. (various, not just one.)  it's one
reason that the scifi novel writing is going so slowly.

let me know if any of the above is helpful to figuring out how to proceed
with using lisp to its best ability so i'll know whether to bother trying
to pretty it up for the book.
From: Vassil Nikolov
Subject: Re: Spontaneous bad habits
Date: 
Message-ID: <7faat9$74m$1@nnrp1.dejanews.com>
In article <···············@world.std.com>,
  Kent M Pitman <······@world.std.com> wrote:

(...)

(...)  ;on EQUAL and EQUALP

I think that one important issue here is whether the programmer
knows, at program writing time, the type of the arguments passed
to EQUAL[P].  If that is known, things are somewhat easier
than if it isn't.  (By `known' I mean `known all the way down'
in the case of composite objects; it sometimes happens.)

Personally, I have found EQUAL handy for comparing bit vectors.
(And I am of course guilty of using it to compare lists, but
usually ones that contain conses, symbols, and numbers only.)

(...)  ;on Lisp's type/class hierarchy

I think this is worth putting in a book.  (In response to the
question if that was useful.)

_________________________________________
Equalp treatment for equality predicates!

--
Vassil Nikolov <········@poboxes.com> www.poboxes.com/vnikolov
(You may want to cc your posting to me if I _have_ to see it.)
   LEGEMANVALEMFVTVTVM  (Ancient Roman programmers' adage.)

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    
From: Valeriy E. Ushakov
Subject: Re: Spontaneous bad habits
Date: 
Message-ID: <7f0lri$s10$1@news.ptc.spbu.ru>
Tim Bradshaw <···@tfeb.org> wrote:

> 	(defun format-args (string &rest args)
> 	  (eval `(format t ,string ,@args)))

> I have no reason to think that these people got it from preexisting
> examples (but they might have).

May be just too much sh/tcl/... programming and its "everything is a
string" attitude and corresponding habits applied to Lisp?

SY, Uwe
-- 
···@ptc.spbu.ru                         |       Zu Grunde kommen
http://www.ptc.spbu.ru/~uwe/            |       Ist zu Grunde gehen
From: Robert Swindells
Subject: Re: Spontaneous bad habits
Date: 
Message-ID: <klnfuvr5h.fsf@stimpy.rjs.net>
Valeriy E. Ushakov <···@ptc.spbu.ru> wrote:
>Tim Bradshaw <···@tfeb.org> wrote:

>> 	(defun format-args (string &rest args)
>> 	  (eval `(format t ,string ,@args)))

>> I have no reason to think that these people got it from preexisting
>> examples (but they might have).

>May be just too much sh/tcl/... programming and its "everything is a
>string" attitude and corresponding habits applied to Lisp?

I think I can beat that.

How about:

(setq param-info (read-from-string
	(format () "(:LAMP-SPECIFIER (((:SELECTOR (T))
			(:SELECTED-VALUE \"~A\"))))" name)))
 
Who needs backquote :-)

This was copied from real code.

Robert
From: Andre Koehorst
Subject: Re: Spontaneous bad habits
Date: 
Message-ID: <37159ACA.155BF49B@educ.unimaas.nl>
Tim Bradshaw schreef:

> But some people (possibly only one among a class of 30 or so, but it
> spread) quite spontaneously came up with:
>
>         (defun format-args (string &rest args)
>           (eval `(format t ,string ,@args)))
>
> I have no reason to think that these people got it from preexisting
> examples (but they might have).

Novices tend to solve a problem by assembling a solution with the
constucts they know (or can find in reference manuals). I think that this
student was more comfortable with the construct "eval" than with the
construct "apply". I'd guess 1) that somewhere previously in the course
"eval" has been tackled, and 2) this student mastered "eval" in such a way
that its use could be transferred to this new problem. I'd say pretty good
problem solving.
Also a nice teaching/learning opportunity about 'the good habit of not
using eval'.

(format-args "Andre")
From: Barry Margolin
Subject: Re: Spontaneous bad habits
Date: 
Message-ID: <6ioR2.13$oQ5.585@burlma1-snr2>
In article <·················@educ.unimaas.nl>,
Andre Koehorst  <········@educ.unimaas.nl> wrote:
>
>
>Tim Bradshaw schreef:
>
>> But some people (possibly only one among a class of 30 or so, but it
>> spread) quite spontaneously came up with:
>>
>>         (defun format-args (string &rest args)
>>           (eval `(format t ,string ,@args)))
>>
>> I have no reason to think that these people got it from preexisting
>> examples (but they might have).
>
>Novices tend to solve a problem by assembling a solution with the
>constucts they know (or can find in reference manuals). I think that this
>student was more comfortable with the construct "eval" than with the
>construct "apply". I'd guess 1) that somewhere previously in the course
>"eval" has been tackled, and 2) this student mastered "eval" in such a way
>that its use could be transferred to this new problem. I'd say pretty good
>problem solving.

I gave a similar answer in a comp.unix.* newsgroup a couple of days ago, in
explaining why people often write:

grep ... | awk ...

even though awk has a built-in regular expression matcher.  Someone who
learned about grep for its field selection capability may never have had a
reason to learn that it also has a regexp matcher, but they know that grep
does this.  They use the tools they know in the ways they're familiar.

The thing I find familiar about the student's code is that someone who is
not yet comfortable with APPLY has learned backquote already.  Backquote
isn't usually introduced until you're learning about macros; they're both
pretty advanced topics within the Lisp curriculum.

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.