From: micromoog
Subject: Style question
Date: 
Message-ID: <1133564017.365104.69030@g44g2000cwa.googlegroups.com>
I'm in the early stages of learning Lisp, and I've just written my
first program that actually does something (trivial though it is).  Is
my style appropriate for all of the things I'm doing here?

I guess what I'm asking: am I on the road to developing any obvious bad
habits here?  I know this code uses side effects for the I/O, but it
seems appropriate.

Also, my materials all refer to just using the read-eval-print loop
(which is great for development).  I was trying to figure out how to
make programs executable from the OS in the normal way, and I ended up
including a function call, followed by (quit), in the source file
itself, then loading the program using the shell script below.  Is this
a normal approach?

Source file game.lisp:
==========
(defun game ()
    (format t "Enter a number: ")
    (let ((num (random 100)))
        (do ((guess (read) (read)) (guesses 1 (+ guesses 1)))
            ((= guess num)
                (format t "Right!~%It took you ~A guesses.~%" guesses))
            (if (> guess num)
                (format t "Too high~%Try again: ")
                (format t "Too low~%Try again: ")
            )
        )
    )
)

(game)

(quit)
==========

Executed via a shell script containing this command:

lisp -quiet -load game.lisp

From: Pedro Kröger
Subject: Re: Style question
Date: 
Message-ID: <1133570205.608598.189150@g47g2000cwa.googlegroups.com>
I recommend you take a look at the chapter "Syntax and Semantics"
[1] of PCL (Practical Common Lisp). It has good advice on style
and indentation. The second chapter is also great [2].

It's good to be able to call the program from the shell just like
you would if using python or ruby, but remember that lisp is
*way* more interactive, so you may want to use emacs+slime to
quickly define functions, and (re)compile just the code you've
changed (as opposed to compile/run the hole thing). You may want
to watch Marco "Spielberg" Baringer slime movie [3] to get a
sense of how this works. _Deeply_ recommended :-)

Pedro Kröger

[1] http://www.gigamonkeys.com/book/syntax-and-semantics.html
[2]
http://www.gigamonkeys.com/book/lather-rinse-repeat-a-tour-of-the-repl.html
[3] http://bc.tech.coop/blog/050728.html
From: micromoog
Subject: Re: Style question
Date: 
Message-ID: <1133579251.656392.41380@g14g2000cwa.googlegroups.com>
Pedro Kröger wrote:
> It's good to be able to call the program from the shell just like
> you would if using python or ruby, but remember that lisp is
> *way* more interactive, so you may want to use emacs+slime to
> quickly define functions, and (re)compile just the code you've
> changed (as opposed to compile/run the hole thing). You may want
> to watch Marco "Spielberg" Baringer slime movie [3] to get a
> sense of how this works. _Deeply_ recommended :-)
>

Yes, I keep getting the feeling . . . strike that, I keep getting told
explicitly by knowledgeable people that I should be using slime.  I've
got it installed, but I still haven't learned emacs yet (I've been a
longtime vi addict).  I'll go watch the movie . . . maybe it'll give me
the needed inspiration to go ahead and learn emacs :)

My lisp workflow thus far has been editing code in one window, then
copy/pasting expressions into the default cmucl shell for evaluation.
Kludgy, yes.  Must learn slime.
From: ·············@gmail.com
Subject: Re: Style question
Date: 
Message-ID: <1133582754.623174.70440@z14g2000cwz.googlegroups.com>
micromoog wrote:
> Yes, I keep getting the feeling . . . strike that, I keep getting told
> explicitly by knowledgeable people that I should be using slime.  I've
> got it installed, but I still haven't learned emacs yet (I've been a
> longtime vi addict).  I'll go watch the movie . . . maybe it'll give me
> the needed inspiration to go ahead and learn emacs :)
>

Learning emacs sucks, but it's a necessary evil - I was there recently,
and the sooner you get it over with, the better.  Work through a
tutorial (the built in one is weak, if you can find an old $3 copy of
the Oreilly book it's better).  Use 'alt-x apropos' or tab completion
frequently until you remember commands.  In other words, if you know
theres a command you need that starts with 'slime-', but cant remember
the full name, hit alt-x, type slime, then bang on the tab completion
until you get a list of possible commands.   Realize that emacs default
keybindings are stupid, and it's easy to change them in your .emacs
until they make sense.
From: Ulrich Hobelmann
Subject: Re: Style question
Date: 
Message-ID: <3vdfgkF152ot2U1@individual.net>
·············@gmail.com wrote:
> Learning emacs sucks, but it's a necessary evil - I was there recently,
> and the sooner you get it over with, the better.  Work through a
> tutorial (the built in one is weak, if you can find an old $3 copy of
> the Oreilly book it's better).  Use 'alt-x apropos' or tab completion
> frequently until you remember commands.  In other words, if you know
> theres a command you need that starts with 'slime-', but cant remember
> the full name, hit alt-x, type slime, then bang on the tab completion
> until you get a list of possible commands.   Realize that emacs default
> keybindings are stupid, and it's easy to change them in your .emacs
> until they make sense.

Maybe the worst thing about Emacs is that it works differently on all 
platforms (because of different keyboard conventions).  My Aquamacs (for 
the Mac) doesn't work with Alt (on the Mac Alt is like shift, allowing 
me to type accents, Umlauts, � and other stuff on a limited keyboard), 
so I have to type ESC-x for instance to execute commands.  A Sun I 
sometimes have to sit at seems to have no working Alt either (it just 
beeps frantically), and the caps-lock key is labelled control and seems 
to work (as control), the control key (labelled caps-lock on the Sun) 
seems to be an escape, and the esc-key seems to work as caps lock.

Anyway, because of the esc-madness Emacs still works better for editing 
than vi, even if it's an old Emacs 20.

-- 
Majority, n.: That quality that distinguishes a crime from a law.
From: Peter Seibel
Subject: Re: Style question
Date: 
Message-ID: <m2mzjigpui.fsf@gigamonkeys.com>
Ulrich Hobelmann <···········@web.de> writes:

> Maybe the worst thing about Emacs is that it works differently on all
> platforms (because of different keyboard conventions).  My Aquamacs
> (for the Mac) doesn't work with Alt (on the Mac Alt is like shift,
> allowing me to type accents, Umlauts, � and other stuff on a limited
> keyboard), so I have to type ESC-x for instance to execute commands.

Hmmm, if you are going to use Emacs on multiple platforms and you want
it to be the same on each, why not just use the vanilla Emacs instead
of one that is trying to conform to the native key conventions? I use
Emacs on three or four different OS's and the great thing about it is
that the key commands are always the *same*.

(Note for OS X users: the CVS Emacs sources build fine on OS X--it's a
real pity that it's been, I think, literally years since there's been
an official release of Emacs, especially since the released version
*doesn't* work out of the box on OS X. But the CVS version is
currently quite stable as they are ostensibly trying to get out a new
release.)

-Peter

-- 
Peter Seibel           * ·····@gigamonkeys.com
Gigamonkeys Consulting * http://www.gigamonkeys.com/
Practical Common Lisp  * http://www.gigamonkeys.com/book/
From: Ulrich Hobelmann
Subject: Re: Style question
Date: 
Message-ID: <3ve0rmF15dp5tU2@individual.net>
Peter Seibel wrote:
> Ulrich Hobelmann <···········@web.de> writes:
> 
>> Maybe the worst thing about Emacs is that it works differently on all
>> platforms (because of different keyboard conventions).  My Aquamacs
>> (for the Mac) doesn't work with Alt (on the Mac Alt is like shift,
>> allowing me to type accents, Umlauts, � and other stuff on a limited
>> keyboard), so I have to type ESC-x for instance to execute commands.
> 
> Hmmm, if you are going to use Emacs on multiple platforms and you want
> it to be the same on each, why not just use the vanilla Emacs instead
> of one that is trying to conform to the native key conventions? I use
> Emacs on three or four different OS's and the great thing about it is
> that the key commands are always the *same*.

Well, I don't really use it that much on other platforms, and on the Mac 
I'm already quite used to the Mac conventions, that's why I got 
Aquamacs.  Maybe I'll change that.

-- 
Majority, n.: That quality that distinguishes a crime from a law.
From: Pascal Costanza
Subject: Re: Style question
Date: 
Message-ID: <3vdojfF15foo1U1@individual.net>
Ulrich Hobelmann wrote:

> My Aquamacs (for the Mac) doesn't work with Alt (on the Mac Alt is like shift, allowing 
> me to type accents, Umlauts, � and other stuff on a limited keyboard), 
> so I have to type ESC-x for instance to execute commands.

Adding the following lines to your .emacs should help:

