This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-10-02
Channels
Someone incorrectly ‘improved’ Rich’s reply to a StackOverflow question in 2020. I don’t know enough about the site to fix it. Maybe someone who does can. It’s just the “seq s” which should be “seqs” and, I think, the ‘not’ has been bolded when it was not. https://stackoverflow.com/questions/1641626/how-to-convert-lazy-sequence-to-non-lazy-in-clojure. It’s interesting that someone can tweak a response on there and change what one has posted (minor as it is in this case). I’m a bit OCD and would be annoyed to find answers I made changed in this way.
Thanks! I can sleep now.
It's pretty common for people with sufficient reputation on SO to edit answers (and questions) for what they think are minor formatting or grammatical errors... but, unfortunately, a lot of people gain that reputation without having sufficient command of English grammar or, indeed, the subtleties of accurate formatting in some technologies 🙂
(disclaimer: I have sufficient rep to edit Q & A on SO too but I try you use it only to fix the most egregious errors I see...)
Which is great (to fix things like that) as I would imagine an accepted answer, possibly with upvotes, that is incorrect could create quite a bit of consternation. 👍
SOLVED
My MVE was failing because there is no generator for fn?
. My real problem was a hidden recursion in my base case. Once I pulled that out everything is fine.
I’m just learning clojure.spec.alpha
. I’m writing specs for testing a compiler back end (LPython [sic],
). The input to the back end is a recursively defined tree structure. I want to generate test cases. I present below an MVE that illustrates my question. I’m able to check (`s/valid?`, s/conform
) hand-written trees. The generator, however, only occasionally produces usable results. Most of the time, it throws an exception. However, it occasionally does produce a usable example, so I am not completely dumb! What can I do to improve the following so that it produces usable examples more frequently? Or should I be doing things some other way, completely? I will be grateful for any guidance!
(ns asr.core
(:gen-class)
(:require [clojure.spec.alpha :as s]
[clojure.spec.gen.alpha :as gen] ))
(s/def ::recur-tree-mve
(s/or :base (s/or :i integer? :f fn?)
:recur (s/map-of #{:left :right :op} ::recur-tree-mve)))
(s/valid? ::recur-tree-mve 42)
(s/valid? ::recur-tree-mve {:left {:left 5, :right 8}, :op +, :right 2})
(def RECURSION-LIMIT 1) ; careful!
;; for interactive testing in CIDER:
;; C-x C-e after the closing parenthesis
(binding [s/*recursion-limit* RECURSION-LIMIT]
(->> ::recur-tree-mve
s/gen
gen/generate ))
I'm just guessing here, but I don't think there's a built-in generator for fn?
(see https://github.com/clojure/spec.alpha/blob/master/src/main/clojure/clojure/spec/gen/alpha.clj#L132). You might need to provide a named spec (and a generator) for that function case
Good point. Let me modify it to be a string. I think the problem is the recursion, as the exception prints nil
nil
I usually debug such problems by looking at the successfully generated values and then trying to figure out what branch of the spec is missing -> there's probably something there that doesn't generate successfully
ah, ok
Well, turning things into strings worked, so I need another MVE.
My original fails recursion, but it’s too complicated to post
I’ll debug my original the way you suggested. Maybe it’s something else.
(i’m grateful for your attention :)
no problem, I hope you'll get your problem sorted. fyi: there's also the #clojure-spec channel that specializes in spec problems/questions
Actually, I noticed amidst my cruft that my “base case” was impure and had a deep recursion in it. Once I hoisted it to top-level of the s/or it got cleared up! You solved it! ty again.
This you? https://youtu.be/wASCH_gPnDw I think that was one of the first Clojure videos I saw.
(with-redefs [conj dissoc] (conj {:a 1} :a))
=> {}
(with-redefs [inc dec] (inc 1))
=> 2
(with-redefs [inc dec] (@#'inc 1))
=> 0
Why is inc
special in this regard... presumably it's a math optimization and unavoidable, but I wonder if there is a way I can sidestep the optimization (for example in test code) by setting a flag, redefining some behavior. Where should I look in the Clojure source to understand this better?Oh I see! Thank you.
(alter-meta! #'inc dissoc :inline)
(with-redefs [inc dec] (inc 1))
=> 0