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)