[racket] "lab notebook on learning process" (was: Re: Macros baffle me)

From: Artyom Kazak (yom at artyom.me)
Date: Mon May 5 03:05:31 EDT 2014

On Mon 05 May 2014 06:05:30 AM MSK, Neil Van Dyke wrote:
 > A wise person observed, "any publicity is good publicity", so, on second
 > thought, I suppose it would probably be bad of me to discourage the lab
 > notebook of learning process.
 >
 > I've invited him to the email list, and I hope he sticks with Racket 
for a
 > while, and keeps blogging about Racket as he learns more.

And here I am (and actually has been lurking here for a week).
Sorry for a somewhat long message.

First of all: I really hope that people won't get dissuaded from learning
Racket after seeing some posts written by a person who genuinely enjoys
learning Racket. It'd be very unfortunate for me (to find out that I'm that
bad at expressing positive thoughts), as well as for them (being turned away
from such a nice language, tsk).

 > I had a painful backseat driver impulse, but I could not grab the 
wheel or
 > slam the brakes, and my screams could not be heard.  Maybe a horror movie
 > audience dramatic irony effect, like when the characters say, "Uh oh,
 > something odd is going on; let's split up!", and you see two of them pair
 > off together to do something immoral in the genre, but the cheese-grater
 > killer is waiting for them behind the door.

Gosh. I'd appreciate more details on what caused such a reaction (apart from
the brain dump format, of course, if it's the case). (But thanks for trying
to make the tone milder in the e-mail you've sent to me.)

 > Maybe someone should invite the blog writer to suspend the public lab
 > notebook, use the email list for questions, and then do a good blog post
 > ("A Haskelletorian Perspective on Racket") once they have a better
 > understanding?

Unfortunately, I've yet to see a good, useful, interesting or at least
entertaining blog post of such kind.

Now, here are some replies to Matthias's “comments on comments” (which I saw
only now, and wish I had seen earlier):

 > ?? I don't get the "Uniform syntax is harder to read" comment.
 > More highlighting, hmph?

