What defines *really* knowing Lisp, in your opinion?

0 views
Skip to first unread message

jonathon

unread,
Jul 15, 2005, 12:53:47 AM7/15/05
to

Understanding/frequently using -

closures?
macros?
CLOS?
reader customizations?
most of the CLHS functions?
'almost pure' functional programming?

It seems to me you could develop sophisticated software using just a
couple of these techniques without even scratching the surface of the
others.

Greg Menke

unread,
Jul 15, 2005, 1:20:18 AM7/15/05
to
"jonathon" <j_mck...@bigfoot.com> writes:

Write software. Use it. Fix it. Enhance it. Do it better next the
next time than you did the last time.

What more could you want?

But to answer your question, I'd say knowing Lisp starts when you stop
writing C with it.

Gregm

Robert Strandh

unread,
Jul 15, 2005, 1:39:58 AM7/15/05
to
"jonathon" <j_mck...@bigfoot.com> writes:

Sure, you could develop sophisticated software without using ANY of
these techniques, but why would you want to? All of these techniques
are there to help you write more reliable and maintainable software
faster. Therefore, the more such techniques you know, the better.

"really knowing Lisp" is not a binary thing. Very few people
master all of what CL can offer, and most of us discover new features
on a regular basis.

I am not sure about the motivation for your question. Would you like
for someone to tell you that you can safely ignore some features and
still "really know Lisp"? In my opinion, that is not a good idea.
You might want to take a look at a little essay that I wrote a few
years ago about the psychology of learning:

http://dept-info.labri.fr/~strandh/Essays/psychology.html

--
Robert Strandh

William D Clinger

unread,
Jul 15, 2005, 2:26:18 AM7/15/05
to
I tell my students I don't *really* know any programming
languages. There are a couple of languages I once thought
I understood pretty thoroughly, but both have become so
much more complicated that I no longer understand them.

I also tell my students they can be productive writing
software in languages they don't completely understand.

This is easier in some languages than in others, of
course. C++ is notably difficult for beginners because
so much goes on behind the scenes, and because so much
of that implicit stuff is semantically important.

Will

antoan...@hotmail.com

unread,
Jul 15, 2005, 3:18:07 AM7/15/05
to
>It seems to me you could develop sophisticated software using just a
>couple of these techniques without even scratching the surface of the
>others

Yes you can , many people were doing that or still doing this
especially
in less capable languages (looking from Lisp perspective that is every
other language) . But if a tool could help you why not using it ?
I personally hate OO but when it's the right way i use it.

Pascal Costanza

unread,
Jul 15, 2005, 7:10:50 AM7/15/05
to

You can develop sophisticated software using just assembler. That's not
the point. A programming language is a human-computer interface. It's
important to be able to express a solution to a problem in terms that
people understand.


Pascal

--
2nd European Lisp and Scheme Workshop
July 26 - Glasgow, Scotland - co-located with ECOOP 2005
http://lisp-ecoop05.bknr.net/

jonathon

unread,
Jul 15, 2005, 8:54:04 AM7/15/05
to

Robert Strandh wrote:
> I am not sure about the motivation for your question. Would you like
> for someone to tell you that you can safely ignore some features and
> still "really know Lisp"? In my opinion, that is not a good idea.

My motivation is as I learn the language, I will have ways to measure
my progress and plan my next goal to achieve. Since the language and
the techniques that come with it can be so different from those I know
now, I think this would be helpful.

jonathon

unread,
Jul 15, 2005, 9:01:25 AM7/15/05
to

Greg Menke wrote:

> But to answer your question, I'd say knowing Lisp starts when you stop
> writing C with it.

That's one of the explanations I'm having trouble with. Does this mean
writing more functionally, and using the more complex data structures
(hashes, lists, CLOS) and tools (mapping, sequence manipulation)?

M Jared Finder

unread,
Jul 15, 2005, 11:52:07 AM7/15/05
to

I don't think you can really learn Lisp (or much of anything) in such a
piecemeal fashion. You need to learn just enough about the different
parts of Lisp to know how to use them, and then practice, practice,
practice, practice, practice.

Learn enough about macros to feel that you could write many of the
macros that are already in COMMON-LISP. In particular, DOLIST, DO*, DO,
and LET* are good practice macros.
Learn enough about closures to understand how FLET, LABELS, and LAMBDA
all work.
Learn enough about CLOS to understand how you write OO software in it,
and how generic functions are more powerful than virtual functions.

Then start writing actual software, with an eye toward removing code
duplication. This is the most important step. Lisp's features allow
you to abstract away patterns in simple, direct, yet fast ways that no
other language has.

-- MJF

Greg Menke

unread,
Jul 15, 2005, 12:29:17 PM7/15/05
to

"jonathon" <j_mck...@bigfoot.com> writes:

I'd say writing in Lisp is more associated with using macros and
closures to simplify code. Since C doesn't offer much for those two
cases, its code has a tendency towards highly specified rigidity.