(setq mac-option-modifier 'meta)
(setq mac-pass-option-to-system nil)

The following is also useful:

(global-set-key [C-M-backspace] 'backward-kill-sexp)


I think there are more possible tweaks described in the Aquamacs 
documentation.


Pascal

-- 
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/
From: Ulrich Hobelmann
Subject: Re: Style question
Date: 
Message-ID: <3ve0q0F15dp5tU1@individual.net>
Pascal Costanza wrote:
> Ulrich Hobelmann wrote:
> 
>> My Aquamacs (for the Mac) doesn't work with Alt (on the Mac Alt is 
>> like shift, allowing me to type accents, Umlauts, � and other stuff on 
>> a limited keyboard), so I have to type ESC-x for instance to execute 
>> commands.
> 
> Adding the following lines to your .emacs should help:
> 
> (setq mac-option-modifier 'meta)
> (setq mac-pass-option-to-system nil)
> 
> The following is also useful:
> 
> (global-set-key [C-M-backspace] 'backward-kill-sexp)
> 
> 
> I think there are more possible tweaks described in the Aquamacs 
> documentation.

Thanks, I'll try that, or maybe just revert to vanilla CVS Emacs some time.

Thing is, I sometimes have to write non-English, and then I need the 
keys accessible via the Option/Alt key.

Maybe the best would to make Meta the Mac's Command key.

-- 
Majority, n.: That quality that distinguishes a crime from a law.
From: ·············@gmail.com
Subject: Re: Style question
Date: 
Message-ID: <1133658414.376857.106950@g47g2000cwa.googlegroups.com>
>My Aquamacs (for
>the Mac) doesn't work with Alt (on the Mac Alt is like shift, allowing
>me to type accents, Umlauts, ß and other stuff on a limited keyboard),
>so I have to type ESC-x for instance to execute commands.

You can toggle Option = Meta with Apple-; . Or use the variable
mac-function-modifier to map Function to Meta if you have a Function
key. 

More in the Aquamacs Wiki (Help menu / CustomizeAquamacs page)
From: Ulrich Hobelmann
Subject: Re: Style question
Date: 
Message-ID: <3vg0taF16235qU1@individual.net>
·············@gmail.com wrote:
>> My Aquamacs (for
>> the Mac) doesn't work with Alt (on the Mac Alt is like shift, allowing
>> me to type accents, Umlauts, � and other stuff on a limited keyboard),
>> so I have to type ESC-x for instance to execute commands.
> 
> You can toggle Option = Meta with Apple-; .

Sweet, I haven't seen that menu entry before :)

-- 
Majority, n.: That quality that distinguishes a crime from a law.
From: Thomas A. Russ
Subject: Re: Style question
Date: 
Message-ID: <ymi64q3pidi.fsf@sevak.isi.edu>
Ulrich Hobelmann <···········@web.de> writes:

> My Aquamacs (for 
> the Mac) doesn't work with Alt (on the Mac Alt is like shift, allowing 
> me to type accents, Umlauts, � and other stuff on a limited keyboard), 
> so I have to type ESC-x for instance to execute commands.

Hmmm.  I have a different Emacs version for the Mac which works great
with using the alt/option key as the meta key for Emacs.  But I think it
can be configured to use Apple/Command as the meta key instead.  I
thought Apple/Command is what Aquamacs used, but it's been a while so I
could be confusing it with a different Emacs implementation.

Accents are still a bit of a problem, since the Emacs input system
of the standard Emacs doesn't recognize the standard Mac input
conventions.  For example C-Q M-U gives me � instead of being an umlaut
prefix key.  That may be configurable, though.



-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Ulrich Hobelmann
Subject: Re: Style question
Date: 
Message-ID: <3vjcvqF15u8f0U1@individual.net>
Thomas A. Russ wrote:
> Ulrich Hobelmann <···········@web.de> writes:
> 
>> My Aquamacs (for 
>> the Mac) doesn't work with Alt (on the Mac Alt is like shift, allowing 
>> me to type accents, Umlauts, � and other stuff on a limited keyboard), 
>> so I have to type ESC-x for instance to execute commands.
> 
> Hmmm.  I have a different Emacs version for the Mac which works great
> with using the alt/option key as the meta key for Emacs.  But I think it
> can be configured to use Apple/Command as the meta key instead.  I
> thought Apple/Command is what Aquamacs used, but it's been a while so I
> could be confusing it with a different Emacs implementation.

Aquamacs does Mac-style keychords (cmd-s, cmd-o, cmd-q, cmd-c ...) with 
the cmd-key.

But David Reitter informed me of the cmd-; solution that lets me switch 
between alt-as-meta and alt-as-alternative-key-input, so that's just 
perfect :)

> Accents are still a bit of a problem, since the Emacs input system
> of the standard Emacs doesn't recognize the standard Mac input
> conventions.  For example C-Q M-U gives me � instead of being an umlaut
> prefix key.  That may be configurable, though.

With Aquamacs that works perfectly.  You can type as on the Mac, and 
when you use cmd-; it switches Alt to Meta.  Another cmd-; switches Alt 
back to the input mode.

I don't know the C-Q thing; I always use Mac native input (since it 
works in other programs too).

-- 
Majority, n.: That quality that distinguishes a crime from a law.
From: Peter Seibel
Subject: Re: Style question
Date: 
Message-ID: <m2r78vgk5i.fsf@gigamonkeys.com>
"micromoog" <·········@gmail.com> writes:

> I'm in the early stages of learning Lisp, and I've just written my
> first program that actually does something (trivial though it is).  Is
> my style appropriate for all of the things I'm doing here?
>
> I guess what I'm asking: am I on the road to developing any obvious bad
> habits here?  I know this code uses side effects for the I/O, but it
> seems appropriate.
>
> Also, my materials all refer to just using the read-eval-print loop
> (which is great for development).  I was trying to figure out how to
> make programs executable from the OS in the normal way, and I ended up
> including a function call, followed by (quit), in the source file
> itself, then loading the program using the shell script below.  Is this
> a normal approach?

That's a reasonable way. Some combinations of Lisp implementations and
OS will allow you ta actually include a #! line as you would for a
shell, Perl, or Python script. And other Lisp implementations,
particularly the commercial ones, provide other ways to package
programs for delivery to non-Lisp aware users. (The best situation, in
many ways, is on OS X, where *all* applications are really a directory
full of ancilary files. On that platform you can use a small shell
script as the actual entry point but load all sorts of Lisp files
start Lisp from a dumped image or whatever and still have it look like
a "regular" double-clickable app to the user.

> Source file game.lisp:
> ==========
> (defun game ()
>     (format t "Enter a number: ")
>     (let ((num (random 100)))
>         (do ((guess (read) (read)) (guesses 1 (+ guesses 1)))
>             ((= guess num)
>                 (format t "Right!~%It took you ~A guesses.~%" guesses))
>             (if (> guess num)
>                 (format t "Too high~%Try again: ")
>                 (format t "Too low~%Try again: ")
>             )
>         )
>     )
> )

This is pretty much fine except you should not leave those closing
parens dangling on their own lines. Just lump them all together after
the closing paren of the last FORMAT expression.

-Peter

-- 
Peter Seibel           * ·····@gigamonkeys.com
Gigamonkeys Consulting * http://www.gigamonkeys.com/
Practical Common Lisp  * http://www.gigamonkeys.com/book/
From: ···············@yahoo.com
Subject: Re: Style question
Date: 
Message-ID: <1133566388.957934.22190@g43g2000cwa.googlegroups.com>
Also, I'd put (guesses 1 (1+ guesses)) on the next line, aligned with
(guess ...).  Also note the 1+
From: micromoog
Subject: Re: Style question
Date: 
Message-ID: <1133578888.974766.327030@o13g2000cwo.googlegroups.com>
Peter Seibel wrote:
> "micromoog" <·········@gmail.com> writes:
>
> > I'm in the early stages of learning Lisp, and I've just written my
> > first program that actually does something (trivial though it is).  Is
> > my style appropriate for all of the things I'm doing here?
>
[snip example with several lines containing a single closing paren]
>
> This is pretty much fine except you should not leave those closing
> parens dangling on their own lines. Just lump them all together after
> the closing paren of the last FORMAT expression.
>

Thanks for the comments.  Your book is high on my reading list :)

Yes, I'd noticed that people seem to do that.  That makes it more
difficult for me to keep up with how many parens will be needed to
close out all of the levels . . . do people just typically keep hitting
) until the editor lets you know they're all closed?
From: matteo d'addio 81
Subject: Re: Style question
Date: 
Message-ID: <1133603521.238935.98330@g47g2000cwa.googlegroups.com>
micromoog ha scritto:

