[HN Gopher] The evolution of a Scheme programmer (2020)
___________________________________________________________________
The evolution of a Scheme programmer (2020)
Author : ducktective
Score : 126 points
Date : 2024-05-15 18:33 UTC (2 days ago)
(HTM) web link (erkin.party)
(TXT) w3m dump (erkin.party)
| shric wrote:
| (2020)
| NackerHughes wrote:
| Thanks for the heads-up. I was almost about to be misinformed
| by an outdated, no-longer-relevant article about a language
| that's been more or less the same for the last few decades.
| mark_l_watson wrote:
| That was a tasty read! The Y-combinator implementation gave me a
| slight headache, but I averted my eyes and all was OK.
|
| Scheme as a language and from a clean/simplicity point of view
| has always appealed to me, but I have mostly used Common Lisp
| because I have so much legacy code.
| anonzzzies wrote:
| I use Scheme (these days more Racket or Shen) for doing
| 'language experiments' but if anything gets to production,
| it'll be CL. Like you said, legacy code, but also; it's just
| more practical. You give up some elegance, but in exchange you
| get something which you can build practically anything in, in
| modern times.
| roenxi wrote:
| Isn't this missing the joke? The Haskell article code ended with
| the "Tenured Professor" implementation (`fac n = product [1..n]`)
| as a nod to the old trope of not needing to implement anything.
| This article ends with `(define factorial (dynamic-require
| 'math/number-theory 'factorial (lambda () lambda (n) (error
| 'factorial "Cannot import library: ~a" 'math/number-theory)))))`.
|
| Surely there is a lazier implementation than a define and 2x
| lambdas to use a library function. Although I did get a chuckle
| about not feeling a need to add brackets to the Scheme example.
| Y_Y wrote:
| But the extra code is for handling the error, you could just
| `require` it and be done if you want to assume the library is
| available.
| shawn_w wrote:
| Normal Racketeers would just `(require math/number-theory)` and
| be done. No idea why they're loading the module at runtime like
| that instead, unless it's a deliberately over complicated joke
| solution like some of the others. Which would as you noted miss
| the point of the original.
| qart wrote:
| Thankfully, the tenured professor version works in Julia like
| so: prod(1:63)
|
| For bigger numbers, factorial(n) = 1:n .|>
| BigInt |> prod
| soegaard wrote:
| It's not the best algorithm for computing factorials though.
| A better strategy is to pair small and large factors together
| in order to avoid bignum computations (or to reduce the size
| og bignum computations).
|
| https://people.eecs.berkeley.edu/~fateman/papers/factorial.p.
| ..
|
| Also: It's more fun to use the name `fact` in benchmarks...
| lispm wrote:
| We might add an evolution of the display of parentheses...
|
| B&W ()
|
| B&W and optional bold ()
|
| B&W and optional bold/larger ()
|
| Full color rainbow parentheses.
|
| B&W ()
|
| One or two of the Lisp editors I use also support rainbow
| parentheses, but after an initial phase of experimentation, I
| have disabled that feature.
| mckn1ght wrote:
| This is the first time I've ever seen rainbow parentheses, it
| seems like such a useful thing. What wound up leading you back
| to B&W?
| medo-bear wrote:
| Probably because you get used to them and different colours
| become distracting. Highlighting of active parentheses is
| more useful
| lispm wrote:
| Too much visual clutter with very little actual benefit. I
| found that I don't need/want to find matching parentheses by
| a mix of position AND color.
| aredox wrote:
| Using an actual rainbow seems a bad idea. I will try to set
| up a Viridis (or similar perceptually continuous) color
| scheme next time I dabble in lisps.
| dgb23 wrote:
| I like my parens in a muted color with the currently active one
| highlighted.
|
| Rainbow colors are extremely distracting and overloading to me.
| phforms wrote:
| I also came back to B&W because I've noticed that with
| structural editing I think more in terms of s-expressions than
| parentheses and distinguishing them isn't that much of a
| problem anymore.
| roenxi wrote:
| Golden opportunity to slip an "animated" option in there. I'm
| pretty sure there are editors with a little jump to the other
| side of a form to show where it is.
| lispm wrote:
| In Zmacs on the Lisp Machine, the s-expression under the
| mouse cursor gets an outline. This is updated while the mouse
| is moving.
| ReleaseCandidat wrote:
| I use these colours for rainbow brackets in all other languages
| https://github.com/Release-Candidate/vscode-scheme-repl/blob...
| but for LISPs I dimmed them (their saturation) down for normal
| editing (when not "recording" animations/videos).
| oersted wrote:
| Zen of Python
|
| > There should be one-- and preferably only one --obvious way to
| do it.
|
| > Although that way may not be obvious at first unless you're
| Dutch.
| tasuki wrote:
| What is the preferred way to write factorial in Python?
| oersted wrote:
| I'd say the most idiomatic way is to use a simple for-loop:
|
| def factorial(n): result = 1
| for i in range(2, n + 1): result *= i
| return result
|
| The recursive version would be fine as well, but I would say
| it's less idiomatic in Python, and less efficient.
|
| def factorial(n): if n == 0 or n == 1:
| return 1 else: return n *
| factorial(n - 1)
|
| Beyond that, I cannot think of any obvious way to do this
| (without getting unreasonably convoluted).
|
| In my opinion, it's great that there are such few options to
| express this operation, and that both cases are eminently
| readable.
| Y_Y wrote:
| > In my opinion, it's great that there are such few options
| to express this operation, and that both cases are
| eminently readable.
|
| There are lots of ways to do this in Python. That's not
| only fine, it's inevitable.
|
| Here's a burnt-out PhD level one using highly pythonic
| paradigms: def fac(n):
| return eval("*".join(str(1+a) for a in range(n))
| oersted wrote:
| I have never seen a codebase that uses eval, it's
| considered more toxic than goto.
|
| Of course there are more ways, but I would definitely
| qualify this as "unreasonably convoluted".
| Y_Y wrote:
| > it's considered more toxic then goto
|
| Again I ask, considered by who? This is the kind of
| language that wikipedians would call "weasel words". Of
| course you shouldn't misuse eval or goto, and it's fine
| to have a rule of thumb to discourage it.
|
| What's not fine, and strikes me as no better than
| superstition, is to make vague "everybody knows"-type
| statements that convey almost no information. If it's bad
| you should be able to say (or provide reference to)
| specifically how it's bad and what convinced you this was
| the case.
|
| And yes, I deliberately wrote a perverse function because
| it was funny, but if you did a real fold instead of my
| fake one with strings then it wouldn't be so perverse.
| And wasn't it more pythonic to use a generator?
|
| Not embracing Perl's tmtowtdi is fine, but until you
| solve the halting problem some people will write "x+x"
| and some will write "2*x" and some will write "x<<2" and
| those can't sensibly be unified.
| tasuki wrote:
| I find both Haskell's `fac n = product [1..n]` and F# `let
| factorial n = [1..n] |> List.reduce ( _)` more readable and
| easier to comprehend. You could say using `product` is
| cheating, but `fac n = fold (_ ) [1..n]` definitely isn't!
|
| Your idiomatic Python version uses three variables, two of
| which mutate. I'm a simple man - go easy on me please! The
| `n + 1` took me a while to figure out too.
| Y_Y wrote:
| Preferred by who? `math.factorial` is a good start.
| oersted wrote:
| Obviously preferable, it was just to illustrate the "one
| obvious way of doing something".
| tasuki wrote:
| I'm delighted to see there are actually several ways and
| you good people are discussing them.
|
| This is _exactly_ why I asked the question!
| asplake wrote:
| How about: from math import prod # from
| Python 3.8 onwards def factorial(n):
| return prod(range(n+1))
| oersted wrote:
| Definitely preferable, wasn't aware of it.
| gshubert17 wrote:
| Since the first element in range() will be 0, should the
| last line be ...? return
| prod(1,range(n+1))
| asplake wrote:
| Oops yes! And unfortunately it still doesn't work for n=0
|
| Edit: prod(range(1, n+1)) does work
| gshubert17 wrote:
| My oops too. The extra 1 argument belongs with range, as
| you have it here.
| DeathArrow wrote:
| I like how in F# things are simpler:
|
| let factorial n = [1..n] |> List.reduce (*)
| pona-a wrote:
| (defn fac [n] (->> (range 1 (inc n)) (reduce *))) or in
| Clojure.
| aredox wrote:
| Has someone tried to evaluate all the solutions in terms of
| memory/CPU usage? Or do all the differences end up optimised
| away?
| 0x445442 wrote:
| And then there's Raku; say [*] 1..$n
___________________________________________________________________
(page generated 2024-05-17 23:01 UTC)