Maybe to put it another way, once your Lisp experience starts making
your C/C++ code better, then you're learning Lisp.

The first signs of starting to grok Lisp might be you suddenly discover
that you're being overly obsessed with types. For instance you can just
let numbers be numbers until you care about presenting them.

Gregm

Christophe Rhodes

unread,
Jul 15, 2005, 12:33:40 PM7/15/05
to
M Jared Finder <ja...@hpalace.com> writes:

> Learn enough about macros to feel that you could write many of the
> macros that are already in COMMON-LISP. In particular, DOLIST, DO*,
> DO, and LET* are good practice macros.

Just in case anyone takes this up: LET*, I believe, cannot be
implemented as a macro absent semantic knowledge of declarations at
macroexpansion time. LET* without declarations is a good practice
macro.

Christophe

Geoffrey Summerhayes

unread,
Jul 15, 2005, 1:07:44 PM7/15/05
to

Mu

--
Geoff


wildwood

unread,
Jul 15, 2005, 5:42:19 PM7/15/05
to
Greg Menke wrote:
>
> I'd say writing in Lisp is more associated with using macros and
> closures to simplify code. Since C doesn't offer much for those two
> cases, its code has a tendency towards highly specified rigidity.
>
> Maybe to put it another way, once your Lisp experience starts making
> your C/C++ code better, then you're learning Lisp.
>
> The first signs of starting to grok Lisp might be you suddenly discover
> that you're being overly obsessed with types. For instance you can just
> let numbers be numbers until you care about presenting them.
>
> Gregm

I'm still a lisp newbie, working on exercises from ACL and PCL, making
an effort to absorb knowledge and ideas from c.l.l.

At work, I'm implementing a SOAP gateway to an Oracle database in java.
It involves an annoying amount of cut-and-paste code, to set up and
close database connections, and to catch the exact same error
conditions for every single table lookup. At one point, I got annoyed,
and thought to myself, "With a 'with-database-connection' macro, this
class would be a tenth of the size."

...and then I realized that maybe I'm starting to grok some of this
lisp stuff after all.


--David

Greg Menke

unread,
Jul 15, 2005, 6:07:34 PM7/15/05
to

"wildwood" <david....@gmail.com> writes:
>
> At work, I'm implementing a SOAP gateway to an Oracle database in java.
> It involves an annoying amount of cut-and-paste code, to set up and
> close database connections, and to catch the exact same error
> conditions for every single table lookup. At one point, I got annoyed,
> and thought to myself, "With a 'with-database-connection' macro, this
> class would be a tenth of the size."

Thats a good beginning.

> ...and then I realized that maybe I'm starting to grok some of this
> lisp stuff after all.

As far as that goes, set up a Postgres server someplace, load your data
into it- skip SOAP & Java and manipulate the tables & queries directly
from Lisp- theres a Postgres interface on cliki last time I checked
which seemed like it would do the trick. Or maybe check out the ODBC
interfaces available in the commerical Lisps.

You'll probably notice a deafening lack of the loud sucking noise that I
imagine you've been getting used to.

Gregm


Joe Marshall

unread,
Jul 15, 2005, 7:51:45 PM7/15/05
to
"jonathon" <j_mck...@bigfoot.com> writes:

``What defines *really* knowing Lisp, in your opinion?''

Waking up with a hangover and finding parenthesis mixed in with your
underwear.


--
~jrm

Peter Scott

unread,
Jul 15, 2005, 8:07:03 PM7/15/05
to

I had weird parenthesis dreams when I was first seriously learning
Lisp, but they went away when I came to better know Lisp.

-Peter

M Jared Finder

unread,
Jul 16, 2005, 1:22:27 AM7/16/05
to

How about this? Use SYMBOL-MACROLET to rename the variables to gensyms:

(defmacro let*- (bindings &body body)
(let ((gensyms (mapcar (lambda (binding)
(gensym (symbol-name (first binding))))
bindings)))
(let*-helper bindings gensyms 0 body)))

(defun let*-helper (bindings gensyms n body)
(if (= n (length bindings))
`(let ,(map 'list (lambda (binding gensym)
(list (first binding) gensym))
bindings gensyms)
,@body)
(let ((value (second (nth n bindings)))
(gensym (nth n gensyms))
(prev-vars (mapcar #'first (subseq bindings 0 n)))
(prev-gensyms (subseq gensyms 0 n)))
`(let ((,gensym (symbol-macrolet ,(map 'list
(lambda (var gensym)
(list var gensym))
prev-vars prev-gensyms)
,value)))
,(let*-helper bindings gensyms (1+ n) body)))))