> Source file game.lisp:
> ==========
> (defun game ()
>     (format t "Enter a number: ")
>     (let ((num (random 100)))
>         (do ((guess (read) (read)) (guesses 1 (+ guesses 1)))
>             ((= guess num)
>                 (format t "Right!~%It took you ~A guesses.~%" guesses))
>             (if (> guess num)
>                 (format t "Too high~%Try again: ")
>                 (format t "Too low~%Try again: ")
>             )
>         )
>     )
> )
>
> > This is pretty much fine except you should not leave those closing
> > parens dangling on their own lines. Just lump them all together after
> > the closing paren of the last FORMAT expression.
> >
>
> Yes, I'd noticed that people seem to do that.  That makes it more
> difficult for me to keep up with how many parens will be needed to
> close out all of the levels . . . do people just typically keep hitting
> ) until the editor lets you know they're all closed?

If your code is correctly indented it can be inferred from
the indentation level. As you can see in your code, four
indentation levels, four parentesis needed.

I do this way with windows notepad and it works fine.

The only issue with notepad is that you can't indent or deindent
several row at a time, so you mast do it manually, and reindenting
a large function can be painful.

regards
matteo
From: drewc
Subject: Re: Style question
Date: 
Message-ID: <X48kf.22228$Gd6.11825@pd7tw3no>
micromoog wrote:
> Peter Seibel wrote:
>>
> [snip example with several lines containing a single closing paren]
> 
>>This is pretty much fine except you should not leave those closing
>>parens dangling on their own lines. Just lump them all together after
>>the closing paren of the last FORMAT expression.
>>
> 
> 
> Thanks for the comments.  Your book is high on my reading list :)
> 
> Yes, I'd noticed that people seem to do that.  That makes it more
> difficult for me to keep up with how many parens will be needed to
> close out all of the levels . . . do people just typically keep hitting
> ) until the editor lets you know they're all closed?


You can do it that way, or you can practice a more 'structured' approach 
(as seen in Marco's SLIME movie) where you always insert both parens. 
This way there is never a worry about closing forms, they are already 
closed.

but, a lot of the time i just end up hitting ) 'till the editor tells me 
it's closed. simple and effective.

drewc



-- 
Drew Crampsie
drewc at tech dot coop
  "... the most advanced use of lisp in the field of bass lure sales"
	-- Xach on #lisp
From: Bill Atkins
Subject: Re: Style question
Date: 
Message-ID: <1133619830.399303.59990@g14g2000cwa.googlegroups.com>
There's an Emacs mode called paredit that automatically takes care of
closing parentheses for you.  When you type a left parenthesis, it will
immediately insert a closing one afterward.  It imposes some structure
on your code, too - for instance, you can't simply delete a closing
parenthesis.  Instead, you'd have to clear out what's inside the list
and then delete the opening parenthesis.

It's a little hard to get used to, but I find I code much faster in
paredit-mode than I do without it and that all of my parentheses stay
balanced without any extra work.  If you're going to try this out you
should get familiar with the sexp commands in Emacs (forward-sexp,
kill-sexp, mark-sexp, up-list, etc.).  Try M-x apropos RET sexp RET and
M-x apropos -list RET.

Here is the link: http://mumble.net/~campbell/emacs/paredit.el

Happy lisping!

Bill Atkins
From: Pedro Kröger
Subject: Re: Style question
Date: 
Message-ID: <1133628705.254401.296660@g47g2000cwa.googlegroups.com>
micromoog wrote:
> do people just typically keep hitting
> ) until the editor lets you know they're all closed?

Yes, that's what I do. or I use slime-close-parens-at-point (C-c C-q)
to instert all needed closing-parens. Remember that the key thing is to
think of *expressions*, not parens. This link may be of help:

http://www.cliki.net/Editing%20Lisp%20Code%20with%20Emacs

Pedro Kröger
From: Steven E. Harris
Subject: Re: Style question
Date: 
Message-ID: <q94ek4ribj5.fsf@chlorine.gnostech.com>
"micromoog" <·········@gmail.com> writes:

> do people just typically keep hitting ) until the editor lets you
> know they're all closed?

I use the following configuration for Lisp-related modes in XEmacs:

,----
| (defmacro make-key-inserter (def)
|   "Substitute for `self-insert-command'."
|   `(lambda (arg)
|     (interactive "*P")
|     (insert-char ,def (prefix-numeric-value arg))))
| 
| (define-key shared-lisp-mode-map ?\[ 'insert-parentheses)
| (define-key shared-lisp-mode-map ?\] 'move-past-close-and-reindent)
| (define-key shared-lisp-mode-map '(meta ?\[) (make-key-inserter ?\[))
| (define-key shared-lisp-mode-map '(meta ?\]) (make-key-inserter ?\]))
| (define-key shared-lisp-mode-map '(meta control ?\]) 'slime-close-all-sexp)
`----

The most important one there is `insert-parentheses', bound to the
left bracket ('[') key. I use that to open a balanced sexp, and almost
never type a lone parentheses character. The right bracket (']') key
is a useful movement aid that typically doesn't insert any non-space
characters.

-- 
Steven E. Harris
From: ···············@yahoo.com
Subject: Re: Style question
Date: 
Message-ID: <1133811921.313731.85410@f14g2000cwb.googlegroups.com>
I keep hitting right-paren, but watch the corresponding left-paren
[Emacs makes it blink].  It's a possible bug either if the left-parens
don't march diagonally up to the left, or if it doesn't make sense that
you'd be closing such-and-such a form after the one you've just closed.
From: Jack Unrue
Subject: Re: Style question
Date: 
Message-ID: <n5t9p1li09pjj0js0bo6vl4nu5amsm9hci@4ax.com>
On 5 Dec 2005 11:45:21 -0800, ···············@yahoo.com wrote:

> I keep hitting right-paren, but watch the corresponding left-paren
> [Emacs makes it blink].  It's a possible bug either if the left-parens
> don't march diagonally up to the left, or if it doesn't make sense that
> you'd be closing such-and-such a form after the one you've just closed.

Yep, me too.  And I also traverse right-parens with the cursor to
double-check things.

In another post, I said I was going to investigate some Emacs-editing
macros and what-not for TextPad, but the paren matching behavior in
TextPad is suboptimal and I don't yet know of any way to fix it:

  - you have to explicitly request paren matching via a keypress
  - only one of a pair is matched at a time
  - the matching paren is actually selected for editing instead
    of being highlighted separately, which means an edit from
    there destroys the paren you just matched

So I gave up that idea.

-- 
Jack Unrue
From: Majorinc, Kazimir
Subject: Re: Style question
Date: 
Message-ID: <MPG.1dfe97d47107289d9898ab@news.carnet.hr>
In article <··············@gigamonkeys.com>, 
·····@gigamonkeys.com says...


> >                 (format t "Too low~%Try again: ")
> >             )
> >         )
> >     )
> > )
> 
> This is pretty much fine except you should not leave those closing
> parens dangling on their own lines. Just lump them all together after
> the closing paren of the last FORMAT expression.



I have find that it is harder to comment out lines or add some 
extra expressions for debbuging purposes if closing parens are 
lumped together. 

( 
   (....) ;(some debugging job)
)

is better than

(
   (....) (some debugging job)) ; ???

What is the advantage of the Lisp style, i.e. closing parens in 
the same line))))?
From: Coby Beck
Subject: Re: Style question
Date: 
Message-ID: <Dd0lf.136313$y_1.92237@edtnps89>
<Majorinc>; "Kazimir" <·····@email.address> wrote in message 
·······························@news.carnet.hr...
> In article <··············@gigamonkeys.com>,
> ·····@gigamonkeys.com says...
>
>
>> >                 (format t "Too low~%Try again: ")
>> >             )
>> >         )
>> >     )
>> > )
>>
>> This is pretty much fine except you should not leave those closing
>> parens dangling on their own lines. Just lump them all together after
>> the closing paren of the last FORMAT expression.
>
> I have find that it is harder to comment out lines or add some
> extra expressions for debbuging purposes if closing parens are
> lumped together.
>
> (
>   (....) ;(some debugging job)
> )
>
> is better than
>
> (
>   (....) (some debugging job)) ; ???
>

I don't disagree with you, and I often do the same.  I don't recommend it as 
a habit put everywhere "just in case", only do it in the precise places 
where you actually do need some debugging work.  But I clean it up as soon 
as I'm done, just like the (format t "foo is ~A here" foo) expressions. 
Certainly I clean it up if I'm going to post it to a lisp newsgroup ;)

> What is the advantage of the Lisp style, i.e. closing parens in
> the same line))))?

The advantages are:
- less screen realestate used up
- encourages the zen of lisp "there are no parentheses,
  there are only expressions"
- facilitates the flexibility of functional expressions,
  rather than the stiffness of statement-centered styles.
- conforms with the social norms of lisp development.

(don't dismiss too lightly this last point, purposely ignoring conventions 
that every one else embraces is very anti-social and only works if you 
program now and forever in a bubble of source code solitude)

-- 
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")


-- 
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: Pascal Costanza
Subject: Re: Style question
Date: 
Message-ID: <3vje02F15nul4U1@individual.net>
Majorinc wrote:
> In article <··············@gigamonkeys.com>, 
> ·····@gigamonkeys.com says...
> 
> 
> 
>>>                (format t "Too low~%Try again: ")
>>>            )
>>>        )
>>>    )
>>>)
>>
>>This is pretty much fine except you should not leave those closing
>>parens dangling on their own lines. Just lump them all together after
>>the closing paren of the last FORMAT expression.
> 
> I have find that it is harder to comment out lines or add some 
> extra expressions for debbuging purposes if closing parens are 
> lumped together. 
> 
> ( 
>    (....) ;(some debugging job)
> )
> 
> is better than
> 
> (
>    (....) (some debugging job)) ; ???

Try:

(... (...) #|(some debugging job)|#)

or:

(... (...) #+(or)(some debugging job))

or even better:

(... (...) #+debug (some debugging job))

Then adding or removing :debug to *features* will enable or disable 
debugging.

> What is the advantage of the Lisp style, i.e. closing parens in 
> the same line))))?

Vertical space is valuable. The more code you can fit on a screen, the 
better overview you have over what the overall code is doing. That's why 
features that reduce code size are in general a good idea (functions, 
macros, etc.)

The amount of information of one single closing bracket on a line of 
code is almost zero.


Pascal

-- 
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/
From: Edi Weitz
Subject: Re: Style question
Date: 
Message-ID: <ud5kbe7ky.fsf@agharta.de>
On Mon, 5 Dec 2005 18:31:17 +0100, Majorinc, Kazimir <·····@email.address> wrote:

> I have find that it is harder to comment out lines or add some extra
> expressions for debbuging purposes if closing parens are lumped
> together.

Then you're probably using the wrong editor...

Cheers,
Edi.

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: Philippe Lorin
Subject: Re: Style question
Date: 
Message-ID: <4398169a$0$21716$626a54ce@news.free.fr>
Majorinc wrote:
> I have find that it is harder to comment out lines or add some 
> extra expressions for debbuging purposes if closing parens are 
> lumped together. 

I'm glad you brought this up. I have the same problem. My very first 
Lisp programs were written in C-style, but now that the language has 
become clearer to me I prefer the Lisp style (putting all closing 
parentheses together). However, I still regularly need to comment out 
some line, and the closing parentheses get in my way, so I end up 
putting them on the following line. When my code is fixed, I reformat 
back to standard style, which I find more readable. But this is frustrating.

I'd be interested in hearing more of seasoned Lispers' advice about this 
problem. I find Pascal Costanza's solution (#|...|# / #+debug) too 
heavy: you need to reach the expression, rather than just the line, and 
write/delete more characters. I'm using the proper editor (Emacs), but 
I'm not yet fluent in Slime, so maybe there's something to that as Edi 
Weitz suggested -- could somebody hint at any helpful commands?

I also suspect that the need for commenting out code is linked to my not 
much using the repl. Except for testing the behaviour of standard 
functions or isolatable constructs, I usually launch my Lisp with my 
loader file, and when the program's done it quits (I'm developing a GUI 
program so I'm afraid using the repl interactively is not as easy; or is 
it just me?).
From: Edi Weitz
Subject: Re: Style question
Date: 
Message-ID: <u4q5jakag.fsf@agharta.de>
On Thu, 08 Dec 2005 12:20:35 +0100, Philippe Lorin <············@gmail.com> wrote:

> I'm using the proper editor (Emacs), but I'm not yet fluent in
> Slime, so maybe there's something to that as Edi Weitz suggested --
> could somebody hint at any helpful commands?

It's not about SLIME but rather about Emacs (and applies to similar
editors like the one from LispWorks as well).  You need to learn the
basic commands for navigating S-expressions.  It'll take some time to
get used to them but once you're fluent it's a /lot/ easier to edit
Lisp (Common Lisp, Emacs Lisp, Scheme) programs.

Here are some examples off the top of my head.  I probably forgot some
that I use daily without thinking about them so others should chime
in:

  C-M-f and C-M-b move forward and backward one s-expr

  C-M-d moves forward and then "down" one s-expr

  C-M-u moves "up" one s-expr

  C-M-h marks the current "defun" (Emacs' concept of the top-level
        form you're in)

  C-M-SPC mark until the end of the current s-expr

  C-M-a and C-M-e move to the beginning and end of a "defun"

  C-M-q indents the code properly (C-M-a C-M-q is a combo I use
        frequently)

  C-M-k kills the next s-exp (there's a similar command for killing
        backwards but it differs between platforms and might be the
        one that by default kills your X server if you're on Unix)

HTH,
Edi.

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: Edgar
Subject: Re: Style question
Date: 
Message-ID: <1134066864.263644.288910@g44g2000cwa.googlegroups.com>
Edi Weitz wrote:
> On Thu, 08 Dec 2005 12:20:35 +0100, Philippe Lorin <············@gmail.com> wrote:
>
> > I'm using the proper editor (Emacs), but I'm not yet fluent in
> > Slime, so maybe there's something to that as Edi Weitz suggested --
> > could somebody hint at any helpful commands?
>
> It's not about SLIME but rather about Emacs (and applies to similar
> editors like the one from LispWorks as well).  You need to learn the
> basic commands for navigating S-expressions.  It'll take some time to
> get used to them but once you're fluent it's a /lot/ easier to edit
> Lisp (Common Lisp, Emacs Lisp, Scheme) programs.
>
> Here are some examples off the top of my head.  I probably forgot some
> that I use daily without thinking about them so others should chime
> in:
>
>   C-M-f and C-M-b move forward and backward one s-expr
>
>   C-M-d moves forward and then "down" one s-expr
>
>   C-M-u moves "up" one s-expr
>
>   C-M-h marks the current "defun" (Emacs' concept of the top-level
>         form you're in)
>
>   C-M-SPC mark until the end of the current s-expr
>
>   C-M-a and C-M-e move to the beginning and end of a "defun"
>
>   C-M-q indents the code properly (C-M-a C-M-q is a combo I use
>         frequently)
>
>   C-M-k kills the next s-exp (there's a similar command for killing
>         backwards but it differs between platforms and might be the
>         one that by default kills your X server if you're on Unix)
>
> HTH,
> Edi.
>
> --
>
> Lisp is not dead, it just smells funny.
>
> Real email: (replace (subseq ·········@agharta.de" 5) "edi")

Also, after you have marked the s-exp with C-M-SPC, you can comment
out the s-exp with the command 'M-x comment-dwim' (bound to M-;).

This will comment out only the s-exp.

Any other ')' that are on the same line as the final ')' in the marked
s-exp are automatically moved to a new line so that they are not
commented. 

Edgar.
From: Edi Weitz
Subject: Re: Style question
Date: 
Message-ID: <u4q5jxwge.fsf@agharta.de>
On 8 Dec 2005 10:34:24 -0800, "Edgar" <··········@comcast.net> wrote:

> Also, after you have marked the s-exp with C-M-SPC, you can comment
> out the s-exp with the command 'M-x comment-dwim' (bound to M-;).
>
> This will comment out only the s-exp.
>
> Any other ')' that are on the same line as the final ')' in the
> marked s-exp are automatically moved to a new line so that they are
> not commented.

Thanks, didn't know that.

BTW, another way to comment out one s-exp is to write #+(or) (or
#-(and) which some prefer) in front of it.

  (defun foo (x)
    (let ((y x)) #+(or) (incf y) y))

So, the function above will return x, not x + 1.

Cheers,
Edi.

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: David Trudgett
Subject: Re: Style question
Date: 
Message-ID: <m3vexwimrg.fsf@rr.trudgett>
Edi Weitz <········@agharta.de> writes:

> On 8 Dec 2005 10:34:24 -0800, "Edgar" <··········@comcast.net> wrote:
>
>> Also, after you have marked the s-exp with C-M-SPC, you can comment
>> out the s-exp with the command 'M-x comment-dwim' (bound to M-;).
>>
>> This will comment out only the s-exp.
>>
>> Any other ')' that are on the same line as the final ')' in the
>> marked s-exp are automatically moved to a new line so that they are
>> not commented.
>
> Thanks, didn't know that.

Aren't there also key sequences to wrap and unwrap the next sexp? I
thought they might have been listed here:

    http://www.cliki.net/Editing%20Lisp%20Code%20with%20Emacs

but they aren't there. There is also (mentioned in the above page):

    http://mumble.net/~campbell/emacs/paredit.el

but I don't think I've ever used that (whereas I think I *have* done
the wrap/unwrap thing before).


David


-- 

David Trudgett
http://www.zeta.org.au/~wpower/

Government is not reason. Government is not eloquence. It is force.
And, like fire, it is a dangerous servant and a fearful master.

    -- George Washington
From: Coby Beck
Subject: Re: Style question
Date: 
Message-ID: <2D%lf.235809$ir4.195235@edtnps90>
"Philippe Lorin" <············@gmail.com> wrote in message 
······························@news.free.fr...
> Majorinc wrote:
>> I have find that it is harder to comment out lines or add some extra 
>> expressions for debbuging purposes if closing parens are lumped together.
>
> I'm glad you brought this up. I have the same problem. My very first Lisp 
> programs were written in C-style, but now that the language has become 
> clearer to me I prefer the Lisp style (putting all closing parentheses 
> together). However, I still regularly need to comment out some line, and 
> the closing parentheses get in my way, so I end up putting them on the 
> following line. When my code is fixed, I reformat back to standard style, 
> which I find more readable. But this is frustrating.

I am not sure what you find frustrating about that, it seems a reasonable 
way to work to me.  But here are a few suggestions:
- sometimes you can just put a quote in front of an expression.
   Caveats: must be sufficiently isolated functionally so the returned
            expression is irrelevant.
   Pros: fast, one character to add or remove
   Cons: hard to see, easy to forget
- bind test data to local variables and evaluate your function
  step by step in place or in the REPL.
   Caveats: data involved must be practical to create.  Don't
            use this method over long lisp sessions.
   Pros: see precise behaviours one expression at a time
         find and fix immediately, then move on
   Cons: you will probably be creating specials out of locals which
         gives you a very small chance of creating very subtle bugs
         (see second caveat)
- use the REPL for "proof of concept" tests of individual expressions
  as you build your functions for the first time.
   Caveats: similar to just above
   Pros: your function is debugged before you even insert the final paren.
   Cons: only works well in bottom up developement or can leave you with
         lots of "stub" functions all over
- test all of your functions individually and rigourously
   Caveats: not always practical depending on complexity of data structures
   Pros: very favorable ratio of bugs caught right at the source to bugs
         buried deep in long forgotten code.
   Cons: slows you down during those inspired rapid development phases.

Personally, it is rather rare that I finish writing a long or medium length 
function where most of the internal chanks have not been pretty well tested. 
It takes longer to finish a particular piece of code, but there is something 
very satisfying about writing a complex function that works <cough> 
perfectly right out of the box.

> I'd be interested in hearing more of seasoned Lispers' advice about this 
> problem. I find Pascal Costanza's solution (#|...|# / #+debug) too heavy: 
> you need to reach the expression, rather than just the line, and 
> write/delete more characters. I'm using the proper editor (Emacs), but I'm 
> not yet fluent in Slime, so maybe there's something to that as Edi Weitz 
> suggested -- could somebody hint at any helpful commands?

I often just kill suspect sections, rerun whatever, and then ctrl-_ to undo 
it.  Just don't get distracted!

> I also suspect that the need for commenting out code is linked to my not 
> much using the repl. Except for testing the behaviour of standard 
> functions or isolatable constructs, I usually launch my Lisp with my 
> loader file, and when the program's done it quits (I'm developing a GUI 
> program so I'm afraid using the repl interactively is not as easy; or is 
> it just me?).

That does sound like you are not utilizing the greatest advantage an 
integrated debugger and a REPL offers.  I have not however written much GUI 
code so I don't know if working with event loops etc makes that harder.

-- 
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: Alan Crowe
Subject: Re: Style question
Date: 
Message-ID: <863bl3mm2l.fsf@cawtech.freeserve.co.uk>
Philippe Lorin <············@gmail.com> writes:
> I also suspect that the need for commenting out code is linked to my not 
> much using the repl. Except for testing the behaviour of standard 
> functions or isolatable constructs, I usually launch my Lisp with my 
> loader file, and when the program's done it quits (I'm developing a GUI 
> program so I'm afraid using the repl interactively is not as easy; or is 
> it just me?).

I hit this problem when playing with CLX. The core of a CLX
program is the event loop that is responding to messages
from the window system. While it is sitting in the event
loop the REPL is locked out.

Rather than learn the multiprocessing stuff, I used my
interaction macro. It depends on CLX's event-case having a
time out. I set the time out to, oh, half a second, then
check for input on the REPL with listen.

There are various limitations. If you want to send a
multiline form to the REPL it is best to type it into an
Emacs buffer and then send it across all at once with
Meta-Ctrl-x, otherwise READ will be waiting for the final
closing bracket and block the event loop.

Also, if a form that you send to the REPL signals an error
that will also block the event loop until you choose a
restart. This is uncool, but is sometimes what you actually
want.

Example
-------
* (defun tabulate (arg-func-pair)
    (format t "~&~A ~A~%"
            (car arg-func-pair)
            (funcall (cdr arg-func-pair)
                   (car arg-func-pair)))
    (incf (car arg-func-pair))
    (sleep 2))

TABULATE
* (defparameter *afp* (cons 7 #'log))

*AFP*
* (repeat-interactively () (tabulate *afp*))

>>-0-> 
7 1.9459101
8 2.0794415
9 2.1972246
10 2.3025851
(setf (cdr *afp*) (lambda(x)(* x x)))

#<Interpreted Function (LAMBDA (X) (* X X)) {4814BA19}> 
>>-4-> 
11 121
12 144
13 169
(throw 'stop 'enough-already)
ENOUGH-ALREADY

The macro
---------

;;;; repeat-interactively
;;;
;;; Allows the programmer to work on running code
;;; 
(defmacro repeat-interactively ((&optional (tick 1)
					   (count-var 'count)
					   (prompt "~&>>-~A-> "))
				&body code)
  `(flet ((prompt-user()
	    (declare (special prompt ,count-var ))
	    (format t prompt ,count-var)
	    (force-output)))
      (let ((,count-var 0)
	    (prompt ,prompt)
	    (tick ,tick))
	(declare (special ,count-var prompt tick))
	(prompt-user)
	(catch 'stop
	  (loop
	   (restart-case
	    (progn ,@code (incf ,count-var)(sleep tick))
	    (fixed () :report "Resume processing."))
	   (when (listen)
	     (tagbody top
		      (restart-case
		       (progn
			 (print (eval (read)))
			 (prompt-user))
		       (shrug () :report "Continue processing."
			      (prompt-user))
		       (retry () :report "Evaluate another form."
			      (prompt-user)
			      (go top)))))
	   )))))

