Re: [racket-dev] Code micro-level organization

2012-06-01 Thread Eli Barzilay
[Combined reply]

Two days ago, Jon Rafkind wrote:
 On 05/30/2012 04:07 PM, Eli Barzilay wrote:
 
  Having expressions come from the bottom, using the down arrow, seems
  sort of wierd.
  Here's a concrete example:
 
(○ (let ([x 10]) ↓)
   (for ([i (in-range x)]) ↓)
   (for ([j (in-range i)]) ↓)
   ...etc...)
 
  Do you have a concrete suggestion for doing that?
 
 Well in this case its easy, just remove the closing ) from each of
 the lines so the next line is nested in the right place.

Yes, but then you get the drift which is one of the things that it's
trying to eliminate.  (It's true that strictly speaking you don't need
that -- but the premise of this whole thing is a tool for structuring
code for easier reading  writing, like many other unnecessary tools
(which are most of the language, of course).)


 If you were going to use the down arrow in a different position,
 like
 
 (for ([i ↓]) ..blah..)
 (let ...)
 
 I think things would get out of hand quickly because the physical
 gap between the for expression and the let expression could get
 quite large.

The use case for these things would be to simplify the code in a way
that puts each point of focus on consecutive lines.  To demonstrate
with just the above, you *could* do something like this:

  ;; print a table of square roots
  (○ (for ([i ↓]) (printf ~s² = ~s\n (* i i)))
 (in-range 0 100))

