This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-08-13
Channels
- # aleph (6)
- # architecture (29)
- # beginners (175)
- # cider (22)
- # clara (5)
- # cljdoc (5)
- # cljs-dev (28)
- # cljsrn (6)
- # clojure (62)
- # clojure-finland (7)
- # clojure-italy (7)
- # clojure-nl (2)
- # clojure-spec (23)
- # clojure-uk (194)
- # clojurescript (90)
- # core-async (2)
- # cursive (23)
- # datomic (41)
- # defnpodcast (2)
- # editors (4)
- # emacs (1)
- # figwheel-main (41)
- # fulcro (53)
- # hoplon (15)
- # hyperfiddle (4)
- # immutant (1)
- # jobs (7)
- # jobs-discuss (103)
- # lein-figwheel (9)
- # off-topic (34)
- # onyx (3)
- # parinfer (1)
- # portkey (1)
- # re-frame (7)
- # reagent (2)
- # remote-jobs (2)
- # rum (1)
- # shadow-cljs (148)
- # sql (54)
- # tools-deps (3)
- # vim (7)
If I define a function like so:
(defn foo ^double [^double x ^double y] (+ x y))
What combination of type hints / primitive casts / feng shui do I need on my calls to foo
such that the compiled bytecode will call foo
's .invokePrim
method and use the unboxed value coming back?I've been experimenting with clj-java-decompiler
:
user> (decompile (foo 1.0 2.0))
// Decompiling class: cjd__init
...
((IFn)const__0.getRawRoot()).invoke(const__1, const__2);
...
user> (decompile (+ ^double (foo (double 1.0) (double 2.0)) 3.0))
...
Numbers.add(RT.doubleCast(((IFn)const__1.getRawRoot()).invoke(RT.doubleCast(1.0), RT.doubleCast(2.0))), 3.0);
...
but it's possible that the decompiler is incorrectly inferring the compiled logic in practice.@aengelberg are you aware of https://github.com/gtrak/no.disassemble?
Does anyone know of a tool like https://github.com/benedekfazekas/mranderson that instead operates on plain Jar files instead of some higher level abstraction like Leiningen's project.clj? Or could point me in the right direction for doing that with mranderson? Thanks
There was something that seemed to wrap a maven plugin, but I struggled to understand quite what it was doing, and it was a lein plugin too, but less coupled.
i recall a podcast where they talked about dep including jars as source but i might be remembering wrong
you may be referring to the add-lib stuff (not yet merged)
but I think it would helpful to state what you want as I’m not sure
yeah, that’s why I think it would be helpful to actually start from the problem
I want to take jars (clojure/java), take their source files and move all namespaces/packages according to some predictable scheme (e.g. adding a prefix)
The problem I'm trying to solve by doing this is loading individual dependencies in potentially multiple versions. Specifically the cljdoc analyzer environment where I already have some dependencies that I currently cannot analyze in a version different than the one I have loaded.
Hope that makes sense. It's also not a huge issue for cljdoc yet, I was just looking around what might be out there.
dependencies of your analyzer are colliding with the dependencies of the projects you're analyzing?
not with their dependencies but dependencies of the analyzer might also be projects to be analyzed. Eg. I need org.clojure/tools.namespace but I won't be able to build docs for it in a different version than the one I have currently loaded.
@U09LZR36F not sure I understand the question? the analyzer is a slightly more complex mixture than tools.analyzer but yes, it might be that cljdoc wants to build docs for a new (or old) release of tools.analyzer. Currently it can't because it already uses a specific version of tools analyzer.
I was thinking that if tools.analyzer let you override how to find source files, then that would solve the problem
I could just say "use the version that should get analyzed" but that might break things, especially when trying to build for an old version
The cljdoc analyzer takes a directory of source files as input, is that what you mean?
@U050TNB9F those files are on the classpath though? why?
if they were not, requiring transitive namespace dependencies would fail, no?
So, if you could control how require
worked in tools.analyzer, you could use an isolated classloader.
yeah, maybe. sounds like a lot of work 😅
I've done the classloader thing a few times. It's even done in cider to support boot.
in java land, there are tools like Jar Jar Links (oof, I know) or Maven Shade to do stuff like this, but I’m not familiar with anything in Clojure
in autodoc, the project is split into the collector (which has no deps and merely analyzes and builds a data file), and a renderer project that takes the data file. That helps minimize the deps problem.
not sure how wide the issue is, but seems like you could maybe do this manually if the number of affected libs is small enough
Cljdoc ended up with the same approach autodoc seems to be taking.
But still, some deps (Clojure, ClojureScript, tns, Java cp, ...) for which it will be trickier to analyze all versions of. I’ll think of something :)
@U064X3EF3 mr anderson is a wrapper of jar jar links, the api is horrible
I have not used mranderson, but have done something intended to solve the same problem for Eastwood, called 'dolly', but it requires manually fixing up some changed require statements by hand in some cases: https://github.com/jafingerhut/dolly I hesitate to even mention it because it is a barely-working piece of code that you have to treat it just right or it useless.
It doesn't do much more than copy a namespace's source files from one project into another, attempting to rename all occurrences of one or more other namespaces as it goes, in Eastwood's case by prepending something like 'eastwood.copieddeps.proj<n>.'
hallo! anybody has a recommendation for a library to use for a slack bot?
@aengelberg the decompiler is correct, you're just forcing boxing because decompil
is wrapping the entire expression into a non-primitive returning function
try decompiling e.g. (Long/toString (let ..))
-- you'll see everything being unboxed until the call to Long.toString(long)
Hi, smb use manifold (https://github.com/ztellman/manifold), i can't find how create something like core.async go-loop only for manifold stream? (and smb known if use manifold.deffered/loop & recur, thread are parked or it alway take message from source)
@bronsa hmm I just tried that, doesn't seem to be working.
that's sort of what I was going for with the (+ ^double (foo (double 1.0) (double 2.0)) 3.0)
example above
ok, I just combined the two tips (make sure I'm calling a defn
ed function, and wrap it in TheType/toString
) and it seems to be working now:
user> (decompile (Double/toString
(let [d (double 1.0)]
(foo d d))))
// Decompiling class: user$fn__17583
import clojure.lang.*;
public final class user$fn__17583 extends AFunction
{
public static final Var const__2;
public static Object invokeStatic() {
final double d = 1.0;
return ((DDD)const__2.getRawRoot()).invokePrim(d, d);
}
public Object invoke() {
return invokeStatic();
}
static {
const__2 = RT.var("user", "foo");
}
}
nil
interestingly I had to wrap it in a let
to get it to work; (Double/toString (foo 1.0 2.0))
didn't work
with
(defn foo ^long [^long a ^long b]
a)
(defn bar []
(Long/toString (foo 1 2)))
I'm definitely getting clojure/lang/IFn$LLL.invokePrim:(JJ)J
are you sure you weren't doing a long -> double cast by mistake? (that's what I just did)
@skrat https://docs.datomic.com/on-prem/query.html#not-caluses interestingly, the anchor has a typo
@skrat datascript has a missing?
predicate https://github.com/tonsky/datascript/wiki/Tips-&-tricks#querying-on-a-missing-attribute