From: Alexis Gallagher
Subject: Should I read lisp "bacwards"
Date: 
Message-ID: <dveu91$l86$1@news.ox.ac.uk>
Hi,

When I think of a process, I usually think of it is as progressing from 
the left to the right, or else from the top to the bottom. This is the 
conventional layout of graphs plotting change over time, of flowcharts, 
and of English writing.

But when I write in a functional style in CL, the nesting of operators 
seems to force me to write "backwards", in that the original value is 
the innermost value, and successive processing steps expand outward -- 
actually, upward and leftward if every function takes earlier arguments. 
For instance, I was surprised how easy it was to write this function, 
but also how it ended up looking:

(defun basis-member<-neighborhood (x neighborhood items)
   "Given a function NEIGHBORHOOD defined over ITEMS, returns the basis
set member of X in ITEMS. As defined in Cupal2000"
		; 3. intersect resulting neighborhoods
   (reduce #'intersection
		; 2. map N over  filtered subset
	  (mapcar neighborhood
		; 1. filters Y to Y such that x exists in N(y)
		  (remove-if-not
		   #'(lambda (item)
		       (elementp x (funcall neighborhood item)))
		   items))))

If I'd written in an imperative style, the other would have been 1,2,3 
down the page. So I'm wondering: is this a fault in my style, b/c of my 
ignorance of a smoother idiom for this kind of computation, or if this 
is just something one gets used to?

When you read a heavily nested piece of lisp code, do you start inside 
and work outward or do you read it down the page?

thanks,
alexis

From: Eric Lavigne
Subject: Re: Should I read lisp "bacwards"
Date: 
Message-ID: <1142622539.997288.302030@i39g2000cwa.googlegroups.com>
> When I think of a process, I usually think of it is as progressing from
> the left to the right, or else from the top to the bottom. This is the
> conventional layout of graphs plotting change over time, of flowcharts,
> and of English writing.
>
> But when I write in a functional style in CL, the nesting of operators
> seems to force me to write "backwards"

Yes, functional and imperative styles tend to show things in opposite
orders, but which one is really backwards?

If you are following orders to carry out a task, you are acting
procedurally. You follow step 1, move on to step 2, etc.

What about when you are designing? The first thing you do is determine
what you are trying to accomplish (in other words, what happens last).
Then you figure out what process can reach that point (outermost
function), and what resources that process will require (arguments to
outermost function). Then you have a new set of design tasks to
address. How to obtain each of those resources...

As a programmer, I need to do both.

Sometimes I am a designer, trying to find a way to reach some end. In
that case I start with creating the outermost function and find
something to put in it.

Sometimes I am reading someone's code, trying to understand their
intent, then I start with their outermost function to see what they are
trying to accomplish.

Sometimes my compiler/computer has trouble trying to carry out my
orders. This might involve compiler-errors or optimization issues. In
that case, I will work from the inside out (procedurally) to see the
problem from the machine's point of view. I check if some step gets
carried out more often than necessary, or to test correctness I will
try some subset starting from the inside.

And sometimes I am trying to explain the program to FORTRAN
programmers, in which case I need to forget which direction designers
and readers should think in :-p
From: Kaz Kylheku
Subject: Re: Should I read lisp "bacwards"
Date: 
Message-ID: <1142626261.055028.281700@j52g2000cwj.googlegroups.com>
Alexis Gallagher wrote:
>
> If I'd written in an imperative style, the other would have been 1,2,3
> down the page.

This is just a matter of syntax. Functional filters can be "syntaxed"
to go left to right.

e.g. see the article with message ID

   ·······················@o13g2000cwo.googlegroups.com

Or: http://groups.google.ca/group/comp.lang.lisp/msg/68b08ac1c8ec4f20

> So I'm wondering: is this a fault in my style, b/c of my
> ignorance of a smoother idiom for this kind of computation, or if this
> is just something one gets used to?

Note that this "problem" exists in mathematical notations.

> When you read a heavily nested piece of lisp code, do you start inside
> and work outward or do you read it down the page?

You can't start inside, because you may be completely led astray. For
instance, when you get to the very outer expression, you may discover
that it's preceded by

  #+IGNORE

:)

The overall meaning of an expression is determined by its operator. So
evaluation actually begins on the outside. The operator determines how
the remaining arguments are evaluated. For those that are evaluated,
the process is applied recursively and so the bottom-up evaluation
happens as a result of popping out of that recursion.

