Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8248243
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 7, 20262026-06-07T23:07:47+00:00 2026-06-07T23:07:47+00:00

To learn Clojure , I’m solving the problems at 4clojure . I’m currently cutting

  • 0

To learn Clojure, I’m solving the problems at 4clojure. I’m currently cutting my teeth on question 164, where you are to enumerate (part of) the language a DFA accepts. An interesting condition is that the language may be infinite, so the solution has to be lazy (in that case, the test cases for the solution (take 2000 ....

I have a solution that works on my machine, but when I submit it on the website, it blows the stack (if I increase the amount of acceptable strings to be determined from 2000 to 20000, I also blow the stack locally, so it’s a deficiency of my solution).

My solution[1] is:

(fn [dfa]
  (let [start-state (dfa :start)
        accept-states (dfa :accepts)
        transitions (dfa :transitions)]
    (letfn [
      (accept-state? [state] (contains? accept-states state))

      (follow-transitions-from [state prefix]
          (lazy-seq (mapcat 
            (fn [pair] (enumerate-language (val pair) (str prefix (key pair))))
            (transitions state))))

      (enumerate-language [state prefix]
        (if (accept-state? state) 
          (cons prefix (follow-transitions-from state prefix))
          (follow-transitions-from state prefix)))
      ]   
      (enumerate-language start-state ""))
  )
)

it accepts the DFA

'{:states #{q0 q1 q2 q3}
              :alphabet #{a b c}
              :start q0
              :accepts #{q1 q2 q3}
              :transitions {q0 {a q1}
                            q1 {b q2}
                            q2 {c q3}}}

and returns the language that DFA accepts (#{a ab abc}). However, when determining the first 2000 accepted strings of DFA

(take 2000 (f '{:states #{q0 q1} 
                           :alphabet #{0 1}
                           :start q0
                           :accepts #{q0}
                           :transitions {q0 {0 q0, 1 q1} 
                                         q1 {0 q1, 1 q0}}}))

it blows the stack. Obviously I should restructure the solution to be tail recursive, but I don’t see how that is possible. In particular, I don’t see how it is even possible to combine laziness with tail-recursiveness (via either recur or trampoline). The lazy-seq function creates a closure, so using recur inside lazy-seq would use the closure as the recursion point. When using lazy-seq inside recur, the lazy-seq is always evaluated, because recur issues a function call that needs to evaluate its arguments.

When using trampoline,I don’t see how I can iteratively construct a list whose elements can be lazily evaluated. As I have used it and see it used, trampoline can only return a value when it finally finishes (i.e. one of the trampolining functions does not return a function).

Other solutions are considered out of scope

I consider a different kind of solution to this 4Clojure problem out of scope of this question. I’m currently working on a solution using iterate, where each step only calculates the strings the ‘next step’ (following transitions from the current statew) accepts, so it doesn’t recurse at all. You then only keep track of current states and the strings that got you into that state (which are the prefixes for the next states). What’s proving difficult in that case is detecting when a DFA that accepts a finite language will no longer return any results. I haven’t yet devised a proper stop-criterion for the take-while surrounding the iterate, but I’m pretty sure I’ll manage to get this solution to work. For this question, I’m interested in the fundamental question: can laziness and tail-recursiveness be combined or is that fundamentally impossible?

[1] Note that there are some restrictions on the site, like not being able to use def and defn, which may explain some peculiarities of my code.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-07T23:07:48+00:00Added an answer on June 7, 2026 at 11:07 pm

    The problem is that you are building something that looks like:

    (mapcat f (mapcat f (mapcat f ...)))
    

    Which is fine in principle, but the elements on the far right of this list don’t get realized for a long time, and by the time you do realize them, they have a huge stack of lazy sequences that need to be forced in order to get a single element.

    If you don’t mind a spoiler, you can see my solution at https://gist.github.com/3124087. I’m doing two things differently than you are, and both are important:

    1. Traversing the tree breadth-first. You don’t want to get “stuck” in a loop from q0 to q0 if that’s a non-accepting state. It looks like that’s not a problem for the particular test case you’re failing because of the order the transitions are passed to you, but the next test case after this does have that characteristic.
    2. Using doall to force a sequence that I’m building lazily. Because I know many concats will build a very large stack, and I also know that the sequence will never be infinite, I force the whole thing as I build it, to prevent the layering of lazy sequences that causes the stack overflow.

    Edit: In general you cannot combine lazy sequences with tail recursion. You can have one function that uses both of them, perhaps recurring when there’s more work to be done before adding a single element, and lazy-recurring when there is a new element, but most of the time they have opposite goals and attempting to combine them incautiously will lead only to pain, and no particular improvements.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have a question about Clojure: I am trying to learn the language by
Working on the problems on Project Euler to try to learn Clojure. I'm on
Currently I'm trying to learn Clojure and I would like to write a function
I am starting to learn the Clojure programming language. Are there any recommendations for
I try to learn a bit of Clojure because the language looks nice. But
I'm writing a simple IRC bot to try to learn more about Clojure, using
To learn the basics of OCaml, I'm solving one of the easy facebook engineering
I have been using ClojureBox with great success to learn both Clojure and emacs.
If I want to learn Clojure, should I start by learning Scheme or Common
I'm trying to learn Clojure, so I figured a good way to start would

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.