CL-USER> (macroexpand-1 '(let*- ((a 1)
(b (1+ a)))
(values a b)))
(LET ((#:A4714
(SYMBOL-MACROLET ()
1)))
(LET ((#:B4715
(SYMBOL-MACROLET ((A #:A4714))
(1+ A))))
(LET ((A #:A4714) (B #:B4715))
(VALUES A B))))

CL-USER> (let*- ((a 1)
(b (1+ a)))
(values a b))
1
2

-- MJF

Christophe Rhodes

unread,
Jul 16, 2005, 3:32:21 AM7/16/05
to
M Jared Finder <ja...@hpalace.com> writes:

> Christophe Rhodes wrote:
>> M Jared Finder <ja...@hpalace.com> writes:
>>
>>>Learn enough about macros to feel that you could write many of the
>>>macros that are already in COMMON-LISP. In particular, DOLIST, DO*,
>>>DO, and LET* are good practice macros.
>> Just in case anyone takes this up: LET*, I believe, cannot be
>> implemented as a macro absent semantic knowledge of declarations at
>> macroexpansion time. LET* without declarations is a good practice
>> macro.
>
> How about this? Use SYMBOL-MACROLET to rename the variables to gensyms:

What problem is that meant to solve? Now I'm confused :-)

For the declaration-free let*, why doesn't

(defmacro let% (bindings &body body)
(if (null bindings)
`(locally ,@body)
`(let (,(car bindings))
(let% (,@(cdr bindings)) ,@body))))

work?

(The difficult bit with declarations is to get something like

(flet ((foo () (declare (special x)) (1+ x)))
(let* ((x 1)
(y (foo)))
(declare (special x))))

right)

Christophe

Peter Seibel

unread,
Jul 16, 2005, 10:26:56 AM7/16/05
to
Christophe Rhodes <cs...@cam.ac.uk> writes:

>>> Just in case anyone takes this up: LET*, I believe, cannot be
>>> implemented as a macro absent semantic knowledge of declarations
>>> at macroexpansion time. LET* without declarations is a good
>>> practice macro.
>>
>

> (The difficult bit with declarations is to get something like
>
> (flet ((foo () (declare (special x)) (1+ x)))
> (let* ((x 1)
> (y (foo)))
> (declare (special x))))
>
> right)

So maybe this is what you mean by "semantic knowledge of declarations"
or maybe I'm still missing something but this handles your test case
anyway:

(defmacro let% ((&rest bindings) &body body)


(if (null bindings)
`(locally ,@body)

(destructuring-bind ((variable init-form) &rest remaining-bindings)
(normalize-bindings bindings)
(multiple-value-bind (declarations body)
(parse-declarations body)
(multiple-value-bind (applicable-declarations not-applicable-declarations)
(applicable-declarations variable declarations)
`(let ((,variable ,init-form))
,@applicable-declarations
(let% ,remaining-bindings
,@(append not-applicable-declarations body))))))))

(defun normalize-bindings (bindings)
(mapcar #'(lambda (b) (if (consp b) b (list b nil))) bindings))

(defun parse-declarations (body)
(let ((real-body (member 'declare body :key #'car :test-not #'eql)))
(let ((declarations (ldiff body real-body)))
(values (expand-declarations declarations) real-body))))

(defun expand-declarations (declarations)
(loop for decl in declarations nconcing (expand-1-declaration decl)))

(defun expand-1-declaration (declaration)
(if (eql (caadr declaration) 'type)
(loop with type = (cadadr declaration)
for var in (cddadr declaration) collect `(declaration (,type ,var)))
(loop with d = (caadr declaration)
for var in (cdadr declaration) collect `(declare (,d ,var)))))

(defun applicable-declarations (variable declarations)
(loop for d in declarations
when (eql (cadadr d) variable) collect d into applicable
else collect d into not-applicable
finally (return (values applicable not-applicable))))


-Peter

--
Peter Seibel * pe...@gigamonkeys.com
Gigamonkeys Consulting * http://www.gigamonkeys.com/
Practical Common Lisp * http://www.gigamonkeys.com/book/

M Jared Finder

unread,
Jul 16, 2005, 10:21:30 AM7/16/05
to
Christophe Rhodes wrote:
> M Jared Finder <ja...@hpalace.com> writes:
>
>
>>Christophe Rhodes wrote:
>>
>>>M Jared Finder <ja...@hpalace.com> writes:
>>>
>>>
>>>>Learn enough about macros to feel that you could write many of the
>>>>macros that are already in COMMON-LISP. In particular, DOLIST, DO*,
>>>>DO, and LET* are good practice macros.
>>>
>>>Just in case anyone takes this up: LET*, I believe, cannot be
>>>implemented as a macro absent semantic knowledge of declarations at
>>>macroexpansion time. LET* without declarations is a good practice
>>>macro.
>>
>>How about this? Use SYMBOL-MACROLET to rename the variables to gensyms:
>
> What problem is that meant to solve? Now I'm confused :-)

I was trying to support declarations by delaying the binding of the
variables until the last block. Doesn't that solve the problem with
let* and declarations?

-- MJF

Reply all
Reply to author
Forward
0 new messages