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 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 >>> (foo 1<> 2) >>> (bar y<>)) >>> >>> that expands to (bar y (foo 1 x 2)). (The reason that clojure has two >>> other forms (`-?>' and `-?>>') is something that is related to the >>> below, so I'll skip it for now.) >>> >>> The next thing that I tried is to contrast this with `nest'. The >>> difference between them is that while both lead to a simpler syntax >>> for nested expressions, they do the nesting in different directions, >>> where (*very* roughly speaking) `->' nests things downwards and `nest' >>> nests them upwards: >>> >>> (-> X Y) nests X into Y >>> (nest X Y) nests Y into X >>> >>> or more generally: >>> >>> (-> X Y0 Y ...) nests X into Y0 and nests the results with Y ... >>> (nest X Y ...) nests the result of nesting Y ... into X >>> >>> So I tried to see if I can come up with something that can kill both >>> birds -- which is why I started with the above example: >>> >>> (let ([str (string-trim (substring "foo bar baz" 3 8))]) >>> (and (regexp-match? #rx"^[a-z].*[a-z]$" str) >>> (string-append "*" str "*"))) >>> >>> 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. >>> >>> There are still some problems with this though. One problem is that >>> it can be ambiguous -- for example, I had this as one experiement: >>> >>> (○ (let ([str "foo bar baz"]) ↓) >>> (substring str 3 8) >>> (string-trim ↑) >>> (string-append "*" ↑ "*")) >>> >>> where the upward nesting could happen first -- this ambiguity is easy >>> to resolve if there's a simple rule for merging the first two >>> expressions repeatedly, stopping with an error if there's not exactly >>> one down arrow in the first or one up arrow in the second; and >>> finishing when there's one expression (throwing an error if it still >>> has arrows). Using this, the expansion of the above goes with these >>> steps: >>> >>> ... -> >>> (○ (let ([str "foo bar baz"]) (substring str 3 8)) >>> (string-trim ↑) >>> (string-append "*" ↑ "*")) >>> -> >>> (○ (string-trim (let ([str "foo bar baz"]) (substring str 3 8))) >>> (string-append "*" ↑ "*")) >>> -> >>> (○ (string-append "*" (string-trim (let ([str "foo bar baz"]) (substring >>> str 3 8))) "*")) >>> -> >>> (string-trim (let ([str "foo bar baz"]) (substring str 3 8))) >>> >>> It's also unclear if this is generic enough though. I vaguely suspect >>> that there might be cases where you want arrows from multiple places >>> in the form which makes this a kind of a literate-programming-like >>> tool for micro-level code organization (and yes, I intensely dislike >>> LP, so that's would be a bad thing). In addition, something like this >>> should really have simple rules for how it works, otherwise it not >>> something that anyone would want to use or read. >>> >>> BTW, I take the `nest' experiment as an example: the form itself is, >>> IMO, perfectly fine, but it suffered from having too much parentheses, >>> which makes it hard to use. One thing I like in the above is that the >>> explicit arrow markers make it much easier to read -- I think that >>> this is also an advantage over the clojure threading forms, where you >>> see a form like (take 10) and you have to look back at the arrow kind >>> that was used to know what this really is. >>> >>> In any case, any thoughts about this? I'd especially appreciate >>> little code layout horrors you might encounter, to see how such a form >>> can deal with them. Feel free to reply off-list to avoid premature >>> bike-shedding. (I'm *not* going to commit anything -- this is just >>> trying to roll around the idea to see if there's any point in doing >>> something like this. *If* there is enough interest, then I'll post a >>> concrete suggestion when I have one.) >>> >>> -- >>> ((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 >> >> >> >> > -- Jay McCarthy <j...@cs.byu.edu> Assistant Professor / Brigham Young University http://faculty.cs.byu.edu/~jay "The glory of God is Intelligence" - D&C 93 _________________________ Racket Developers list: http://lists.racket-lang.org/dev