Oh dear I need to work on this macro one day. Don't put
anything that you might need to change in the body of code,
because you cannot change it without restarting. It would be
better if the macro just took a symbol naming a function
that gets called repeatedly. If your GUI code signals an
error you fix the running code by sending the new definition
across to the repl from the source code file, and then
selecting the FIXED restart. The GUI is blocked waiting for
you to do this.

It would be way cool to rewrite this with a wrapper on DEFUN
to stack up the old function definitions. Then one could
write an error handler so that the GUI code could fall back
to an earlier definition and continue running while you
decided how to fix the new definition. Of course, if the
error has borked global data structures you lose, but it
would make a nice demo.

The point of my interaction macro is that it is ANSI CL, so
it should work with every implementation, and not require
learning anything not in the spec.

Alan Crowe
Edinburgh
Scotland

P.S. Here is a fun thing to do with an implementation that
has a both an interpreter and a compiler.

Write a function that is compute intensive, say a tree
recursive computation of the fibonacci series. Have it print
to a file, with a finish-output to make sure it gets there.
Follow the progress in an xterm with tail -f.

Use the REPL built into repeat-interactively to compile the
program and load it. Watch the running tabulation get faster
as the compiled version is loaded into the running
image. Coming from a C background I find this mind blowing.
From: Majorinc, Kazimir
Subject: Re: Style question
Date: 
Message-ID: <MPG.1e03e9f1881da550989681@news.carnet.hr>
In article <·························@news.free.fr>, 
············@gmail.com says...

> Majorinc wrote:
> > I have find that it is harder to comment out lines or add some 
> > extra expressions for debbuging purposes if closing parens are 
> > lumped together. 
> 
> I'm glad you brought this up. I have the same problem. My very first 
> Lisp programs were written in C-style, but now that the language has 
> become clearer to me I prefer the Lisp style (putting all closing 
> parentheses together). However, I still regularly need to comment out 
> some line, and the closing parentheses get in my way, so I end up 
> putting them on the following line. When my code is fixed, I reformat 
> back to standard style, which I find more readable. But this is frustrating.

