Fork me on GitHub

I am guessing that if some function A included in Clojure calls function B, and I instrument B, then because of direct linking within default Clojure JAR, A will still call un-instremented version of B? And building my own Clojure with direct linking disabled is probably best way to enable A to call instrumented version of B?


Makes sense. Thx

Alex Miller (Clojure team)00:01:07

There is a build property you can set in the Clojure build (we run the tests both with and without on CI)


I must be doing it wrong. I've tried "mvn -Ddirectlinking=false clean package install", and even edited build.xml to change directlinking to false in there, but instrument'd B isn't causing A-to-B call to fail as I think it should. I'll keep experimenting to see where I'm going wrong.


@andy.fingerhut beware of inlining maybe


A is, or actually a function/protocol implementation that it calls, that calls B = clojure.set/union, where clojure.set/union is the function I'm trying to instrument.


Ugh. I think I forgot that build.xml only affect ant builds, not mvn builds.




(or at least that's what we have in our script for production processes -- and we assume it's false by default elsewhere)


I believe that flag is what tells the Clojure compiler whether to direct link user Clojure programs, or not. It doesn't seem to affect whether Clojure core code is compiled with direct linking (i.e. it still seems to have direct linking between my A and B functions that are both within Clojure itself)


I can avoid direct linking within Clojure itself by building it from source after changing true to false for directlinking inside of pom.xml


I haven't found the right incantation to make that happen from the command line, without editing pom.xml


Ah, OK, misread what you were attempting then. Sorry.


Given that it's hardcoded in pom.xml I would not expect it could be overridden at the command-line (but my mvn-fu is weak).

Alex Miller (Clojure team)01:01:19

You can override it (that’s what the clojure matrix builds do). Maybe that flag is only for test compilation. Sorry, on my phone and haven’t looked at it in a couple years.


@alexmiller No worries. Hand-editing pom.xml is doing the trick for me, and I don't need it automated for any personal reasons. I suspect you may be correct that the command line options might only be affecting compilation of Clojure tests.

Alex Miller (Clojure team)01:01:57

Oh, it is just for testing - see the profile definitions in the pom

Alex Miller (Clojure team)01:01:10

Activating the different profiles will change the flag

Alex Miller (Clojure team)01:01:05

You change the compilation for Clojure itself in build.xml

Alex Miller (Clojure team)01:01:23

In the compile-clojure target

Alex Miller (Clojure team)01:01:38

There is a sysproperty there

Alex Miller (Clojure team)01:01:59

I think you’ll have to hard code that change


If I get a reproducible way to build Clojure in this way, is it of any use to add it to dev wiki ?

Alex Miller (Clojure team)01:01:34

Sure, although I’m not sure how wide the need is for it

Alex Miller (Clojure team)01:01:17

Stu sometimes runs with just the src too, no aot at all


is there any way to write a spec for a multimethod?

Alex Miller (Clojure team)13:01:33

Currently, no. You can separate the dispatch function though and spec that if you like


thanks, that's what i've been doing so far but i was wondering if spec contained some syntax sugar for this


@alexmiller I understand the need is not very wide for building Clojure without direct linking, but I took a shot at adding a short section with instructions for how to do so at the end of this wiki page. Feel free to delete it if it is not useful enough, or edit otherwise to your heart's contents:


how do I both have

(s/and vector? (s/cat :a int? :b (s/* string?)))
and generator for free? this exact form gives up on generating vector? part


I do have to use gen/let, etc. don't I?


ideally the API would be such that you could specify that the default generator for (s/cat :a int? :b (s/* string?)) be transformed with (gen/fmap vec ___)


I don't think the spec API makes that easy though


so I need to extract s/cat as dedicated spec, and use it both in s/and spec definition and generator


or is there a "shorter" way?

Alex Miller (Clojure team)13:01:39

cat + vector is something that is quite difficult to do atm while retaining conform, generator, form, etc and a known gap. There are various ways to get parts of those but it’s hard to get all of them. This is certainly something I’ve run into and you can see it in some of the core dsl specs. I’ve come to the conclusion that a built in s/vcat would solve all of the cases I’ve run into but I think Rich is looking for a more composable solution still


s/vcat is definitely an ok solution for an application code, but smells like "giving up" in a library opieop

Alex Miller (Clojure team)13:01:18

Which is one reason this is still unresolved :)

Alex Miller (Clojure team)13:01:55

There is overlap here between regex ops and coll-of which both work on colls. Ideally those features could be more easily composed


Is there an "easy" way to overwrite :min-count :max-count of the s/coll-of s/map-of specs' generators "inline"? e.g. for REPLing. Or will I have to provide brand new generators for those and use them in s/with-gen?

Alex Miller (Clojure team)18:01:14

the generators will respect the min/max count you gave them

Alex Miller (Clojure team)18:01:52

but you can do something like (s/with-gen (s/coll-of int? :max-count 100) #(s/gen (s/coll-of int? :max-count 3)))


I am asking, if there is shorter way than you wrote. Many colls-of I speced as a standalone specs, and it would be cool to reuse those with something like

(s/def ::my-coll-spec (s/coll-of int? :max-count 100))
(-> ::my-coll-spec
  (with-opts :min-count 5 :max-count 10)


2 main use cases for this for me, are: - do not generate too many, because I want to eyeball it. - do not generate too few, like (s/exercise) tends to do for first few samples (or all, if you give it small sample size (s/exercise ::my-spec 2))

Alex Miller (Clojure team)19:01:14

in short, no. you can give exercise a generator override map though


I remember that, but it is basically the same effort stuff-typing- and copypaste-error-wise for these 2 usecases. thank you


When I have (s/conform (s/merge ::spec-1 ::spec-2) my-data) this only seems to conform values in the last merged spec, not the first one. If you swap the spec order, you get conformedvalues from ::spec-1 instead but not ::spec-2 -- is that by design or is it a bug in s/merge? /cc @alexmiller


(if I change s/merge to s/and I get conformed values from both specs)

Alex Miller (Clojure team)22:01:29

By design s/merge does not flow conformed values


OK. That was just surprising, given the docstring.


So I'm going to need (s/and (s/merge ::spec-1 ::spec-2) ::spec-1) for my particular use case (so that it still generates), right @alexmiller?


(I know that checks ::spec-1 twice)

Alex Miller (Clojure team)23:01:46

The generator for merge will produce maps that validate for both specs

Alex Miller (Clojure team)23:01:47

So you shouldn’t need the and here for generation


Right, but I need the s/and to get conformance flowing through the specs.


If I want both conform-flow and generation, I need both the s/and and s/merge.


The s/merge on its own doesn't flow conformance (but will generate fine).


spec-tools is already doing the rogue coercion stuff, so woudn't make the lib any more bad in that sense.


The s/and on its own doesn't generate properly (but will flow conformance).


This is because we have specs that conform API parameter strings to long, double, date etc -- and I want to be able to combine them and get full conformed values across the combination and get generation across the combination 🙂


(cue @alexmiller saying "Well, don't do that!" 🙂 )

Alex Miller (Clojure team)23:01:58

Didn’t anyone ever tell you not to do coercion?