clojure-spec 2021-09-21

is there ever a situation where the :ret value passed to a (failing) fdef :fn checker would diverge from the value you get when you run the function in question with the associated :args manually ?

(I'm seeing this currently and it's a bit baffling)

these are the reported values:

:cljs.spec.alpha/value
  {:args {:maps ({:A/A ""} {:A/A ""})}, :ret {:A/A " "}},

I think unless itโ€™s being conformed into that different value it will be the same. You could try doing:

(s/conform (:ret (s/get-spec `your-function)) {:A/A ""}) 
as a sanity check to make sure your spec isnโ€™t changing it during conforming.

the :ret spec here is simply map?

but for completeness:

utils.utils=> (s/conform (:ret (s/get-spec `-merge-attribs)) {:A/A ""})
{:A/A ""}

could this be a bug in clojure spec ? it is in alpha after all. @alexmiller ?

Alex Miller (Clojure team) 2021-09-22T18:17:40.135400Z

sorry, can you re-explain?

is there ever a situation where the :ret value passed to a (failing) fdef :fn checker would diverge from the value you get when you run the function in question with the associated :args manually ?

these are the reported values:

:cljs.spec.alpha/value
  {:args {:maps ({:A/A ""} {:A/A ""})}, :ret {:A/A " "}},

this is the manual repl invocation of the function in question:

utils.utils=> (-merge-attribs '({:A/A ""} {:A/A ""}))
{:A/A ""}
the manual repl invocation is the "correct" one

Notice that the one reported by spec includes a \space and the one returned from the manual invocation is merely the empty string.

(the :ret that is)

Alex Miller (Clojure team) 2021-09-22T18:25:08.136600Z

it seems like you're asking me a question about your function, not spec

Alex Miller (Clojure team) 2021-09-22T18:26:05.136800Z

maybe there is more here than you can "see" - that "empty" string could have a Unicode non-breaking space or something in it

Alex Miller (Clojure team) 2021-09-22T18:26:36.137Z

or zero-width space, whatever that weird unicode thing is

Alex Miller (Clojure team) 2021-09-22T18:28:33.137200Z

in general, my answer to your original question is no (unless you're using spec :stub instrumentation or something)

i think you misunderstood.

spec says that for some input a specific return value is returned. when i run that function manually in the repl with the exact same input a different value is returned.

i.e., "" != " "

regardless what that character is

empty string is empty string

" " is not empty string

Alex Miller (Clojure team) 2021-09-22T18:47:00.138600Z

a 1-character string with a Unicode zero-width space character looks like an empty string

is there any way to get the raw characters to be printed ?

from what i've seen spec seem to report escape sequences for those

like \b, \f etc etc

Alex Miller (Clojure team) 2021-09-22T18:47:49.139600Z

not those

Alex Miller (Clojure team) 2021-09-22T18:48:07.139800Z

U+200B

ah, ok. thanks. any other characters like that i should know about ?

Alex Miller (Clojure team) 2021-09-22T18:48:36.140200Z

well, that's one I've had this problem with. there are probably others

hehe ๐Ÿ™‚ too bad https://clojuredocs.org/clojure.core/char-escape-string doesn't exist in cljs (although seems that wouldn't cover all of these anyway)

Alex Miller (Clojure team) 2021-09-22T18:49:28.140600Z

you add a debug in your :fn function to print the count of the input strings or map char etc

๐Ÿ‘ thx

Alex Miller (Clojure team) 2021-09-22T18:50:09.141Z

I'm just guessing here - this is a possible answer that matches what I see, but you should validate

yes of course

Alex Miller (Clojure team) 2021-09-22T18:51:15.141400Z

these kinds of things happen with generative tests :)

unfortunately i think it might be something else:

comparing v: '1 1', and: '1 1', count v: 5, count joined: 5 false

ooh, there's two non-printable chars in there

and they're probably in opposing positions

found it. silly mistake.

i added a spurious reverse on the array of values i was comparing against

might be worth thinking about how to better report string values (adding perhaps unicode escapes for these as well as the platform default escapes)

thanks for your help!

fyi... i had used simple-type-equatable as my inner-type for a recursive map gen. if i had used instead simple-type-printable-equatable, this probably wouldn't have happened

this is the manual repl invocation of the function in question:

utils.utils=> (-merge-attribs '({:A/A ""} {:A/A ""}))
{:A/A ""}

the manual repl invocation is the "correct" one

(i have deleted the target/ directory and restarted the repl so it should not be a stale code issue)