Not only commenting out debugging expressions; each insertion 
of the code between closing parenthesesis is more complicated 
in standard Lisp style. Emacs only partly compensates.

Furthermore, availability of sophisticated and specialized text 
editors shouldn't be taken for granted. They are not required 
by Lisp standard. It is better that style works well even in 
simple editors.
From: Thomas A. Russ
Subject: Re: Style question
Date: 
Message-ID: <ymilkyqnq32.fsf@sevak.isi.edu>
Majorinc, Kazimir <·····@email.com> writes:

> 
> In article <·························@news.free.fr>, 
> ············@gmail.com says...
> 
> > Majorinc wrote:
> > > I have find that it is harder to comment out lines or add some 
> > > extra expressions for debbuging purposes if closing parens are 
> > > lumped together. 
> > 
> > I'm glad you brought this up. I have the same problem. My very first 
> > Lisp programs were written in C-style, but now that the language has 
> > become clearer to me I prefer the Lisp style (putting all closing 
> > parentheses together). However, I still regularly need to comment out 
> > some line, and the closing parentheses get in my way, so I end up 
> > putting them on the following line. When my code is fixed, I reformat 
> > back to standard style, which I find more readable. But this is frustrating.
> 
> Not only commenting out debugging expressions; each insertion 
> of the code between closing parenthesesis is more complicated 
> in standard Lisp style.  Emacs only partly compensates.

No it isn't.  You just position your cursor in the correct place and
either paste or start typing.  That isn't any easier or harder depending
on where the close parentheses go.  You still need to find the correct
place to insert the new code, and that is where having
language-appropriate editing tools helps.  Being able to move forward
one S-expression helps a lot.

> Furthermore, availability of sophisticated and specialized text 
> editors shouldn't be taken for granted. They are not required 
> by Lisp standard. It is better that style works well even in 
> simple editors.

The style will work in all editors.  It is just that certain language
support makes life a lot easier.  After all, writing C code using
Microsoft Word is possible, but the indenting will be all funny, and not
easy to do.

The lisp style has evolved over time, not to make your life harder, but
rather to make the life and communication of the programs among regular
practitioners of the language easier.  There is a well-founded set of
reasons for why this particular style has developed.  You are free to
disregard this experience and write Lisp any way you want, but it does
mean foregoing the collective wisdom of many programmers.  You pick.

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Rainer Joswig
Subject: Re: Style question
Date: 
Message-ID: <BFC39108.22389%joswig@lisp.de>
Am 09.12.2005 19:23 Uhr schrieb "Majorinc, Kazimir" unter <·····@email.com>
in ··························@news.carnet.hr:

> In article <·························@news.free.fr>,
> ············@gmail.com says...
> 
>> Majorinc wrote:
>>> I have find that it is harder to comment out lines or add some
>>> extra expressions for debbuging purposes if closing parens are
>>> lumped together.
>> 
>> I'm glad you brought this up. I have the same problem. My very first
>> Lisp programs were written in C-style, but now that the language has
>> become clearer to me I prefer the Lisp style (putting all closing
>> parentheses together). However, I still regularly need to comment out
>> some line, and the closing parentheses get in my way, so I end up
>> putting them on the following line. When my code is fixed, I reformat
>> back to standard style, which I find more readable. But this is frustrating.
> 
> Not only commenting out debugging expressions; each insertion
> of the code between closing parenthesesis is more complicated
> in standard Lisp style.

Really? Move the cursor at the position, 'Indent New Line' (for example c-j
in LispWorks) and start typing...

> Emacs only partly compensates.

Come on. If there are any features needed for Lisp source editing, they are
a) already provided or b) implementable in Emacs. That's the point
of Emacs (and related editors).

> Furthermore, availability of sophisticated and specialized text
> editors shouldn't be taken for granted. They are not required
> by Lisp standard. It is better that style works well even in
> simple editors.
> 

You can dig a hole with your hands or take a shovel...
Even if you prefer to use a shovel, you can still try to design
your work process so that you can dig with your hands.

Using tools is a productivity boost. Lisp is a tool-building tool.
;-)
From: Rob Warnock
Subject: Re: Style question
Date: 
Message-ID: <H_WdnX7LMJeGPwzeRVn-rQ@speakeasy.net>
micromoog <·········@gmail.com> wrote:
+---------------
| I'm in the early stages of learning Lisp, and I've just written my
| first program that actually does something (trivial though it is).
| Is my style appropriate for all of the things I'm doing here?
+---------------

Others have commented on your parens & indentation, so I'll just say this:

1. On most platforms you'll need to do a FORCE-OUTPUT [or FINISH-OUTPUT]
   when outputting partial lines, especially to buffered streams.
   [See code below.] (Usually you can omit this if what you're printing
   ends in a newline.)

2. Use the "expression" (rather than "statement") nature of the
   language to help you simplify things. That is, rather than this:

     (if (> guess num)
       (format t "Too high, try again: ")
       (format t "Too low, try again: ")

   you can write this:

       (format t "Too ~a, try again: " (if (> guess num) "high" "low"))

3. FORMAT -- which is *much* more powerful than C's PRINTF! -- has a
   built-in feature to make that slightly shorter still (but note that
   this conditional requires the order "~:[false~;true~]"):

       (format t "Too ~:[low~;high~], try again: " (> guess num))

4. When you get a little further you might want to start exploring
   the majesty & mystery of LOOP as an alternative to DO. I don't
   suggest jumping into it right now, but as a hint of what's to
   come, below is a version using LOOP.

Put that all together (with one or two other tweaks, such as the
addition of an optional upper LIMIT arg), and one gets this version:

   > (defun game (&optional (limit 100))
       (format t "Enter a number between 0 and ~d: " (1- limit))
       (force-output)
       (loop with num = (random limit)
	     for guess = (read)
	     and guesses from 1
	     until (= guess num) 
	 do (format t "Too ~:[low~;high~], try again: " (> guess num))
	    (force-output)
	 finally (format t "Right!~%It took you ~A guesses.~%" guesses))) 

   GAME
   > (game)
   Enter a number between 0 and 99: 50
   Too high, try again: 25
   Too low, try again: 37
   Too low, try again: 42
   Too low, try again: 46
   Too low, try again: 48
   Right!
   It took you 6 guesses.
   NIL
   > (game 250)
   Enter a number between 0 and 249: 125
   Too high, try again: 62
   Too high, try again: 31
   Too high, try again: 15
   Too low, try again: 25
   Too high, try again: 20
   Too low, try again: 22
   Too low, try again: 23
   Right!
   It took you 8 guesses.
   NIL
   > 


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: micromoog
Subject: Re: Style question
Date: 
Message-ID: <1133675477.747158.311520@f14g2000cwb.googlegroups.com>
Rob Warnock wrote:
> Others have commented on your parens & indentation, so I'll just say this:

Thanks for commenting.

> 2. Use the "expression" (rather than "statement") nature of the
>    language to help you simplify things. That is, rather than this:
>
>      (if (> guess num)
>        (format t "Too high, try again: ")
>        (format t "Too low, try again: ")
>
>    you can write this:
>
>        (format t "Too ~a, try again: " (if (> guess num) "high" "low"))

I thought there should be a more elegant way to do this.  Thanks!

> 4. When you get a little further you might want to start exploring
>    the majesty & mystery of LOOP as an alternative to DO. I don't
>    suggest jumping into it right now, but as a hint of what's to
>    come, below is a version using LOOP.

Others on this thread have also commented that DO is not preferable.
Is LOOP just a more powerful construct, or are there other reasons
(e.g. performance)?
From: Aaron Sokoloski
Subject: Re: Style question
Date: 
Message-ID: <1133683734.281123.244150@g44g2000cwa.googlegroups.com>
LOOP is more powerful than DO, while performance should be exactly the
same in most cases.  But most consider LOOP far easier on the brain,
both to write and to read.
From: Edi Weitz
Subject: Re: Style question
Date: 
Message-ID: <uy83141yd.fsf@agharta.de>
On 3 Dec 2005 21:51:17 -0800, "micromoog" <·········@gmail.com> wrote:

>>        (format t "Too ~a, try again: " (if (> guess num) "high" "low"))
>
> I thought there should be a more elegant way to do this.

  (format t "Too ~:[low~;high~], try again: " (> guess num))

Cheers,
Edi.

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: Rob Warnock
Subject: Re: Style question
Date: 
Message-ID: <R5SdnaXe6fP7Xw_eRVn-tQ@speakeasy.net>
Edi Weitz  <········@agharta.de> wrote:
+---------------
| "micromoog" <·········@gmail.com> wrote:
| >>        (format t "Too ~a, try again: " (if (> guess num) "high" "low"))
| >
| > I thought there should be a more elegant way to do this.
| 
|   (format t "Too ~:[low~;high~], try again: " (> guess num))
+---------------

Yes, I pointed that out, in my point #3 [which OP didn't quote].


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: micromoog
Subject: Re: Style question
Date: 
Message-ID: <1133712538.395351.286410@g47g2000cwa.googlegroups.com>
Rob Warnock wrote:
> Yes, I pointed that out, in my point #3 [which OP didn't quote].
>

Sorry if I wasn't clear; I meant that your way (the one I quoted) _was_
the more elegant way.  While your second one, which I didn't quote, was
a more elegant way still :)
From: Edi Weitz
Subject: Re: Style question
Date: 
Message-ID: <uu0dp3wft.fsf@agharta.de>
On Sun, 04 Dec 2005 04:18:14 -0600, ····@rpw3.org (Rob Warnock) wrote:

> Yes, I pointed that out, in my point #3 [which OP didn't quote].

Oops, sorry.

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: Alain Picard
Subject: Re: Style question
Date: 
Message-ID: <87k6emzwr1.fsf@memetrics.com>
"micromoog" <·········@gmail.com> writes:

> I'm in the early stages of learning Lisp, and I've just written my
> first program that actually does something (trivial though it is).  

Good for you!  Welcome to the lisp world!

> Is my style appropriate for all of the things I'm doing here?
> I guess what I'm asking: am I on the road to developing any obvious bad
> habits here?  I know this code uses side effects for the I/O, but it
> seems appropriate.

The worse habit you have is that you're thinking of the parentheses
as though they were braces in C-like languages---they are not.
Lispers never put an empty paren on a line, thus your code is
more idiomatically expressed as:

(defun game ()
  (format t "Enter a number: ")
  (let ((num (random 100)))
    (do ((guess (read) (read)) (guesses 1 (+ guesses 1)))
	((= guess num)
	 (format t "Right!~%It took you ~A guesses.~%" guesses))
      (if (> guess num)
	  (format t "Too high~%Try again: ")
	  (format t "Too low~%Try again: ")))))

Secondly, your indentation was weird --- the above is what
the stock slime/emacs combination produces.

As for the finer points of io, use of DO, etc, I'll let others
comment on those aspects... :-)

