[HN Gopher] Why learn Racket? A student's perspective
       ___________________________________________________________________
        
       Why learn Racket? A student's perspective
        
       Author : hydroxideOH-
       Score  : 72 points
       Date   : 2022-02-20 01:41 UTC (1 days ago)
        
 (HTM) web link (www.micahcantor.com)
 (TXT) w3m dump (www.micahcantor.com)
        
       | spdegabrielle wrote:
       | Nice write up.
       | 
       | You mention SICP, but I'm wondering if you are using HTDP
       | http://htdp.org/ ?
       | 
       | I've always been struck by the vision the authors state in the
       | preface;
       | 
       | > everyone can design programs
       | 
       | >
       | 
       | > and
       | 
       | >
       | 
       | > everyone can experience the satisfaction that comes with
       | creative design.
       | 
       | >
       | 
       | > Indeed, we go even further and argue that program design--but
       | not programming--deserves the same role in a liberal-arts
       | education as mathematics and language skills.
       | 
       | >
       | 
       | > A student of design who never touches a program again will
       | still pick up universally useful problem-solving skills,
       | experience a deeply creative activity, and learn to appreciate a
       | new form of aesthetic.
       | 
       | I'm not a good programmer - I'm not even a average one, but the
       | book and learning Racket has made me better.
        
       | axelerator wrote:
       | I always say my appreciation for functional programming comes
       | from having spent enough time in imperative hell.
       | 
       | That being said I think learning programming in an "expressions
       | only" environment can enable the student to deal with more
       | complex problems earlier, merely by making certain types of
       | errors impossible.
       | 
       | I think the Elm programming language is the sweet spot for that.
       | 
       | - it does have elegant (Haskell like) syntax
       | 
       | - it has still a simple syntax because it deliberately omits
       | certain features (namely typeclasses, do-notation)
       | 
       | - it has a self contained build system (compiler, package
       | manager, repl, dev server) with a rich ecosystem of libraries
       | 
       | - it is comparatively easy to ship something tangible because it
       | compiles to JS for the browser
        
       | tonfreed wrote:
       | I think it's important to show students how to think about
       | languages as a set of tools. OP's post stabs at this quite well,
       | with the "Languages are less important than you think" section,
       | and as someone who has already jumped across 5 or 6 languages
       | over the course of his just over 10 year pro career this
       | definitely rings true.
       | 
       | I think it's fine to bag on languages like Racket, but a good
       | engineer should be able to hop across any language and at least
       | be able to read and understand what they're doing.
        
       | melony wrote:
       | It is interesting that recursion is still considered to be so
       | _novel_ on blogs and forums. From what I have seen of current CS
       | curriculums, recursion is usually taught in the first year
       | immediately after introductory CS. It is almost impossible not to
       | use recursion when dealing with tree structures (using an
       | explicit stack takes a lot more code, most coding interviews don
       | 't ask for an iterative solution unless absolutely necessary).
        
         | moron4hire wrote:
         | After 20 years of software development in a variety of
         | languages and projects, I've come to the opinion that recursion
         | really should be relegated to being a novelty.
         | 
         | Few languages offer tail-call optimization. If we look at
         | popularity of languages, then the likelihood any particular
         | solution is going to end up in such a language is vanishingly
         | small. For the remaining languages, fitting into the stack
         | depth is easy to get wrong. It's easy to end up in an infinite
         | loop that ends in an obscure error with a confusing, verbose,
         | needle-in-hay-stack stack frame that over complicates
         | debugging. And frankly, lots of programmers don't have a good
         | handle on it, even the ones who studied CS in college, so
         | asking them to maintain recursive code written by someone else
         | usually ends pretty poorly.
         | 
         | So when we consider that, actually, no, it's not true that
         | using an explicit stack takes "a lot more code" (it's like,
         | three extra lines), recursion starts to look more and more like
         | a code smell, a smell indicating the originating programmer is
         | more a temporarily-embarrassed mathematician than an engineer.
         | 
         | To be clear, I have no problems conceiving of and implementing
         | recursive solutions to problems. But every single one of my
         | recursive solutions has eventually failed to survive contact
         | with real life data. It might be next week when the code goes
         | to production or it might be a year from now when the data
         | processing needs grow, but I've eventually replaced them all.
         | 
         | I'm not the only one with this opinion. Many safety regulations
         | covering vehicles from cars to spacecraft explicitly ban
         | recursion because of these issues. We need to just stop with
         | the fetishising of math in software development.
        
           | dgb23 wrote:
           | In web/gui programming it's a good fit. Your data is a tree
           | that you render on a screen, so it's by default relatively
           | shallow and not very big. It's never going to blow the stack
           | and the benefit of using recursion, closures and functional
           | composition is you get clear, dense code and tend to make
           | fatter data structures and more general code.
        
             | nonameiguess wrote:
             | Yep. Same thing with filesystems. Since they're meant for
             | humans to traverse, finding a directory structure with deep
             | enough nesting to blow up the process stack or hit a
             | runtime recursion limit is sufficiently rare that you
             | shouldn't even worry about it. I'm sure there are plenty of
             | other examples where the practical limit you'll see in much
             | lower than what an address space stack can fit. We had a
             | task at an old job to create dependency and build trees of
             | every service in the overall project and then operate on
             | them. Even assuming a language runtime with a very small
             | limit, say Python with its 997 or so default maximum
             | simultaneous stack frames, we didn't have 997 individual
             | services, so even the maximally malicious dependency tree
             | couldn't have exceeded that limit.
        
           | soegaard wrote:
           | It's great to have support for tail recursion when
           | implementing recursive solutions, but it is a tall order to
           | add to more traditional languages. However tail recursion is
           | not the only trick Racket has up its sleeve.
           | 
           | In Racket you can't get a stack overflow.
           | 
           | At the time a potential stack overflow is detected, the
           | oldest parts of the current stack is copied to the heap and a
           | fresh stack is introduced. When the stack underflows the
           | saved stack is reinstated. [At least this is a rough idea of
           | how it works - implementation details differ to make it
           | process efficient.]
           | 
           | This means that you can rely on recursive solutions even when
           | the recursive call occurs in a non-tail context.
           | 
           | This idea (no stack overflows) could be used in more
           | traditional languages too. As you write in traditional
           | languages there is a real risk to bump into the stack limit.
        
           | Banana699 wrote:
           | >it's not true that using an explicit stack takes "a lot more
           | code" (it's like, three extra lines)
           | 
           | I don't know if you mean that literally or just as a
           | rhetorical exaggeration, but it's absolutely false. The first
           | example that came to mind is Quick Sort, search for the
           | iterative version of the algorithm and compare it with the
           | traditional recursive version, easily a 10x factor. The
           | increase in complexity isn't linear in code size either, the
           | code that replaces the simple recursive calls is full to the
           | brim with loops, state and conditional mutations, i.e. Free
           | Bugs, yummy yummy.
           | 
           | >Few languages offer tail-call optimization.
           | 
           | I was hacking on a (non-tail-) recursive solution to a
           | problem a couple of days ago in a repl.it container, and a
           | buggy solution exploded after consuming 15000 stack frames.
           | The repl had 1024 MB RAM as a max limit. The point is,
           | absence of tail cail optimization is rarely if ever a real
           | problem in a language that has loops, its a big, big problem
           | if the language doesn't have loops, but as long as the
           | language has loops and relegates recursion to the "Side Role"
           | its so good at, its just not that of a big deal.
           | 
           | This also fails to consider why recursion is such an
           | attractive algorithmic construct, tail recursion is
           | absolutely trivial, it can be transformed to loops
           | mechanically, it rarely adds anything of value to the
           | readability and expressiveness of code.
           | 
           | The vast majority of interesting and useful uses of recursion
           | is the non-tail-recursive variety, where you have to use a
           | stack anyway, at this point the whole argument reduces to
           | whether you can maintain a stack more efficiently and
           | readably than the machine, which in my view ends in you
           | losing to the machine 9 times out of 10.
           | 
           | >And frankly, lots of programmers don't have a good handle on
           | it, even the ones who studied CS in college, so asking them
           | to maintain recursive code written by someone else usually
           | ends pretty poorly.
           | 
           | If those programmers were asked to instead maintain the
           | explicitly iterative version of the code, I bet it would end
           | even more badly. Recursion, after the initial cost of
           | watching a few tutorials, is _less_ confusing than loops. It
           | 's about hiding state, how on earth is explicitly managing
           | all that state yourself better? This is like saying that "2+4
           | _6 /(3+1)_4" is best calculated as a long sequence of
           | 2-argument assembly instructions because its more explicit
           | that way, its more explicit, true, but - paradoxically - way
           | more obscure.
           | 
           | >Many safety regulations covering vehicles from cars to
           | spacecraft explicitly ban recursion because of these issues.
           | 
           | Embedded Systems safety regulations and conventions ban a lot
           | of things, recursion is not special at all. One thing is
           | dynamic allocation, another thing is multiple returns out of
           | a subroutine. Are you ready to give up those 2 things?
           | 
           | It makes no sense to take the conventions of a very specific
           | and idiosyncratic industry like that and try to derive from
           | it universal rules that should govern all software.
        
             | BeetleB wrote:
             | > Embedded Systems safety regulations and conventions ban a
             | lot of things, recursion is not special at all. One thing
             | is dynamic allocation, another thing is multiple returns
             | out of a subroutine. Are you ready to give up those 2
             | things?
             | 
             | Indeed. On one automotive project, we could not use C++
             | strings, due to the hidden dynamic allocation.
        
       | ausbah wrote:
       | would've put my money on this coming from a Northeastern student,
       | nice write up either way
        
       | srcreigh wrote:
       | The point about simple evaluation models, while true for basic
       | Racket, is actually the furthest from the truth in idiomatic
       | Racket.
       | 
       | The idiomatic way to solve a problem in Racket is to develop new
       | syntax (and evaluation orders) which are suited to the problem.
       | 
       | In fact, Racket has pythonic list comprehension syntax too:
       | (for/list ([x '(2 4 8)]) (sqr x))
       | 
       | It also has lazy evaluation langs, static typecheck pre-eval step
       | langs, DFA compilers, OOP...
       | 
       | Basically the floodgates are open, even if the river is still a
       | bit barren. Every confusing language feature in existence can be
       | added to Racket. The only saving grace is that anyone, including
       | you, can replace it with less confusing syntax / evaluation
       | orders if they so desire.
       | 
       | I wrote a Macro which adds identifiers to your program based _on
       | a SQLite database 's column names_. [0] If the database isn't
       | found your program _does not compile_. How is _that_ for
       | confusing alternative evaluation order? If that 's your
       | nightmare, my point is made.
       | 
       | [0]: http://tech.perpetua.io/2022/01/generating-sqlite-
       | bindings-w...
        
         | neilv wrote:
         | Developing domain-specific languages/minilanguages is claimed
         | by many to be idiomatic for many Lisps.
         | 
         | And DSL is an especially strength of Racket (especially with
         | the syntax objects, pattern-based syntax transformers, module
         | system and submodules, and `#lang`).
         | 
         | But, just to avoid giving non-Racketeers the wrong
         | impression... I don't recall anyone ever calling a piece of
         | Racket code _non_ -idiomatic merely because it didn't introduce
         | a DSL or syntax extension.
         | 
         | In my (abandoned) Racket book, I intended to get people
         | commercial-grade productive the first day, and introducing
         | syntax extension wouldn't come until calendar weeks/months
         | later. (Related: there'd be an entire chapter at the _end_ ,
         | entitled "Don't Use `eval`", starting out like:
         | https://lists.racket-lang.org/users/archive/2014-July/063597...
         | :)
        
         | srcreigh wrote:
         | Another example... this Arc code doesn't finish evaluating
         | until a couple round trips with a web browser are finished.
         | Absolutely cursed                   (defop said req
         | (aform [w/link (pr "you said: " (arg _ "foo"))
         | (pr "click here")]             (input "foo")
         | (submit)))
         | 
         | (If you didn't know, Arc is implemented in Racket, and powers
         | this site...)
         | 
         | http://paulgraham.com/arcchallenge.html
        
         | kjander79 wrote:
         | One thing to note: The reason why SICP uses Scheme is not that
         | the resulting programs are simpler. But instead, the mental
         | model of what is happening under the hood is simpler, and easy
         | to refine as you go along. This makes it possible to come to
         | the end of the class, ready to create your own Scheme
         | interpreter. I don't think that's possible with any of the
         | alternatives, like Python.
         | 
         | I am sure this result was rare, of course, even when it was the
         | introductory at MIT. And as you point out, Racket has changed a
         | lot also. I think it has been some years that Racket stopped
         | calling itself Scheme, feeling the changes they have made have
         | deviated too far.
        
         | neilv wrote:
         | In my (abandoned) Racket book (which had a very specific
         | positioning), I was going to introduce some of the non-Scheme
         | iterators like `for/list` at the start, to help people do
         | commercial work on the first day... and then later teach some
         | more old-school Scheme-idiomatic ways to do things, with
         | named-`let` and avoiding mutations to shoehorn. (Then, once
         | people were comfortable with the less-familiar way, they could
         | decide when to use which.)
        
         | xhevahir wrote:
         | You're a lot more pessimistic here than in your blog post!
        
       | adamddev1 wrote:
       | Great writing and I agree with these points. I learned Racket by
       | working through HTDP [1] and although I've never used Racket for
       | anything other than those exercises it was totally worth it. I
       | think it (the language and HTDP) massively improved the way I
       | think through, organize, and write everything else.
       | 
       | [1]: https://htdp.org/
        
       | scythe wrote:
       | One aspect of Racket that I would expect to appeal to students,
       | but which does _not_ appear in this blog post, is its cross-
       | platform (and widget-native!) GUI framework:
       | 
       | https://docs.racket-lang.org/gui/
       | 
       | The first "side-project" I ever did was a tic-tac-toe program in
       | Java AWT during my first year of programming in high school. AWT
       | wasn't even part of the curriculum, it was just what I gravitated
       | towards as a 13-year-old whose experience with computers
       | consisted entirely of graphical applications.
       | 
       | Maybe the kids these days would be more interested in building a
       | web app or something, but frankly I don't think it's surprising
       | that writing code that primarily consumes and emits text at a
       | terminal is not interesting to students who have never had any
       | need for a terminal before.
        
         | Bootvis wrote:
         | I tried (not very hard) to see some screenshots but failed. Do
         | you know of a gallery with example code?
        
           | samth wrote:
           | https://alex-hhh.github.io/2021/09/screenshots.html is a nice
           | gallery of one person's apps.
        
         | tonfreed wrote:
         | Can confirm, I very quickly picked up Swing when I started Java
         | programming just because I wanted to make little games and
         | cellular automata. Before that, we'd had Haskell forced upon us
         | and the GUI stuff had been very difficult for a beginner to
         | pick up.
        
         | steinuil wrote:
         | I love racket/gui and recently shipped a product using it for a
         | diagnostics tool! The killer features are as you said that it
         | uses native widgets, but also that it doesn't require any sort
         | of dynamic linking to heavyweight C libraries (other than the
         | ones Racket itself comes with) and that you can easily compile
         | it in a redistributable form with basically no dependencies for
         | all platforms. I can't recommend it enough.
        
       | fuzzer37 wrote:
       | There is no reason. Don't learn Racket. Let it die like it
       | deserves to.
        
       | dbpatterson wrote:
       | So... unless Grinnell does things very differently, the author
       | did not learn Racket, they learned
       | (Beginning/Intermediate/Advanced) Student Language, and that's
       | the point.
       | 
       | Racket is a complicated language, designed primarily in order to
       | support the easy creation of other languages: it would be as bad
       | a choice (perhaps worse) for a first language as any other. All
       | of the simplicity, focusing on learning to program, programming
       | structurally based on data, that comes out of HtDP, is enabled by
       | the restricted language.
       | 
       | It's too bad that this naming confusion persists, as I think it
       | hurts the effort to focus on teaching _programming_ in intro
       | classes, vs. teaching X language (I don't want to teach people
       | Racket any more than I want to teach them Python or Java. They
       | can learn those on their own -- they'll probably learn at least a
       | half dozen other languages over their career, all on their own,
       | if they stick with it). This curriculum is about figuring out how
       | to most effectively teach people to program: the language was
       | created, after the fact, to support that.
        
         | [deleted]
        
       | jboynyc wrote:
       | Nice writeup, keep it up!
        
         | mark_l_watson wrote:
         | I agree, keep writing.
         | 
         | I have spent a lot of my professional life using Lisp
         | languages. Not as popular as Python, Java, etc., but Lisp (and
         | other languages like Haskell) have a good effect on how we
         | think about computation.
        
         | hydroxideOH- wrote:
         | Thank you!
        
       ___________________________________________________________________
       (page generated 2022-02-21 23:00 UTC)