I would personally be delighted if I heard a tiny bell sound whenever I look
at a function declaration, but highlighting would do too, as well as line
noise. Simplest example:

     > (cond
        ((positive? -5) (error "doesn't get here"))
        ((zero? -5) (error "doesn't get here, either"))
        ((positive? 5) 'here))

is (sli-ightly) harder to read than

     > (cond
        [(positive? -5) (error "doesn't get here")]
        [(zero? -5) (error "doesn't get here, either")]
        [(positive? 5) 'here])

which is harder to read than

     > (cond
        [(positive? -5)  (error "doesn't get here")]
        [(zero? -5)      (error "doesn't get here, either")]
        [(positive? 5)   'here])

which, in its turn, would've been harder to read (if the example wasn't so
simple) than

     > (cond
        [(positive? -5) => (error "doesn't get here")]
        [(zero? -5)     => (error "doesn't get here, either")]
        [(positive? 5)  => 'here])

(yes, I know that `=>` exists but is used for another purpose). I completely
understand that uniform syntax has its benefits, but I imagine there 
could be
ways to make it less uniform-*looking* without having to compromise.
DrRacket's feature which changes colors based on depth of nested brackets is
awesome at the first glance, but somewhat unusable at every glance after
that.

 > He wants an Arc-style lambda function. Hmph.

Does it mean that I'll get an Arc-style lambda function eventually, or that
I'll get an explanation why it's a bad ide— wait, nevermind, I can get
whatever I want, 'cause it's Racket. Mwa-ha-ha.

(I'd still welcome an explanation, tho.)

 > ?? How did the kid get (apply and ...) to work? Was I asleep?

Ouch. Yeah, right, it doesn't work. (The kid had checked that `apply +`
works, and that `and` works, but hadn't noticed that `and` wasn't 
*exactly* a
polyvariadic version of `&&` from C. So, I'll correct it tomorrow.)

 > He doesn't know what type safety is. I understand that C++ers don't get
 > it. Why do Haskellians don't get it?

I could argue that there are other shades of “type safety” besides “won't
attempt to make spaghetti out of your data at runtime”, but since the
definition on Wikipedia doesn't agree with me, I've updated the post 
instead.

 > People want overloading. (< "hello" "hello world") should work. Hmph.

It's more like people want to know why arbitrary restrictions apply to them
(or at least be told that it's a historical accident).

 > Show
 >
 > (for ((f (list f1 f2 f3 f4)))
 >  (time (f 10000)))
 >
 > early?

Definitely.

 > Why does he think "Performance sucks"?

Because here's the list of things that are slow: making a hundred thousand
calls to GMP, printing a string, and DrRacket itself, which is presumably
written in Racket.

(I mean, DrRacket's garbage collection – which happens every now and 
then, by
the way, according to the indicator in bottom right corner – causes delays
ranging from 2 to 5 seconds. That's not nice.)

 > What is this about:
 >
 > > "Support for functional paradigm is somewhere in the middle. Everything
 > > needed is there, but it's not very convenient to use. (I expect to
 > > stumble upon goodies/fp or haskell-racket module one day, but for now
 > > I won't be looking for it – I need to understand Racket's main paradigm
 > > before allowing myself to consciously deviate from it.)"
 >
 > I am thinking of Racket as FP.

Here's an example from Racket site's front page:

     #lang racket
     ;; Finds Racket sources in all subdirs
     (for ([path (in-directory)]
           #:when (regexp-match? #rx"[.]rkt$" path))
       (printf "source file: ~a\n" path))

It's a for-loop with a `skip` keyword. In Haskell it'd be

     mapM_ (printf "source file: %s\n") $
       filter (regexpMatch "[.]rkt$") inDirectory

Not saying one is better over the other, but they're not quite the same
either. Also, I know that you can write as imperatively in Haskell and
functionally in Racket as you wish; the question isn't about what is
possible, but what is more comfortable and idiomatic.

Racket relies on internal defines (or so I'm told), Haskell uses `where`s
extensively. Function composition is `<<` in F#, `.` in Haskell, and
`compose` in Racket (which naturally led to things such as `negate` from
racket/function – programmers still optimise for common cases). Instead of
pipelines there are `let`s and nested brackets. Lack of currying-by-default
led to `add1` and `sub1` (common case optimisation again). Implementing
control structures as macros means that you can't conveniently compose 
them –
and this shows in standard library (look at `for/and`, `for/or`, `for/sum`,
`for/product`, `for/first`, `for/last`, `for/fold`...); or I could bring up
`time`, which can be used with `for` but can't – with `map`.

 > This
 >
 > > "Given that reading every chapter of TRG raises lots of questions and
 > > provokes endless tinkering with not-quite-related concepts, I'll be
 > > happy if I manage to read as much as chapter 2.4."
 >
 > means the Guide is the wrong kind of introduction for a functional
 > Haskellian.

I should've made the accent on “reading” clearer – “given that the 
process of
reading raises lots of questions and provokes tinkering, I shouldn't expect
to spend more time reading that tinkering”. The Guide is a nice 
introduction,
tho I wish there was a warning along the lines of “don't forget:
call-by-value! call-by-value!” somewhere early on.

 > Some of our error messages are, well, real-world error messages. Like all
 > compilers, they assume complete knowledge of the languages so when a 
novice
 > makes a mistake, he gets, well, nothing out of it.

And again, an admission of my own impatience and unwillingness to learn the
basics before going for... well, less basic basics seems to have been taken
for a criticism of the language. Hm, I am tempted to make a poll at the end
of third part of this “lab notebook” to see how level of concern that I'm
“dissuading people from learning Racket” is correlated with reader's
knowledge of Racket.

 > So do we need to explain why literals in syntax-parse must be 
pre-bound? I
 > have run into this, read up on it, said "duh", and moved on.

Ouch #2. Should've googled it instead of giving up on a mystery so easily.

(Can't help but wonder if mine “There's probably some good reason for 
it, but
I've no idea what it could be.” has been taken as sarcasm.)

 > In general, how much rationale should be given for features? Do we need a
 > more hyper-linked document organization?

It probably varies from person to person – some just want to know how to do
stuff, some want rationale. Personally I want all the rationale there 
is, but
I'm just one data point; we could ask tutorial/book writers for better
statistics.


Posted on the users mailing list.