> Also, my materials all refer to just using the read-eval-print loop
> (which is great for development).  I was trying to figure out how to
> make programs executable from the OS in the normal way, and I ended up
> including a function call, followed by (quit), in the source file
> itself, then loading the program using the shell script below.  Is this
> a normal approach?

Yes -- it is _a_ normal approach.  Other approaches may be available
to you depending on which implementation your are using.

Cheers, and happy lisping!

-- 
It would be difficult to construe        Larry Wall, in  article
this as a feature.			 <·····················@netlabs.com>
From: Coby Beck
Subject: Re: Style question
Date: 
Message-ID: <q2mkf.232661$ir4.217883@edtnps90>
"Alain Picard" <············@memetrics.com> wrote in message 
···················@memetrics.com...

> As for the finer points of io, use of DO, etc, I'll let others
> comment on those aspects... :-)

My only opinion about the use of DO is DON'T ;)

-- 
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: drewc
Subject: Re: Style question
Date: 
Message-ID: <mGukf.31890$Eq5.1157@pd7tw1no>
Coby Beck wrote:
> "Alain Picard" <············@memetrics.com> wrote in message 
> ···················@memetrics.com...
> 
> 
>>As for the finer points of io, use of DO, etc, I'll let others
>>comment on those aspects... :-)
> 
> 
> My only opinion about the use of DO is DON'T ;)
> 

lol, i'm glad someone else feels that way :). I've never found DO 
readable, or writable for that matter.



-- 
Drew Crampsie
drewc at tech dot coop
  "... the most advanced use of lisp in the field of bass lure sales"
	-- Xach on #lisp
From: micromoog
Subject: Re: Style question
Date: 
Message-ID: <1133675607.251739.98980@o13g2000cwo.googlegroups.com>
drewc wrote:
> Coby Beck wrote:
> > "Alain Picard" <············@memetrics.com> wrote in message
> >
> >>As for the finer points of io, use of DO, etc, I'll let others
> >>comment on those aspects... :-)
> >
> > My only opinion about the use of DO is DON'T ;)
> >
>
> lol, i'm glad someone else feels that way :). I've never found DO
> readable, or writable for that matter.

Is LOOP the way to go, then, for iteration?
From: Edi Weitz
Subject: Re: Style question
Date: 
Message-ID: <u3bl95gnj.fsf@agharta.de>
On 3 Dec 2005 21:53:27 -0800, "micromoog" <·········@gmail.com> wrote:

> Is LOOP the way to go, then, for iteration?

Yes.  Or DOTIMES and DOLIST in simple cases.

Cheers,
Edi.

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: John Thingstad
Subject: Re: Style question
Date: 
Message-ID: <op.s09b95empqzri1@mjolner.upc.no>
On Sun, 04 Dec 2005 06:53:27 +0100, micromoog <·········@gmail.com> wrote:

> drewc wrote:
>> Coby Beck wrote:
>> > "Alain Picard" <············@memetrics.com> wrote in message
>> >
>> >>As for the finer points of io, use of DO, etc, I'll let others
>> >>comment on those aspects... :-)
>> >
>> > My only opinion about the use of DO is DON'T ;)
>> >
>>
>> lol, i'm glad someone else feels that way :). I've never found DO
>> readable, or writable for that matter.
>
> Is LOOP the way to go, then, for iteration?
>

Well. That is debatable.
Some lispers avoid LOOP like the plaugue claiming it is unlispy.
DO has a simple command structure that although difficult to read
until you get used to it is far easier to get right.
Now there is plenty of documentation on how to use LOOP right
though so it is less of a problem.
Still see www.norvig.com/luv-slides.ps for some style guides.

-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
From: Rob Warnock
Subject: Re: Style question
Date: 
Message-ID: <x4Kdna3blcSd4wjeRVn-sw@speakeasy.net>
John Thingstad <··············@chello.no> wrote:
+---------------
| micromoog <·········@gmail.com> wrote:
| > Is LOOP the way to go, then, for iteration?
| 
| Well. That is debatable.
| Some lispers avoid LOOP like the plaugue claiming it is unlispy.
| DO has a simple command structure that although difficult to read
| until you get used to it is far easier to get right.
| Now there is plenty of documentation on how to use LOOP right
| though so it is less of a problem.
| Still see www.norvig.com/luv-slides.ps for some style guides.
+---------------

Also, start slow with LOOP, sticking to a few simple templates
you understand [or useful idioms you see posted], and only add
additional refinements as you find you actually need them later.

A couple of my favorite basic LOOP-using functions [note the defaulting
of "FOR var = form" which LOOP treats as "FOR var = form THEN form"]:

    (defun file-lines (path)
      "Sucks up an entire file from PATH into a list of freshly-allocated
      strings, returning two values: the list of strings and the number of
      lines read."
      (with-open-file (s path)
	(loop for line = (read-line s nil nil)
	      while line
	  collect line into lines
	  counting t into line-count
	  finally (return (values lines line-count)))))

    (defun file-forms (path)
      "Sucks up an entire file from PATH into a list of forms (sexprs),
      returning two values: the list of forms and the number of forms read."
      (with-open-file (s path)
	(loop with eof = (list :eof)
	      for form = (read s nil eof)
	      until (eq form eof)
	  collect form into forms
	  counting t into form-count
	  finally (return (values forms form-count)))))

The most common set of simple "scanning" iterators in LOOP:

  - To scan a list, use "FOR item IN some-list ...".

  - To scan a string, use "FOR char ACROSS some-string ..."

  - To scan an alist, use "FOR (key . val) IN some-alist ..."

  - To scan a property list, use "FOR (prop val) ON some-plist BY #'cddr ..."

  - To scan a hash table, you need to type a somewhat longer template:

      FOR key BEING HASH-KEY IN some-hash-table USING (HASH-VALUE value) ...

