9 comments

  • shawn_w20 hours ago
    The Racket Discourse thread on this: <a href="https:&#x2F;&#x2F;racket.discourse.group&#x2F;t&#x2F;illustrate-anonymous-recursive-functions-a-la-powershell&#x2F;3932" rel="nofollow">https:&#x2F;&#x2F;racket.discourse.group&#x2F;t&#x2F;illustrate-anonymous-recurs...</a><p>(Just me suggesting other alternatives right now)
    • skrishnamurthi5 hours ago
      Thanks for the suggestion to replace the reference to MzLib with SRFI-31. I&#x27;ve done that now.<p><a href="https:&#x2F;&#x2F;github.com&#x2F;shriram&#x2F;anonymous-recursive-function&#x2F;commit&#x2F;6c05e1bcd67014c56308a44d4ef2d8a4ce94eb6c" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;shriram&#x2F;anonymous-recursive-function&#x2F;comm...</a>
  • maplant23 hours ago
    This isn&#x27;t specific to racket, any implementation of R6RS scheme should fully support this, although the define-syntax form is slightly different.<p>I checked this with my R6RS implementation and it works just as you would expect (<a href="https:&#x2F;&#x2F;github.com&#x2F;maplant&#x2F;scheme-rs" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;maplant&#x2F;scheme-rs</a>)
    • valorzard22 hours ago
      How close are you to getting a &quot;full&quot; implementation of R6RS? I&#x27;ve been thinking of picking either your project or Steel[0] for a Rust Scheme thing<p>[0] <a href="https:&#x2F;&#x2F;github.com&#x2F;mattwparas&#x2F;steel" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;mattwparas&#x2F;steel</a>
      • maplant21 hours ago
        I’m hoping by the end of the year. All of the “difficult” things are finished (control flow, syntax transformers, call&#x2F;cc, dynamic wind, exceptions, libraries, etc) and it’s just a matter of filling missing base library functions. If there’s something in particular that you need you’re welcome to file and issue or post a message on the discord and I’ll prioritize it.<p>That being said, Steel is excellent and I highly recommend it if you just need R5RS with syntax transformers
    • skrishnamurthi20 hours ago
      Wow — scheme-rs is such a neat project! Hadn&#x27;t heard of it before!
      • maplant18 hours ago
        Thanks! I haven’t really publicized it, my goal is to get it finished first, but I will be presenting on it at the scheme workshop at ICFP&#x2F;SPLASH
        • skrishnamurthi6 hours ago
          Neat! Will see if I can make it (though I&#x27;ll probably have to be dealing with OOPSLA stuff at the same time )-:).
  • adityaathalye17 hours ago
    In Clojure...<p><pre><code> ((fn [xs ret] (if (empty? xs) ret (recur (rest xs) (+ ret (first xs))))) (range 5) 0) =&gt; 10 </code></pre> nb. Clojure doesn&#x27;t have automatic tail call optimisation. We need to explicitly emulate it with`recur`.
    • skrishnamurthi1 hour ago
      It&#x27;s not the same thing. `recur` in Clojure must be in tail-position. This program<p><a href="https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=45154253">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=45154253</a><p>would therefore not work.
      • adityaathalye1 hour ago
        I was trying to say something like that with my note in the GP comment:<p><pre><code> &gt; &quot;nb. Clojure doesn&#x27;t have automatic tail call optimisation. We need to explicitly emulate it with`recur`.&quot; </code></pre> Just an average joe programmer here... advanced macrology is way above my pay grade :sweat-smile:.
    • JonChesterfield12 hours ago
      Do the clojure folks still insist this is a feature, as opposed to an incomplete compiler leaking limitations into their world?
      • jayceedenton12 hours ago
        Without the explicit recur it&#x27;s far too easy to misidentify a tail call and use recursion where it&#x27;s not safe.<p>Recur has zero inconvenience. It&#x27;s four letters, it verifies that you are in a tail position, and it&#x27;s portable if you take code to a new function or rename a function. What&#x27;s not to love?
        • rgherdt3 hours ago
          That doesn&#x27;t work for mutual recursion, what is quite common in Scheme programs. Besides, tail call optimization is not only useful in recursion.
          • skrishnamurthi1 hour ago
            Tails calls are especially useful in languages with macros. You don&#x27;t know what context you are in, you just generate the call that makes sense. If the call happens to be in tail-position, you get the benefit of it.<p>Moreover, you can design cooperating macros that induce and take advantage of tail-position calls.<p>Here&#x27;s a simple example that motivates tail-calls that are not tail-recursive:<p><a href="https:&#x2F;&#x2F;cs.brown.edu&#x2F;~sk&#x2F;Publications&#x2F;Papers&#x2F;Published&#x2F;sk-automata-macros&#x2F;" rel="nofollow">https:&#x2F;&#x2F;cs.brown.edu&#x2F;~sk&#x2F;Publications&#x2F;Papers&#x2F;Published&#x2F;sk-au...</a>
            • adityaathalye1 hour ago
              Yeah, absent automatic TCO, we have to do it all, explicitly, by hand... `recur` and `trampoline`.<p>recur: <a href="https:&#x2F;&#x2F;clojuredocs.org&#x2F;clojure.core&#x2F;recur" rel="nofollow">https:&#x2F;&#x2F;clojuredocs.org&#x2F;clojure.core&#x2F;recur</a><p><pre><code> &gt; Evaluates the exprs in order, then, in parallel, rebinds the bindings of</code></pre> the recursion point to the values of the exprs.<p><pre><code> (def factorial (fn [n] (loop [cnt n acc 1] (if (zero? cnt) acc (recur (dec cnt) (* acc cnt)) ; in loop cnt will take the value (dec cnt) ; and acc will take the value (* acc cnt) )))) </code></pre> trampoline: <a href="https:&#x2F;&#x2F;clojuredocs.org&#x2F;clojure.core&#x2F;trampoline" rel="nofollow">https:&#x2F;&#x2F;clojuredocs.org&#x2F;clojure.core&#x2F;trampoline</a><p><pre><code> &gt; trampoline can be used to convert algorithms requiring mutual recursion without stack consumption. </code></pre> i.e. these <i>emulate</i> TCO, with similar stack consumption properties (they don&#x27;t implement real TCO).<p>(edit: formatting)
              • skrishnamurthi40 minutes ago
                Thanks for the pointers. Trampolining is an old idea for obtaining tail-calls. It&#x27;s a kind of folk-wisdom that has been rediscovered many times, as the related work here shows:<p><a href="https:&#x2F;&#x2F;dl.acm.org&#x2F;doi&#x2F;pdf&#x2F;10.1145&#x2F;317636.317779" rel="nofollow">https:&#x2F;&#x2F;dl.acm.org&#x2F;doi&#x2F;pdf&#x2F;10.1145&#x2F;317636.317779</a><p>Usually the trampoline is implemented automatically by the language rather than forcing the author to confront it, though I can see why Clojure might have chosen to put the burden on the user.
  • h4ch121 hours ago
    Tangential, but I&#x27;ve been wanting to dive back into FP for quite sometime; for context I used Haskell at a payments corp ~10 years back, working mostly with Typescript, Zig and Nim for the past couple of years, realizing I am basically trying to do FP in most of these languages.<p>Is Racket a good language to pick up and re-learn my concepts + implement some tools? Or are there some other languages that would be better to both brush up and learn the syntax of, I do not want to fight the syntax but rather express functions as seamlessly as I can.
    • skrishnamurthi21 hours ago
      Racket is a rich and powerful language, but it is also designed with certain specific ideas in mind. You can learn more about the &quot;zen&quot; of Racket here:<p><a href="https:&#x2F;&#x2F;cs.brown.edu&#x2F;~sk&#x2F;Publications&#x2F;Papers&#x2F;Published&#x2F;fffkbmt-programmable-prog-lang&#x2F;" rel="nofollow">https:&#x2F;&#x2F;cs.brown.edu&#x2F;~sk&#x2F;Publications&#x2F;Papers&#x2F;Published&#x2F;fffkb...</a><p>That might help you decide whether Racket will help you with what you&#x27;re trying to brush up on.
      • h4ch120 hours ago
        Thank you for the response professor, really appreciate it from one of the creators of the language itself;<p>I did give your document a read and my (naive) understanding is you basically create DSLs for each sub-part of the problem you&#x27;re trying to solve?<p><i>&gt;A LOP-based software system consists of multiple, cooperating components, each written in domain-specific languages.</i><p>and<p><i>&gt;cooperating multi-lingual components must respect the invariants that each participating language establishes.</i><p>So basically you&#x27;re enforcing rules&#x2F;checks at the language level rather than compile time?<p>How would you recommend a complete novice attain this sort of state of mind&#x2F;thought process while working in this language? Because my thoughts go simply to creating types and enforcing type-checking coupled with pure functions to avoid successful-fail at runtime programs.<p>Also how would one navigate the complexity of multiple abstractions while debugging?<p>The paper also mentions a web-server language (footnote 27), if I use racket will I be productive &quot;out of the box&quot; or is the recommended path to take is writing a web server language first.<p>Thank you again for taking the time to respond, and please do forgive me for these naive questions.
        • skrishnamurthi20 hours ago
          These are great questions!<p>Yes, what you&#x27;re describing is the &quot;extreme&quot; version of LOP. Of course you don&#x27;t have to do it that aggressively to get working code.<p>Two references I like to point to:<p><a href="https:&#x2F;&#x2F;www.hashcollision.org&#x2F;brainfudge&#x2F;" rel="nofollow">https:&#x2F;&#x2F;www.hashcollision.org&#x2F;brainfudge&#x2F;</a><p><a href="https:&#x2F;&#x2F;beautifulracket.com&#x2F;" rel="nofollow">https:&#x2F;&#x2F;beautifulracket.com&#x2F;</a><p>They will give you a sense of how one uses LOP productively.<p>You do <i>not</i> need to write a &quot;web server language&quot;! To the contrary, the Web server <i>provides</i> several languages to give you a trade-off between ease and power in writing server-side Web applications. So you can just write regular Racket code and serve it through the server. The server also comes with some really neat, powerful primitives (orthogonal to LOP) — like `send&#x2F;suspend` — that make it much easier to write server-based code.
          • h4ch120 hours ago
            Understood. Will dive deeper into Racket to get a proper understanding since it&#x27;s created an itch because I still don&#x27;t understand it :)<p>Even if I don&#x27;t go fully into it as a production language, hopefully it&#x27;ll open some avenues of thought that I do not yet possess.<p>Thank you for taking the time to respond, have a great day!
    • humanfromearth911 hours ago
      You could try Purescript, with the book¹ written by Charles Scalfani.<p>It focuses exclusively on FP and does not deviate from it.<p>¹ <a href="https:&#x2F;&#x2F;leanpub.com&#x2F;fp-made-easier&#x2F;" rel="nofollow">https:&#x2F;&#x2F;leanpub.com&#x2F;fp-made-easier&#x2F;</a>
  • userbinator1 day ago
    A relevant article to the domain name of this site.
    • drivenextfunc23 hours ago
      If you look at the code, you&#x27;ll be (unpleasantly) surprised, I think. The author does not seem to have known what Y combinator is.
      • skrishnamurthi21 hours ago
        If it helps, you will find the Y-combinator described (indeed, derived) in the first edition (<a href="https:&#x2F;&#x2F;cs.brown.edu&#x2F;~sk&#x2F;Publications&#x2F;Books&#x2F;ProgLangs&#x2F;2007-04-26&#x2F;" rel="nofollow">https:&#x2F;&#x2F;cs.brown.edu&#x2F;~sk&#x2F;Publications&#x2F;Books&#x2F;ProgLangs&#x2F;2007-0...</a>) of the author&#x27;s programming languages book (<a href="https:&#x2F;&#x2F;www.plai.org&#x2F;" rel="nofollow">https:&#x2F;&#x2F;www.plai.org&#x2F;</a>). (Page 228, if that helps, though the derivation begins on page 223.)<p>For added fun, the day he teaches it in class, he wears a t-shirt from Y-combinator the startup accelerator (and explains what its name means).<p>Now that we&#x27;ve gotten that out of the way, it remains unclear what is surprising or unpleasantly surprising about the code.
        • userbinator16 hours ago
          This reminds me of when John Nagle showed up in a thread about his algorithm on here.
        • adityaathalye17 hours ago
          Shriram invoking Shriram ... (λ.x (x x) λ.x (x x)) forever \m&#x2F; :)
      • blahedo21 hours ago
        In addition to the general sibling comments, I can personally attest that Shriram knows what the Y combinator is and has been teaching students about it for <i>at least</i> 25 years. My own lecture notes from one of his classes about the lambda calculus and the Y combinator were for a long time on the front page of google results for info about either!
      • plaitowin23 hours ago
        I&#x27;m pretty sure Shriram Krishnamurthi understands the Y combinator...
      • Philpax21 hours ago
        <a href="https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Shriram_Krishnamurthi" rel="nofollow">https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Shriram_Krishnamurthi</a>
        • skrishnamurthi21 hours ago
          Don&#x27;t see Y-combinator mentioned <i>anywhere</i> on that page.
          • adityaathalye17 hours ago
            But I do see that page mentioned on Y Combinator&#x27;s page.<p>The joke can go on forever...
            • shawn_w15 hours ago
              Somebody forgot to add a base case.
      • almostgotcaught21 hours ago
        These are my favorite types of comments on hn
        • neilv19 hours ago
          The HN guidelines suggest assuming the strongest interpretation of what someone said, so obviously the commenter was making a joke. :)
      • srpablo22 hours ago
        lmao Google him
  • shakna11 hours ago
    Probably worth noting that there&#x27;s already an SRFI for this. [0] And that macro will work on any Scheme implementing the standard since about &#x27;98.<p><pre><code> (define-syntax rec (syntax-rules () ((rec (NAME . VARIABLES) . BODY) (letrec ( (NAME (lambda VARIABLES . BODY)) ) NAME)) ((rec NAME EXPRESSION) (letrec ( (NAME EXPRESSION) ) NAME)))) </code></pre> [0] <a href="https:&#x2F;&#x2F;srfi.schemers.org&#x2F;srfi-31&#x2F;srfi-31.html" rel="nofollow">https:&#x2F;&#x2F;srfi.schemers.org&#x2F;srfi-31&#x2F;srfi-31.html</a>
    • skrishnamurthi6 hours ago
      1. This isn&#x27;t the same. `rec` names the function. This does not name the function. The point is to illustrate how the name-capture works.<p>2. The README literally says &quot;Don&#x27;t Use This Macro!&quot; and references `rec` to use instead:<p><a href="https:&#x2F;&#x2F;github.com&#x2F;shriram&#x2F;anonymous-recursive-function?tab=readme-ov-file#dont-use-this-macro" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;shriram&#x2F;anonymous-recursive-function?tab=...</a>
  • user393938220 hours ago
    All the languages I like have niche ecosystems which have a lot of drawbacks
    • neilv18 hours ago
      In such ecosystems, for long-term, evolving production work (when you don&#x27;t know all your eventual needs upfront), you need to have the institutional capability to build from scratch whatever components you might need. Just in case whatever you need later doesn&#x27;t yet exist in the ecosystem.<p>Then you need to retain the personnel who give you that capability. Because they are rare, in a field in which 99%+ of developers only glue together NPM or PyPI packages. (And many use Web search or, now, Claude Code to do the glue part.)<p>If I founded a startup doing mostly Web-like server backend work, I&#x27;d consider doing it in Racket or another Scheme, and then using that as a carrot to be able to hire some of the most capable programmers. (And not having to bother with resume spamming noise from hardly any of the 99%+ developers, who will be pounding the most popular resume tech stack keywords instead, because their primary&#x2F;sole goal is employability.)
    • skrishnamurthi6 hours ago
      The correlation is likely causal in both directions.<p>They&#x27;re niche because they&#x27;re doing weird, interesting things. Like creating their own VMs to support funky features. So nobody wants to depend on them: low bus-factor.<p>They can do weird, interesting things because they don&#x27;t have a large user-base that will yell at them about how they&#x27;re breaking prod.
  • behnamoh21 hours ago
    can we implement this in Python?
    • eliben20 hours ago
      The Y combinator in Python: <a href="https:&#x2F;&#x2F;eli.thegreenplace.net&#x2F;2016&#x2F;some-notes-on-the-y-combinator&#x2F;" rel="nofollow">https:&#x2F;&#x2F;eli.thegreenplace.net&#x2F;2016&#x2F;some-notes-on-the-y-combi...</a><p>(scroll down, after the concept is explained using Clojure)<p>A bit crazier, in Go with generics: <a href="https:&#x2F;&#x2F;eli.thegreenplace.net&#x2F;2022&#x2F;the-y-combinator-in-go-with-generics&#x2F;" rel="nofollow">https:&#x2F;&#x2F;eli.thegreenplace.net&#x2F;2022&#x2F;the-y-combinator-in-go-wi...</a>
  • CyberDildonics23 hours ago
    I would rather use a loop so I can debug it.
    • skrishnamurthi20 hours ago
      This isn&#x27;t meant to be a good programming mechanism, it&#x27;s meant to be an illustration of how to use the macro system.<p>But also, if you&#x27;re processing non-linear data, you&#x27;re going to want to do with a recursive function anyway. E.g., when dealing with a tree. Code below; can&#x27;t seem to get multi-line code-formatting so it looks hideous:<p>#lang racket<p>(require &quot;anon-rec.rkt&quot;) (require rackunit)<p>(struct mt ()) (struct node (v l r))<p>(define sum-tree (lam&#x2F;anon (t) (cond [(mt? t) 0] [(node? t) (+ (node-v t) ($MyInvocation (node-l t)) ($MyInvocation (node-r t)))])))<p>(define t (node 5 (node 3 (mt) (mt)) (node 7 (node 9 (mt) (mt)) (mt))))<p>(check-equal? (sum-tree t) 24)
      • neilv18 hours ago
        For formatting code blocks on HN, prefixing each line with 4+ leading spaces works:<p><pre><code> (define sum-tree (lam&#x2F;anon (t) (cond ((mt? t) 0) ((node? t) (+ (node-v t) ($MyInvocation (node-l t)) ($MyInvocation (node-r t)))))))</code></pre>
      • CyberDildonics19 hours ago
        Recursion just ends up using the call stack as a stack data structure. I would much rather use an actual stack data structure, that will be easier to debug and have better locality since there isn&#x27;t an entire call frame overhead to put one value into the stack.
    • treyd23 hours ago
      Tail-recursive functions in Racket are optimized down to essentially for loops.
      • stirfish20 hours ago
        What&#x27;s it like to debug them?
        • rgherdt3 hours ago
          One strategy is by &quot;tracing&quot; a function call:<p><a href="https:&#x2F;&#x2F;docs.racket-lang.org&#x2F;trace&#x2F;" rel="nofollow">https:&#x2F;&#x2F;docs.racket-lang.org&#x2F;trace&#x2F;</a>