Fork me on GitHub
Lucas Jordan01:08:40

I am looking for cron/quartz like functionality that is idiomatic to the datomic cloud environment. Any suggestions? Thanks!


other than Clojure, are there JVM langs which .jar artifacts are primarily distributed as sources? (I mean for their ecosystems - .jars representing arbitrary libraries from their users. I'm less interested in .jars representing the compilers themselves) i.e. langs for which AOT distribution is less common, and a :classifier "sources" artifact will be quite redundant


is there a library or plugin that will change a [X.Y :refer :all] into a [X.Y :as xy] and then qualify all of the referred symbols to qualified symbols?


i have a project that exports a lot of symbols and it’s now reached the point where [game.core :refer :all] throws a MethodTooLarge error when compiling lol


are you sure just requiring it is the cause of this?


no, but i’m not sure how else this is happening


either way, seems like it’s better to qualify all of these symbols than try to refer them without thought, you know?


better for readability and clarity


can you start a new repl and do (require 'game.core) and see if you get the method too large error?


and yes i agree with you. i consider :refer :all an antipattern apart from clojure.test

Alex Miller (Clojure team)15:08:37

I don't get how :refer :all could cause that error


looking at it again, i think it’s actually my use of import-vars being too big (61 namespaces, 570 vars)


sadly, slamhound isn’t actively maintained anymore and fails on my project

Alex Miller (Clojure team)15:08:58

that seems far more likely

Alex Miller (Clojure team)15:08:01

also, don't use import-vars


Well, I'm not sure if the dislike is conceptual, or its because how Potemkin does it is unreliable (which it is), and doesn't play super well with tools


The issue with "put vars where you want them", is that overtime, there comes reasons to move a var elsewhere, and that's a breaking change, unless like with URLs, you could make the old-var a redirect. Potemkin lets you do that nicely. You can do (def a #'new/a) as well, but its at the Var level, so if you move a whole namespace, you kind of have to remember to keep going back and adding more vars into it. It's no a super big issue. Its come up with me where our team has a big library of Clojure functions, and we want to expose part of it as a lib for other teams to consume, but don't want them to need to pull in the big one we use. So you'd want to be able to create a separate lib that includes a selection of the namespaces from the big lib.

Alex Miller (Clojure team)23:08:21

If refactoring to maintain compatibility was the use case, then I’d feel more amenable to it, but almost every use of import-vars I’ve seen was not that but a priori to make an api that collected things from elsewhere


That's possible, I guess Potemkin's readme kind of talks about using it for that. But I've personally only wanted it in the scenario I described 🤷


The use case I have seen is exposing an API from implementation namespaces.


hi, please advice if I need to implement something like this in clojure:

import java.sql.SQLData;

class Address implements SQLData {

  public String street;
  public String city;
  public String state;
  public String zip;

  public String getSQLTypeName() { 
    return "address";

  public void readSQL(SQLInput stream, String typeName) throws java.sql.SQLException { 
    street = stream.readString();
    city = stream.readString();
    state = stream.readString();
    zip = stream.readString();

  public void writeSQL (SQLOutput stream) throws SQLException { 

i should look into the defrecord? not sure tho how i can specify fields with types

Asko Nōmm20:08:18

Why is it that this code works:

(repeatedly #(let [files-in-dir nil]
                   (prn "new iteration")
                   (Thread/sleep 1000)))
Whereas if I actually try to read files in a directory like so:
(repeatedly #(let [files-in-dir (scan-files-in-dir "./")]
                   (prn "new iteration")
                   (Thread/sleep 1000)))
I get a error: "class clojure.lang.Atom cannot be cast to class clojure.lang.IFn"

Asko Nōmm20:08:52

The scan-files-in-dir function does not use any atoms. It only iterates over the result of (.list (io/file directory))


How do people typically use sente in webapps with many components when the sente handlers need access to those other components (such as a db)? Do you just have a routing function that assoc's into the sente event message all the needed components?


I had a component that depended on sente (as the sink / source of data) plus all the components needed to implement the handlers, and it used a router

Marcus Rydberg21:08:16

For some reason log libraries seem to love using macros. They also seem to rely on & args a lot. That makes me want to apply them. Am I an evil person? Do I dare revive apply-macro?

Alex Miller (Clojure team)21:08:34

why do you want to apply them?


they love macros because because java logging libs all tell you which method is logging the call, and if you called the logging lib from a function it would always report that function's .invoke method instead of your actual call site


so in practice when I use logging libs I usually end up writing macros to extend the logging macros


@marcus.rydberg what do you mean by "revive" - did apply-macro exist somewhere? a macro only sees the literal form to expand so I fail to understand how apply would help

Marcus Rydberg21:08:21

Because I have what I want logged in a neat collection, but the loggging macro always seem to want it destructed, unrolled, whatever it's called. "listed without a surrounding collection". Sorry for Friday-evening aphasia.


of course if the macro you wrap uses & args you use [email protected] to splice the args into the call in your macro

Marcus Rydberg21:08:59

@noisesmith found it in some dark corners of the deprecated contrib package. 🙂

Marcus Rydberg21:08:13

(defmacro apply-macro
  "This is evil.  Don't ever use it.  It makes a macro behave like a
  function.  Seriously, how messed up is that?


then surely the solution is to use the accessing code for the data you want to log and call it in the macro invocation?


perhaps you'd be interested in the subject of structured logging - it's a whole thing and it's oriented to serializable data structures (usually via json) rather than strings

Marcus Rydberg21:08:25

I agree (if I understand you correctly) that the answer is a macro. But I've been deeply instilled with irrational macro-fear so I was hoping to avoid having to learn new things but it seems it has caught up with me.


or if the access patterns are predictable, you write another macro that unwraps the data in the way you want and calls the logging macro on the result

Alex Miller (Clojure team)21:08:47

presumably that log macro calls some log function - can you just call that directly?


@alexmiller I thought that it usually doesn't because that pollutes the underlying log lib functionality of showing class / method


so you end up with a macro that generates an interop form

Marcus Rydberg21:08:50

That's the other option @alexmiller, but it would be stepping in beside the intended public boundary of the library. I think.


I could be misremembering though it's been a while

Marcus Rydberg21:08:09

Thank you both for input. Still laughing about the docstring of the apply-macro. Gotta love this community.


double checking, I see that tools.logging at least does use a function underlying the macro - there must be some other layer taking care of the call site reporting(?)

Alex Miller (Clojure team)21:08:26

a lot of Java things use stack introspection for that I think


OK, that makes sense, and what I saw was every time I wrote a function to wrap a logging macro I'd end up seeing my function falsely reported as the location


Isn't the macro wrapper in tools.logging at least partly to get *ns* correct?


So that gets *ns* at compile time rather than runtime, where it's bound to the top-level calling ns or something?


and there must be something else eliding the tools.logging log* function and going up to your own caller in the impl somewhere...


Is there a better way to get the source code for a function’s var than slurping the file, line, and column number and read-stringing it?


@escherize You mean when (source fn-name) doesn't work?


Or are you asking for an alternative to the implementation of source which, yes, reads the source file and finds the var at that location?


The source isn't retained in the compiled code so there's nothing else out of the box that you could do.


source had slipped my mind, I was going to roll my own source . But maybe I will simply use it directly

Alex Miller (Clojure team)23:08:43

The underlying source-fn might be more useful than the macro


It be interesting to see a decompiler for Clojure. There are some for Java, but it be neat to go byte-code -> Clojure code, or byte-code -> java code -> clojure code (mostly for educational purpose)


bronsa made one and released the source a week after his talk with the fun challenge to decompile it if you were interested


That's actually awesome!


is the talk