Examples:

    > (let ((alist '((a . 5) (b . 3) (c . 17))))
	(loop FOR (key . val) IN alist
	  do (format t "~a = ~s~%" key val)))
    A = 5
    B = 3
    C = 17
    NIL
    > (let ((plist '(a 5 b 3 c 17)))
	(loop FOR (prop val) ON plist BY #'cddr   
	  do (format t "~a = ~s~%" prop val)))
    A = 5
    B = 3
    C = 17
    NIL
    > 


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Steven E. Harris
Subject: Re: Style question
Date: 
Message-ID: <q947jaidphq.fsf@chlorine.gnostech.com>
····@rpw3.org (Rob Warnock) writes:

> (loop for line = (read-line s nil nil)
>       while line
>       collect line into lines
>       counting t into line-count
>       finally (return (values lines line-count)))

I looked at the macro expansion for "counting t into line-count" and
noticed that each increment operation is wrapped in a conditional
"(when t ...)". Does this conditional check get optimized away?

I'm just wondering why you wouldn't prefer the following:

  (loop for line = (read-line s nil nil)
        for line-count upfrom 0
        while line
        collect line into lines
        finally (return (values lines line-count)))


It misses the expressiveness of "counting", but then I also found
"counting /t/" to be confusing.

-- 
Steven E. Harris
From: Rob Warnock
Subject: Re: Style question
Date: 
Message-ID: <vtudnVIsBNMAGgTenZ2dnUVZ_sCdnZ2d@speakeasy.net>
Steven E. Harris <···@panix.com> wrote:
+---------------
| ····@rpw3.org (Rob Warnock) writes:
| > (loop for line = (read-line s nil nil)
| >       while line
| >       collect line into lines
| >       counting t into line-count
| >       finally (return (values lines line-count)))
| 
| I looked at the macro expansion for "counting t into line-count" and
| noticed that each increment operation is wrapped in a conditional
| "(when t ...)". Does this conditional check get optimized away?
+---------------

I suspect so, in any decent compiler at least. In CMUCL, for example:

    > (macroexpand '(when t (foo)))
    (IF T (PROGN NIL (FOO)) (COND))
    > 

Now that's a *lot* of needless noise, eh? But when we compile it,
it all seems to disappear, and the whole thing gets converted into
an unconditional tail-call of FOO:

    > (disassemble (compile nil (lambda () (when t (foo)))))
    ...
    48910FF8:       .ENTRY "LAMBDA NIL"()     ; (FUNCTION NIL *)
	1010:       POP     DWORD PTR [EBP-8]
	1013:       LEA     ESP, [EBP-32]

	1016:       TEST    ECX, ECX          ; [:NON-LOCAL-ENTRY]
	1018:       JNE     L0

	101A:       MOV     EAX, [#x48910FF0] ; #<FDEFINITION object for FOO>
					      ; No-arg-parsing entry point
					      ; [:NON-LOCAL-ENTRY]
	1020:       XOR     ECX, ECX
	1022:       PUSH    DWORD PTR [EBP-8]
    ;;; [3] (FOO)
	1025:       JMP     DWORD PTR [EAX+5] ; [:CALL-SITE]
	1028: L0:   BREAK   10                ; Error trap
	102A:       BYTE    #x02
	102B:       BYTE    #x19              ; INVALID-ARGUMENT-COUNT-ERROR
	102C:       BYTE    #x4D              ; ECX
    > 

+---------------
| I'm just wondering why you wouldn't prefer the following:
|   (loop for line = (read-line s nil nil)
|         for line-count upfrom 0
|         while line
|         collect line into lines
|         finally (return (values lines line-count)))
+---------------

(*blush!*) No special reason. Of course you're right, "LINE-COUNT
UPFROM 0" is fine, and I'll probably even change my library routine
accordingly. The "COUNTING T" is there probably because I learned
COUNTING before I learned multiple FORs. On the other hand, it
might have been because initially I was unsure about the order of
side-effects with multiple loop variable in the presence of a WHILE,
so I put the COUNTING *after* the WHILE to make sure it only counted
when a line was read. But now that I know LOOP a little better, I
know that all FORs must be before any WHILEs, and are executed in
order.

In CL, but *especially* in LOOP, follow the "there's more than one
way to do it" rule. I suspect I'm not the only one who tends to
get locked into whatever idiom one discovers first. I've only been
seriuoaly using CL for 4-5 years, and even code I wrote just a year
ago now looks horribly non-idiomatic. [But who has time for style-only
rewrites...?]

By the way, since there are no serial dependencies between the two
loop variables, I would prefer to use AND instead of the second FOR,
which might generate slightly better code in some cases:

    (loop for line = (read-line s nil nil)
	  and line-count upfrom 0
	  while line
      collect line into lines
      finally (return (values lines line-count)))

Using FOR/AND/... except when you *need* FOR/FOR/... is, to me,
analogous to always using LET except when you *need* LET*.
Some people feel that matters; some don't.


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Wade Humeniuk
Subject: Re: Style question
Date: 
Message-ID: <u3kkf.232421$ir4.63300@edtnps90>
It looks good, welcome.

It is never too early to consider the condition system.

(define-condition number-guess (simple-condition) ())
(define-condition number-high (number-guess) ())
(define-condition number-low (number-guess) ())
(define-condition number-equal (number-guess) ())

(defun compare-guess (guess number)
   (signal (cond
            ((= guess number) 'number-equal)
            ((< guess number) 'number-low)
            ((> guess number) 'number-high))))

(defun guess (prompt number)
   (format t prompt)
   (compare-guess (read) number))

(defun game ()
   (loop with number = (1+ (random 100))
         with prompt = "Enter a number: "
         for guesses from 1 do
         (handler-case (guess prompt number)
           (number-low ()
              (setf prompt "Too low~%Try again: "))
           (number-high ()
              (setf prompt "Too high~%Try again: "))
           (number-equal ()
              (format t "Right!~%It took you ~A guesses.~%" guesses)
              (return))
           (error () (format t "Invalid Input~%")))))

CL-USER 9 > (game)
Enter a number: test
Invalid Input
Enter a number: 50
Too high
Try again: 20
Too low
Try again: 40
Too high
Try again: 30
Too low
Try again: 35
Too high
Try again: 33
Right!
It took you 7 guesses.
NIL

CL-USER 10 >

Wade
From: Wade Humeniuk
Subject: Re: Style question
Date: 
Message-ID: <IAkkf.151000$yS6.117085@clgrps12>
Looking over my own code I would make the conditions more
descriptive and abort the game on an error.  There may
be other errors than type input errors, e.g. something
wrong with the IO streams (should just abort to be safe).
More specific error handling can be added to handle
specific subclasses of ERROR.


(define-condition number-guess (simple-condition) ())
(define-condition guess-high (number-guess) ())
(define-condition guess-low (number-guess) ())
(define-condition guess-equal (number-guess) ())

(defun compare-guess (guess number)
   (signal (cond
            ((= guess number) 'guess-equal)
            ((< guess number) 'guess-low)
            ((> guess number) 'guess-high))))

(defun game ()
   (loop with number = (1+ (random 100))
         with prompt = "Enter a number: "
         for guesses from 1 do
         (handler-case
             (progn
               (format t prompt)
               (compare-guess (read) number))
           (guess-low () (setf prompt "Too low~%Try again: "))
           (guess-high () (setf prompt "Too high~%Try again: "))
           (guess-equal ()
              (format t "Right!~%It took you ~A guesses.~%" guesses)
              (return-from game))
           (error (error)
              (ignore-errors (format t "Error ~A~%" error))
              (return-from game)))))

CL-USER 3 > (game)
Enter a number: test
Error In = of (TEST 16) arguments should be of type NUMBER.
NIL

CL-USER 4 > (game)
Enter a number: 50
Too low
Try again: 80
Too high
Try again: 70
Too high
Try again: 60
Too high
Try again: 55
Too high
Try again: 52
Too low
Try again: 53
Too low
Try again: 54
Right!
It took you 8 guesses.
NIL
From: micromoog
Subject: Re: Style question
Date: 
Message-ID: <1133674980.854129.167520@z14g2000cwz.googlegroups.com>
Wade Humeniuk wrote:
> [snip code using the condition system and error handling]

Some of this is well over my head at this point, but I'm planning to
save this thread anyway for review later.  Thanks for the suggestions!
From: Wade Humeniuk
Subject: Re: Style question
Date: 
Message-ID: <4XEkf.152695$yS6.65514@clgrps12>
micromoog wrote:
> Wade Humeniuk wrote:
> 
>>[snip code using the condition system and error handling]
> 
> 
> Some of this is well over my head at this point, but I'm planning to
> save this thread anyway for review later.  Thanks for the suggestions!
> 

Your welcome.  One of the defining things about (at least Common) Lisp
is that programs do not crash in the way many other programs do.  If
a Common Lisp core dumps its because of a fault in the implementation or
maybe a problem with program's Foreign Function logic.  As a Lisp coder
you can put "protection" around large blocks of code (ie HANDLER-CASE).
This has the effect of allowing one to abort gracefully (hopefully
logging the problem).  A really good example of using this is with
a CL web server.  If the web server encounters (even an unintentional)
error, it can be caught and something can be returned to the web client.
This error handling is free and easy in Lisp.  For your example there
are all sorts of errors that can happen with the guesser's interaction.
Determining what all the possible errors in the GUESS program could
be indeterminate, putting a general error handler around it is easier,
and just as safe.

Wade