But that doesn't make much sense, since using the range expression
inside the for loop is more readable.  This is not different from this
weird way to write this code:

  (let ([f (λ (x) (for ([i ↓]) (printf ~s² = ~s\n (* i i])
(f (in-range 0 100)))

Cases where you would use that is when that expression is that main
focus of the code, for example

  (○ (for/list ([i ↓]) (* i i))
 (in-sequences ↓ (in-range 10))
 (stop-after ↓ zero?)
 (in-naturals ↓)
 (fib 10))


 I mean I hope I'm not trivializing your issue, do you have a
 different example?

Any example where that main focus is not the last expression, like the
above.  Here's a different one:

  (○ (for ([i 10]) ↓ (newline))
 (for ([j 10]) ↓)
 (printf  ~s (* i j)))


Yesterday, Neil Toronto wrote:
 
 It seems like `↑' is another way to not name expressions (i.e. a
 pointless style :D),

(I can't parse that.)


 and `↓' is handled just fine by internal definitions. This is
 equivalent, currently defined, has less nesting, and avoids a
 rename:
 
 (define orig-str foo bar baz)
 (define sub (substring orig-str 3 8))
 (define str (string-trim sub))
 (define m (regexp-match? #rx^[a-z].*[a-z]$ str))
 (and m (string-append * str *))

Yes, I mentioned this hack explicitly.  Maybe it will help if I
clarify why it's a hack: it forces you to choose names where you don't
need any.  For example, see how the names you chose are bad?  -- `str'
doesn't make sense in such a line, so it would become something like
`trimmed-string', and `m' is a buggy convention since it's usually
used with the results of matching so it should be something like
`is-word?'.  And now names are repeating information that is already
clearly visible in the code, which makes me dislike it even more than
the hugarian naming convention.

Another way to deal with this is with a generic base for the name
(which is what I remember Jay posting at some point), as in

  (define x1 ...)
  (define x2 ...)
  ...

This is also a pretty bad way to do that, since the names are
meaningless labels so the machine should be dealing with them, not me.
(Note in particular how adding new intermediate expressions requires
shifting names -- in a way that can eventually lead to a convention of
`x10', `x20', etc so it's easier to debug...)

But a more high-level point is that I *am* already using a highlevel
language where names are not always necessary, and I'd like to keep
that freedom without sacrificing code readability.  The argument that
is usually made for your example is I find that being forced to use
descriptive names help -- that can obviously be true in some cases,
but I dislike requiring it.  A technical problem with this argument is
that it omits the fact that you really need *unique* names; the
high-level problem with the argument is that it's *exactly* the same
argument that people have been using for ages as an excuse to not
having some kind of `lambda' in their languages.


 A `define*' form like Jay (and I) want would make these kinds of
 things less error-prone and allow names to be reused:
 [...]

Right, and it looks like there's strong opposition to that, which is
why I'm trying to find something that can be done.  What I'm
suggesting is not a complete replacement -- one thing it doesn't do is
use different names for farther references (and that's why I asked for
examples), and another difference is that I'm talking about a macro so
you won't be able to use more than one `↑' (or whatever is a good name
for it).  The idea is to make many cases that seem redundantly complex
easier 

Re: [racket-dev] Code micro-level organization

2012-05-31 Thread Neil Toronto

On 05/30/2012 03:40 PM, Eli Barzilay wrote:

Now, lets imagine that instead of a simple `' hole, there are two
kinds of holes with an up or a down direction -- this leads to
this kind of a syntax:

   (○ foo bar baz
  (substring ↑ 3 8)
  (string-trim ↑)
  (let ([str ↑]) ↓)
  (and (regexp-match? #rx^[a-z].*[a-z]$ str) ↓)
  (string-append * str *))

where you can read `↑' as the above and `↓' as the below.


It seems like `↑' is another way to not name expressions (i.e. a 
pointless style :D), and `↓' is handled just fine by internal 
definitions. This is equivalent, currently defined, has less nesting, 
and avoids a rename:


   (define orig-str foo bar baz)
   (define sub (substring orig-str 3 8))
   (define str (string-trim sub))
   (define m (regexp-match? #rx^[a-z].*[a-z]$ str))
   (and m (string-append * str *))

A `define*' form like Jay (and I) want would make these kinds of things 
less error-prone and allow names to be reused:


   (define* ↑ foo bar baz)
   (define* ↑ (substring ↑ 3 8))
   (define* str (string-trim ↑))
   (define* ↑ (regexp-match? #rx^[a-z].*[a-z]$ str))
   (and ↑ (string-append * str *))

It's still pretty wordy, though. Even if I had `define*' I'd be tempted 
to go with my current favorite idiom, which trades wordiness for a 
nesting level:


(let* ([↑foo bar baz]
   [↑(substring ↑ 3 8)]
   [str  (string-trim ↑)]
   [↑(regexp-match? #rx^[a-z].*[a-z]$ str)])
  (and ↑ (string-append * str *)))

I occasionally get annoyed by how deeply these can get nested. I feel 
your pain, man.


Neil ⊥
_
 Racket Developers list:
 http://lists.racket-lang.org/dev


Re: [racket-dev] Code micro-level organization

2012-05-31 Thread Laurent
How about a define* that is exactly like let* without the additional
indentation level?
E.g.:

(define*
[↑ foo bar baz]
[↑ (substring ↑ 3 8)]
[str (string-trim ↑)]
[↑ (regexp-match? #rx^[a-z].*[a-z]$ str)])
(and ↑ (string-append * str *))

Laurent

Le 31 mai 2012 19:04, Neil Toronto neil.toro...@gmail.com a écrit :

 On 05/30/2012 03:40 PM, Eli Barzilay wrote:

 Now, lets imagine that instead of a simple `' hole, there are two
 kinds of holes with an up or a down direction -- this leads to
 this kind of a syntax:

   (○ foo bar baz
  (substring ↑ 3 8)
  (string-trim ↑)
  (let ([str ↑]) ↓)
  (and (regexp-match? #rx^[a-z].*[a-z]$ str) ↓)
  (string-append * str *))

 where you can read `↑' as the above and `↓' as the below.


 It seems like `↑' is another way to not name expressions (i.e. a
pointless style :D), and `↓' is handled just fine by internal
definitions. This is equivalent, currently defined, has less nesting, and
avoids a rename:

   (define orig-str foo bar baz)
   (define sub (substring orig-str 3 8))
   (define str (string-trim sub))
   (define m (regexp-match? #rx^[a-z].*[a-z]$ str))
   (and m (string-append * str *))

 A `define*' form like Jay (and I) want would make these kinds of things
less error-prone and allow names to be reused:

   (define* ↑ foo bar baz)
   (define* ↑ (substring ↑ 3 8))
   (define* str (string-trim ↑))
   (define* ↑ (regexp-match? #rx^[a-z].*[a-z]$ str))
   (and ↑ (string-append * str *))

 It's still pretty wordy, though. Even if I had `define*' I'd be tempted
to go with my current favorite idiom, which trades wordiness for a nesting
level:

 (let* ([↑foo bar baz]
   [↑(substring ↑ 3 8)]
   [str  (string-trim ↑)]
   [↑(regexp-match? #rx^[a-z].*[a-z]$ str)])
  (and ↑ (string-append * str *)))

 I occasionally get annoyed by how deeply these can get nested. I feel
your pain, man.

 Neil ⊥

 _
  Racket Developers list:
  http://lists.racket-lang.org/dev
_
  Racket Developers list:
  http://lists.racket-lang.org/dev


Re: [racket-dev] Code micro-level organization

2012-05-31 Thread Laurent
(sorry for the bad indentation, writing s-exps on a phone predictive
keyboard is painful...)
Le 31 mai 2012 19:21, Laurent laurent.ors...@gmail.com a écrit :

 How about a define* that is exactly like let* without the additional
 indentation level?
 E.g.:

 (define*
 [↑ foo bar baz]
 [↑ (substring ↑ 3 8)]
 [str (string-trim ↑)]
 [↑ (regexp-match? #rx^[a-z].*[a-z]$ str)])
 (and ↑ (string-append * str *))

 Laurent

 Le 31 mai 2012 19:04, Neil Toronto neil.toro...@gmail.com a écrit :
 
  On 05/30/2012 03:40 PM, Eli Barzilay wrote:
 
  Now, lets imagine that instead of a simple `' hole, there are two
  kinds of holes with an up or a down direction -- this leads to
  this kind of a syntax:
 
(○ foo bar baz
   (substring ↑ 3 8)
   (string-trim ↑)
   (let ([str ↑]) ↓)
   (and (regexp-match? #rx^[a-z].*[a-z]$ str) ↓)
   (string-append * str *))
 
  where you can read `↑' as the above and `↓' as the below.
 
 
  It seems like `↑' is another way to not name expressions (i.e. a
 pointless style :D), and `↓' is handled just fine by internal
 definitions. This is equivalent, currently defined, has less nesting, and
 avoids a rename:
 
(define orig-str foo bar baz)
(define sub (substring orig-str 3 8))
(define str (string-trim sub))
(define m (regexp-match? #rx^[a-z].*[a-z]$ str))
(and m (string-append * str *))
 
  A `define*' form like Jay (and I) want would make these kinds of things
 less error-prone and allow names to be reused:
 
(define* ↑ foo bar baz)
(define* ↑ (substring ↑ 3 8))
(define* str (string-trim ↑))
(define* ↑ (regexp-match? #rx^[a-z].*[a-z]$ str))
(and ↑ (string-append * str *))
 
  It's still pretty wordy, though. Even if I had `define*' I'd be tempted
 to go with my current favorite idiom, which trades wordiness for a nesting
 level:
 
  (let* ([↑foo bar baz]
[↑(substring ↑ 3 8)]
[str  (string-trim ↑)]
[↑(regexp-match? #rx^[a-z].*[a-z]$ str)])
   (and ↑ (string-append * str *)))
 
  I occasionally get annoyed by how deeply these can get nested. I feel
 your pain, man.
 
  Neil ⊥
 
  _
   Racket Developers list:
   http://lists.racket-lang.org/dev

_
  Racket Developers list:
  http://lists.racket-lang.org/dev


Re: [racket-dev] Code micro-level organization

2012-05-31 Thread Jay McCarthy
I was clapping through the majority of your email.

I want define* so bad.

I use compose and curry a lot (even though I know their performance
problems) because it don't have to name things.

I like the idea of the - thing with the down and up arrows. I see a
value in both arrows. I also like Jon's suggestion of a 'last' id...
although I'd also want 0 through n or something to refer to so
many spots back.

Jay

On Wed, May 30, 2012 at 3:40 PM, Eli Barzilay e...@barzilay.org wrote:
 I'm going to ramble a bit about organizing code, trying to look for an
 idea for a good solution -- so spread a few kgs of salt over the
 following (if you care to read it).

 The problem that I'm talking about has several manifestations.  The
 most obvious one is code-drift towards the RHS.  A less obvious
 problem is how it's sometimes hard to read code.  To use a cooked up
 example:

  (let ([str (string-trim (substring foo bar baz 3 8))])
    (and (regexp-match? #rx^[a-z].*[a-z]$ str)
         (string-append * str *)))

 to read this, you start from the string literal, then read the
 `substring' expression, then `string-trim', then the `let' binding,
 then the `and' and finally the `string-append'[*].  To relate this to the
 above: besides the right-drift (which is of course very minor here),
 it takes time to internalize the rules of the language that leads to
 this, which is a problem for people new to functional programming with
 it's heavy use of nested function calls.  More than that, I think that
 it's also a problem for *experienced* hackers too -- to see what I
 mean, open up any random piece of code that deals with an area you're
 not familiar with, and try to read through it.  Personally, I often
 find myself in such situations reading the actual ordering as I go
 through the code, and that's fragile since I need to keep mental
 fingers at various locations in the code in question, sometimes even
 using my real fingers...

 You'd probably recognize that there's a whole bunch of tools that are
 trying to make things better.  A few random ones that I can think of
 are:

  * The new semantics  blessing for using `define' forms instead of
    `let' etc makes code easier to read and avoids some right-drift.

  * There's the need (which I recently talked to at NEU) for some kind
    of a `define*' form that can be used as a definition with a `let*'
    scope.  For those who weren't there, the summary of the issue is
    something that Jay once said -- that he sometimes uses
      (define x0 ...)
      (define x1 (... x0 ...))
      (define x2 (... x1 ...))
    because he wants to avoid a `let*'.

  * The old `scheme/nest' is a direct attempt to prevent drift for
    some kinds of nestings.

  * There's the related suggestion for extending the reader with
    something like `$' or `//' that closes the rest of the sexpr in
    its own set of parens.

  * Every once in a while there's a suggestion to invert conversion
    functions, eg, turn `string-number' into `number-string' so it
    reads out better.  In a similar direction, there are sometimes
    suggestions to use `compose' to make things more readable, as in
      ((compose f1 f2 f3 f4) x)
    vs
      (f1 (f2 (f3 (f4 x
    and the textual mess that the latter tends to end up as with real
    names.

  * srfi-2 defines an `and-let*' which is addressing a common pattern
    of interleaving nested `let's and `and's.  Actually, `cond' itself
    is addressing this kind of problem too, so add here various
    suggestions for extending `cond' with binders, anaphoric forms
    etc.

  * Recently, I looked at some clojure pages (to hunt for new
    extensions to `racket/list'), and I saw that they have a
    threading form using `-' that expresses nested function calls.
    See this here:
      http://clojuredocs.org/clojure_core/clojure.core/-%3E
    and note also the other three variants, `-' `-?' and `-?',

  * (The list goes on...)

 (One common theme in all of these is that they're tools that none of
 them are tools that are needed -- they're all just ways to make code
 look better.)

 I actually started thinking about this when I saw the clojure thing.
 The first thing that is limited about it is that it has four forms,
 where the reason for the `-' vs `-' split is to put the nesting in
 a different argument position.  To summarize (and IIUC):

  (- x
      (foo 1 2)
      (bar y))

 expands to

  (bar (foo x 1 2) y)

 whereas using a `-' would make it expand to

  (bar y (foo 1 2 x))

 Not only does it seem to me bad to have two bindings for this, we also
 have the usual problem of the order-defying `regexp-replace' where
 usually the action happens in the *middle* argument...  (Which is how
 it ends up being a common example in showing these problems, as
 happened recently.)

 In any case, this looks like an easy thing to fix by adding an
 explicit marker to the point where the nesting happens.  For example,
 imagine a form that looks like this:

  (○ x
     

Re: [racket-dev] Code micro-level organization

2012-05-31 Thread Ryan Culpepper

On 05/31/2012 02:54 PM, Jay McCarthy wrote:

I was clapping through the majority of your email.

I want define* so bad.


You can use define*; just put it inside of package-begin:

   (require racket/package)
   (package-begin
 (define* x 1)
 (define* x (+ 2 x))
 x)
  3

I don't think I like the idea of making the internal definition contexts 
of racket/base forms act like package-begin, though.


Ryan



I use compose and curry a lot (even though I know their performance
problems) because it don't have to name things.

I like the idea of the -  thing with the down and up arrows. I see a
value in both arrows. I also like Jon's suggestion of a 'last' id...
although I'd also want0  throughn  or something to refer to so
many spots back.

Jay

On Wed, May 30, 2012 at 3:40 PM, Eli Barzilaye...@barzilay.org  wrote:

I'm going to ramble a bit about organizing code, trying to look for an
idea for a good solution -- so spread a few kgs of salt over the
following (if you care to read it).

The problem that I'm talking about has several manifestations.  The
most obvious one is code-drift towards the RHS.  A less obvious
problem is how it's sometimes hard to read code.  To use a cooked up
example:

  (let ([str (string-trim (substring foo bar baz 3 8))])
(and (regexp-match? #rx^[a-z].*[a-z]$ str)
 (string-append * str *)))

to read this, you start from the string literal, then read the
`substring' expression, then `string-trim', then the `let' binding,
then the `and' and finally the `string-append'[*].  To relate this to the
above: besides the right-drift (which is of course very minor here),
it takes time to internalize the rules of the language that leads to
this, which is a problem for people new to functional programming with
it's heavy use of nested function calls.  More than that, I think that
it's also a problem for *experienced* hackers too -- to see what I
mean, open up any random piece of code that deals with an area you're
not familiar with, and try to read through it.  Personally, I often
find myself in such situations reading the actual ordering as I go
through the code, and that's fragile since I need to keep mental
fingers at various locations in the code in question, sometimes even
using my real fingers...

You'd probably recognize that there's a whole bunch of tools that are
trying to make things better.  A few random ones that I can think of
are:

  * The new semantics  blessing for using `define' forms instead of
`let' etc makes code easier to read and avoids some right-drift.

  * There's the need (which I recently talked to at NEU) for some kind
of a `define*' form that can be used as a definition with a `let*'
scope.  For those who weren't there, the summary of the issue is
something that Jay once said -- that he sometimes uses
  (define x0 ...)
  (define x1 (... x0 ...))
  (define x2 (... x1 ...))
because he wants to avoid a `let*'.

  * The old `scheme/nest' is a direct attempt to prevent drift for
some kinds of nestings.

  * There's the related suggestion for extending the reader with
something like `$' or `//' that closes the rest of the sexpr in
its own set of parens.

  * Every once in a while there's a suggestion to invert conversion
functions, eg, turn `string-number' into `number-string' so it
reads out better.  In a similar direction, there are sometimes
suggestions to use `compose' to make things more readable, as in
  ((compose f1 f2 f3 f4) x)
vs
  (f1 (f2 (f3 (f4 x
and the textual mess that the latter tends to end up as with real
names.

  * srfi-2 defines an `and-let*' which is addressing a common pattern
of interleaving nested `let's and `and's.  Actually, `cond' itself
is addressing this kind of problem too, so add here various
suggestions for extending `cond' with binders, anaphoric forms
etc.

  * Recently, I looked at some clojure pages (to hunt for new
extensions to `racket/list'), and I saw that they have a
threading form using `-' that expresses nested function calls.
See this here:
  http://clojuredocs.org/clojure_core/clojure.core/-%3E
and note also the other three variants, `-' `-?' and `-?',

  * (The list goes on...)

(One common theme in all of these is that they're tools that none of
them are tools that are needed -- they're all just ways to make code
look better.)

I actually started thinking about this when I saw the clojure thing.
The first thing that is limited about it is that it has four forms,
where the reason for the `-' vs `-' split is to put the nesting in
a different argument position.  To summarize (and IIUC):

  (-  x
  (foo 1 2)
  (bar y))

expands to

  (bar (foo x 1 2) y)

whereas using a `-' would make it expand to

  (bar y (foo 1 2 x))

Not only does it seem to me bad to have two bindings for this, we also
have the usual problem of the order-defying `regexp-replace' where
usually the action happens in 

Re: [racket-dev] Code micro-level organization

2012-05-31 Thread Jay McCarthy
I know about package-begin, it's just not worth it if I need to bring
in another require and add package-begin

Jay

On Thu, May 31, 2012 at 3:43 PM, Ryan Culpepper r...@cs.utah.edu wrote:
 On 05/31/2012 02:54 PM, Jay McCarthy wrote:

 I was clapping through the majority of your email.

 I want define* so bad.


 You can use define*; just put it inside of package-begin:

   (require racket/package)
   (package-begin
     (define* x 1)
     (define* x (+ 2 x))
     x)
  3

 I don't think I like the idea of making the internal definition contexts of
 racket/base forms act like package-begin, though.

 Ryan


 I use compose and curry a lot (even though I know their performance
 problems) because it don't have to name things.

 I like the idea of the -  thing with the down and up arrows. I see a
 value in both arrows. I also like Jon's suggestion of a 'last' id...
 although I'd also want0  throughn  or something to refer to so
 many spots back.

 Jay

 On Wed, May 30, 2012 at 3:40 PM, Eli Barzilaye...@barzilay.org  wrote:

 I'm going to ramble a bit about organizing code, trying to look for an
 idea for a good solution -- so spread a few kgs of salt over the
 following (if you care to read it).

 The problem that I'm talking about has several manifestations.  The
 most obvious one is code-drift towards the RHS.  A less obvious
 problem is how it's sometimes hard to read code.  To use a cooked up
 example:

  (let ([str (string-trim (substring foo bar baz 3 8))])
    (and (regexp-match? #rx^[a-z].*[a-z]$ str)
         (string-append * str *)))

 to read this, you start from the string literal, then read the
 `substring' expression, then `string-trim', then the `let' binding,
 then the `and' and finally the `string-append'[*].  To relate this to the
 above: besides the right-drift (which is of course very minor here),
 it takes time to internalize the rules of the language that leads to
 this, which is a problem for people new to functional programming with
 it's heavy use of nested function calls.  More than that, I think that
 it's also a problem for *experienced* hackers too -- to see what I
 mean, open up any random piece of code that deals with an area you're
 not familiar with, and try to read through it.  Personally, I often
 find myself in such situations reading the actual ordering as I go
 through the code, and that's fragile since I need to keep mental
 fingers at various locations in the code in question, sometimes even
 using my real fingers...

 You'd probably recognize that there's a whole bunch of tools that are
 trying to make things better.  A few random ones that I can think of
 are:

  * The new semantics  blessing for using `define' forms instead of

    `let' etc makes code easier to read and avoids some right-drift.

  * There's the need (which I recently talked to at NEU) for some kind
    of a `define*' form that can be used as a definition with a `let*'
    scope.  For those who weren't there, the summary of the issue is
    something that Jay once said -- that he sometimes uses
      (define x0 ...)
      (define x1 (... x0 ...))
      (define x2 (... x1 ...))
    because he wants to avoid a `let*'.

  * The old `scheme/nest' is a direct attempt to prevent drift for
    some kinds of nestings.

  * There's the related suggestion for extending the reader with
    something like `$' or `//' that closes the rest of the sexpr in
    its own set of parens.

  * Every once in a while there's a suggestion to invert conversion
    functions, eg, turn `string-number' into `number-string' so it
    reads out better.  In a similar direction, there are sometimes
    suggestions to use `compose' to make things more readable, as in
      ((compose f1 f2 f3 f4) x)
    vs
      (f1 (f2 (f3 (f4 x
    and the textual mess that the latter tends to end up as with real
    names.

  * srfi-2 defines an `and-let*' which is addressing a common pattern
    of interleaving nested `let's and `and's.  Actually, `cond' itself
    is addressing this kind of problem too, so add here various
    suggestions for extending `cond' with binders, anaphoric forms
    etc.

  * Recently, I looked at some clojure pages (to hunt for new
    extensions to `racket/list'), and I saw that they have a
    threading form using `-' that expresses nested function calls.
    See this here:
      http://clojuredocs.org/clojure_core/clojure.core/-%3E
    and note also the other three variants, `-' `-?' and `-?',

  * (The list goes on...)

 (One common theme in all of these is that they're tools that none of
 them are tools that are needed -- they're all just ways to make code
 look better.)

 I actually started thinking about this when I saw the clojure thing.
 The first thing that is limited about it is that it has four forms,
 where the reason for the `-' vs `-' split is to put the nesting in
 a different argument position.  To summarize (and IIUC):

  (-  x
      (foo 1 2)
      (bar y))

 expands to

  (bar (foo x 1 2) y)

 

Re: [racket-dev] Code micro-level organization

2012-05-30 Thread Eli Barzilay
A few minutes ago, Jon Rafkind wrote:
 On 05/30/2012 03:40 PM, Eli Barzilay wrote:
  Now, lets imagine that instead of a simple `' hole, there are two
  kinds of holes with an up or a down direction -- this leads to
  this kind of a syntax:
 
(○ foo bar baz
   (substring ↑ 3 8)
   (string-trim ↑)
   (let ([str ↑]) ↓)
   (and (regexp-match? #rx^[a-z].*[a-z]$ str) ↓)
   (string-append * str *))
 
  where you can read `↑' as the above and `↓' as the below.  The
  thing that makes me excited about this is how you can read this as the 
  above [*] reading.
 
 Maybe a simpler proposal is just a 'last' identifier that is always
 bound to the previous expression?

That's basically the (improved) thing that you get in clojure, and the
problem is that it doesn't fit nesting in the other way, which is what
`nest' does.  Something that I forgot to fill in the previous post is
that this could be one reason why they have the `-?' and `-?'
forms: these things are dealing with conditional values, which is
something that you get with nesting that goes in the other direction.

(As for the identifier names, I think of them as the above and the
below, so maybe those are better names.)


 Having expressions come from the bottom, using the down arrow, seems
 sort of wierd.

Here's a concrete example:

  (○ (let ([x 10]) ↓)
 (for ([i (in-range x)]) ↓)
 (for ([j (in-range i)]) ↓)
 ...etc...)

Do you have a concrete suggestion for doing that?

-- 
  ((lambda (x) (x x)) (lambda (x) (x x)))  Eli Barzilay:
http://barzilay.org/   Maze is Life!

_
  Racket Developers list:
  http://lists.racket-lang.org/dev


Re: [racket-dev] Code micro-level organization

2012-05-30 Thread Jon Rafkind
On 05/30/2012 04:07 PM, Eli Barzilay wrote:

 Having expressions come from the bottom, using the down arrow, seems
 sort of wierd.
 Here's a concrete example:

   (○ (let ([x 10]) ↓)
  (for ([i (in-range x)]) ↓)
  (for ([j (in-range i)]) ↓)
  ...etc...)

 Do you have a concrete suggestion for doing that?


Well in this case its easy, just remove the closing ) from each of the lines so 
the next line is nested in the right place. If you were going to use the down 
arrow in a different position, like

(for ([i ↓]) ..blah..)
(let ...)

I think things would get out of hand quickly because the physical gap between 
the for expression and the let expression could get quite large.

I mean I hope I'm not trivializing your issue, do you have a different example?
_
  Racket Developers list:
  http://lists.racket-lang.org/dev