If you see a (defclass (a b c) ...)  you'd be wrong to start looking at
the (a b c) as a call to operator A with arguments B and C, right?

You can read the code the same way the Lisp implementation does: left
to right, outside in, and maintan a "mental stack" of where you are.
From: Ken Tilton
Subject: Re: Should I read lisp "bacwards"
Date: 
Message-ID: <QWFSf.99$KY4.12@fe08.lga>
Alexis Gallagher wrote:
> Hi,
> 
> When I think of a process, I usually think of it is as progressing from 
> the left to the right, or else from the top to the bottom. This is the 
> conventional layout of graphs plotting change over time, of flowcharts, 
> and of English writing.
> 
> But when I write in a functional style in CL, the nesting of operators 
> seems to force me to write "backwards", in that the original value is 
> the innermost value, and successive processing steps expand outward -- 
> actually, upward and leftward if every function takes earlier arguments. 
> For instance, I was surprised how easy it was to write this function, 
> but also how it ended up looking:
> 
> (defun basis-member<-neighborhood (x neighborhood items)
>   "Given a function NEIGHBORHOOD defined over ITEMS, returns the basis
> set member of X in ITEMS. As defined in Cupal2000"
>         ; 3. intersect resulting neighborhoods
>   (reduce #'intersection
>         ; 2. map N over  filtered subset
>       (mapcar neighborhood
>         ; 1. filters Y to Y such that x exists in N(y)
>           (remove-if-not
>            #'(lambda (item)
>                (elementp x (funcall neighborhood item)))
>            items))))
> 
> If I'd written in an imperative style, the other would have been 1,2,3 
> down the page. So I'm wondering: is this a fault in my style, b/c of my 
> ignorance of a smoother idiom for this kind of computation, or if this 
> is just something one gets used to?
> 
> When you read a heavily nested piece of lisp code, do you start inside 
> and work outward or do you read it down the page?

Do you realize how much growth you demonstrate between your subject and 
this final question? :) You have gone from backwords to inside-out, and 
that last bit (a) is the correct way and (b) explains why functional 
beats imperative.

The functional approach reveals the tree structure of a computation. The 
imperative style explodes that natural assembly into so many lexically 
unrelated expressions and then lines them up on the floor, leaving the 
re-assembly ("oh, ok, X was assigne dup here, now it is being used here 
to compute Y") to the reader's skill at mental juggling.

So my answer would be to read Lisp top-down, where that is understood to 
mean a tree one examines in increasing detail only as needed. If I am 
looking at a function, I know from its name what it does. Why am I 
looking at the code? I want to see how it does it. OK, at the top it is 
a cond. I am interested in what are the cases. Oh, this case is my 
problem. I look at the processing for that. It is an IF. I have no 
problem with the true branch. Now let le look at the false branch. etc etc.

kt


-- 
Cells: http://common-lisp.net/project/cells/

"And I will know my song well before I start singing."  - Bob Dylan
From: John Thingstad
Subject: Re: Should I read lisp "bacwards"
Date: 
Message-ID: <op.s6kl9kkppqzri1@mjolner.upc.no>
On Fri, 17 Mar 2006 19:13:53 +0100, Alexis Gallagher  
<······@alexisgallagher.com> wrote:


>
> When you read a heavily nested piece of lisp code, do you start inside  
> and work outward or do you read it down the page?
>
> thanks,
> alexis

I follow the list from left to right and follow nested list's all the way  
in.
Remember that the function get's evaluated after the arguments. (so think  
(rest list))
Then I work my way outward.
Generally the formatting makes this fairly easy.

This is true of nested functions in all lanuages..
You just see more of them in Lisp.

-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
From: Pascal Bourguignon
Subject: Re: Should I read lisp "bacwards"
Date: 
Message-ID: <87slpgc10j.fsf@thalassa.informatimago.com>
Alexis Gallagher <······@alexisgallagher.com> writes:

> Hi,
>
> When I think of a process, I usually think of it is as progressing
> from the left to the right, or else from the top to the bottom. This
> is the conventional layout of graphs plotting change over time, of
> flowcharts, and of English writing.
>
> But when I write in a functional style in CL, the nesting of
> operators seems to force me to write "backwards", in that the
> original value is the innermost value, and successive processing
> steps expand outward --  actually, upward and leftward if every
> function takes earlier arguments. For instance, I was surprised how
> easy it was to write this function, but also how it ended up
> looking:
>
> (defun basis-member<-neighborhood (x neighborhood items)
>    "Given a function NEIGHBORHOOD defined over ITEMS, returns the basis
> set member of X in ITEMS. As defined in Cupal2000"
> 		; 3. intersect resulting neighborhoods
>    (reduce #'intersection
> 		; 2. map N over  filtered subset
> 	  (mapcar neighborhood
> 		; 1. filters Y to Y such that x exists in N(y)
> 		  (remove-if-not
> 		   #'(lambda (item)
> 		       (elementp x (funcall neighborhood item)))
> 		   items))))
>
> If I'd written in an imperative style, the other would have been 1,2,3
> down the page. So I'm wondering: is this a fault in my style, b/c of
> my ignorance of a smoother idiom for this kind of computation, or if
> this is just something one gets used to?

If you have a lot of these structures and they're really bothering
you, you can do something about it with macros!

See:      http://paste.lisp.org/display/17251#5

You could write:

(defun basis-member<-neighborhood (x neighborhood items)
    "Given a function NEIGHBORHOOD defined over ITEMS, returns the basis
 set member of X in ITEMS. As defined in Cupal2000"
  (functional-pipe
    (lambda (item) (elementp x (funcall neighborhood item)))
    (remove-if-not * items)
    (mapcar neighborhood *)
    (reduce (function intersection) *)))

Or perhaps the first form in the functional-pipe would be:
  (remove-if-not (lambda (item) (elementp x (funcall neighborhood item))) items)
but you see the point.

In each step of the functional-pipe, * refers to the result of the
previous form, ** of the previous previous form, and *** of the
previous previous previous form, just like in the REPL, so you can
build functional-pipes interactively at the REPL, and just
copy-and-paste them to the source.



> When you read a heavily nested piece of lisp code, do you start inside
> and work outward or do you read it down the page?

Yes.  It's called bottom-up interactive development :-)

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

"You cannot really appreciate Dilbert unless you read it in the
original Klingon"
From: Alexis Gallagher
Subject: Re: Should I read lisp "bacwards"
Date: 
Message-ID: <dvrn31$t6i$1@news.ox.ac.uk>
Thanks to everyone for their comments on the right direction to read 
lisp, especially Pascal and Kaz for pointing out their macros for 
reversing the "backwardsness".

In retrospect, I think my example was a bad one, since it is pretty 
naturally read outside-in: you take the intersection of the 
neighborhoods of the points that are in X's neighborhood. But I can 
imagine problems that are more easily read inside-out (or "backwards" of 
the lisp order) -- basically, any process where you are building 
something up through accretion. For instance, most people probably 
wouldn't like cooking recipes that were written as

(bake (insert (shape-to-tin (knead (mix (and flour water egg))))
    	      (mix (fry (and onions garlic)
                    (chop spinach)
                    (crumble feta))))

(Although to be honest I think I'd prefer this, but then I'm eccentric.)

The fact that folks already had already written macros to restore a 
'procedural' order; that the normal style of incremental development on 
the repl involves building up a function inside-out, not vice-versa; 
that the repl supports this with the * symbols, which are very much like 
pronouns -- all of these things suggest to me this direction feels more 
natural sometimes.

But the fact that lisp can reverse itself with macros is very cool, and 
definitely complicates my thinking about how syntax reflects a 
functional vs. imperative style, and what kind of local variables should 
"count" as nonfunctional.

alexis

Pascal Bourguignon wrote:
> Alexis Gallagher <······@alexisgallagher.com> writes:
> 
>> Hi,
>>
>> When I think of a process, I usually think of it is as progressing
>> from the left to the right, or else from the top to the bottom. This
>> is the conventional layout of graphs plotting change over time, of
>> flowcharts, and of English writing.
>>
>> But when I write in a functional style in CL, the nesting of
>> operators seems to force me to write "backwards", in that the
>> original value is the innermost value, and successive processing
>> steps expand outward --  actually, upward and leftward if every
>> function takes earlier arguments. For instance, I was surprised how
>> easy it was to write this function, but also how it ended up
>> looking:
>>
>> (defun basis-member<-neighborhood (x neighborhood items)
>>    "Given a function NEIGHBORHOOD defined over ITEMS, returns the basis
>> set member of X in ITEMS. As defined in Cupal2000"
>> 		; 3. intersect resulting neighborhoods
>>    (reduce #'intersection
>> 		; 2. map N over  filtered subset
>> 	  (mapcar neighborhood
>> 		; 1. filters Y to Y such that x exists in N(y)
>> 		  (remove-if-not
>> 		   #'(lambda (item)
>> 		       (elementp x (funcall neighborhood item)))
>> 		   items))))
>>
>> If I'd written in an imperative style, the other would have been 1,2,3
>> down the page. So I'm wondering: is this a fault in my style, b/c of
>> my ignorance of a smoother idiom for this kind of computation, or if
>> this is just something one gets used to?
> 
> If you have a lot of these structures and they're really bothering
> you, you can do something about it with macros!
> 
> See:      http://paste.lisp.org/display/17251#5
> 
> You could write:
> 
> (defun basis-member<-neighborhood (x neighborhood items)
>     "Given a function NEIGHBORHOOD defined over ITEMS, returns the basis
>  set member of X in ITEMS. As defined in Cupal2000"
>   (functional-pipe
>     (lambda (item) (elementp x (funcall neighborhood item)))
>     (remove-if-not * items)
>     (mapcar neighborhood *)
>     (reduce (function intersection) *)))
> 
> Or perhaps the first form in the functional-pipe would be:
>   (remove-if-not (lambda (item) (elementp x (funcall neighborhood item))) items)
> but you see the point.
> 
> In each step of the functional-pipe, * refers to the result of the
> previous form, ** of the previous previous form, and *** of the
> previous previous previous form, just like in the REPL, so you can
> build functional-pipes interactively at the REPL, and just
> copy-and-paste them to the source.
> 
> 
> 
>> When you read a heavily nested piece of lisp code, do you start inside
>> and work outward or do you read it down the page?
> 
> Yes.  It's called bottom-up interactive development :-)
> 
From: Mikalai
Subject: Re: Should I read lisp "bacwards"
Date: 
Message-ID: <1142710623.542056.35180@i40g2000cwc.googlegroups.com>
Alexis Gallagher wrote:

> Hi,
>
> When I think of a process, I usually think of it is as progressing from
> the left to the right, or else from the top to the bottom. This is the
> conventional layout of graphs plotting change over time, of flowcharts,
> and of English writing.
>
> But when I write in a functional style in CL, the nesting of operators
> seems to force me to write "backwards", in that the original value is
> the innermost value, and successive processing steps expand outward --
> actually, upward and leftward if every function takes earlier arguments.
> For instance, I was surprised how easy it was to write this function,
> but also how it ended up looking:
>
> (defun basis-member<-neighborhood (x neighborhood items)
>    "Given a function NEIGHBORHOOD defined over ITEMS, returns the basis
> set member of X in ITEMS. As defined in Cupal2000"
> 		; 3. intersect resulting neighborhoods
>    (reduce #'intersection
> 		; 2. map N over  filtered subset
> 	  (mapcar neighborhood
> 		; 1. filters Y to Y such that x exists in N(y)
> 		  (remove-if-not
> 		   #'(lambda (item)
> 		       (elementp x (funcall neighborhood item)))
> 		   items))))
>
> If I'd written in an imperative style, the other would have been 1,2,3
> down the page. So I'm wondering: is this a fault in my style, b/c of my
> ignorance of a smoother idiom for this kind of computation, or if this
> is just something one gets used to?
>
> When you read a heavily nested piece of lisp code, do you start inside
> and work outward or do you read it down the page?
>
> thanks,
> alexis
You've got branches of code. Each branch can be thought to be a
function of some sort.
Functions are good in way, that they are black boxes, i.e. you worry
only about what is done by a function, not how.
The same should be true with a branch of a code. Look at it's begining,
and it should tell you, like a name of a function, what it'll do. You
go and read all smaller inner branches, only if you want to know, how
inner things are done.
That's an ideal, when you read less to get *relevant* information. Any
ideal is open to abuse, though.
From: Aaron Brown
Subject: Re: Should I read lisp "bacwards"
Date: 
Message-ID: <1143054299.927774.36990@g10g2000cwb.googlegroups.com>
Alexis Gallagher wrote:

> But when I write in a functional style in CL, the nesting
> of operators seems to force me to write "backwards", in
> that the original value is the innermost value, and
> successive processing steps expand outward [....]

You might find it interesting to read section 3.2 of Paul
Graham's "On Lisp" [1] titled "Imperative Outside-In".

> The trick is to realize that an imperative program is a
> functional program turned inside-out. To find the
> functional program implicit in our imperative one, we just
> turn it outside-in.

[1] http://paulgraham.com/onlisptext.html

-- 
Aaron