[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)