clojure

New to Clojure? Try the #beginners channel. Official docs: https://clojure.org/ Searchable message archives: https://clojurians-log.clojureverse.org/
cjmurphy 2020-12-14T00:04:36.485200Z

Just need to know the points. Just data, no graphics. I'm going to use cljfx, but that's irrelevant to the function I'm looking for. Any kind of plot. I know there's different strategies and then surely known algorithms. https://en.wikipedia.org/wiki/Graph_drawing. So 'just an XY scatterplot'.

2020-12-14T00:13:44.485700Z

https://github.com/generateme/cljplot

2020-12-14T00:14:47.486Z

There's not a ton of documentation but I've been using this to good effect. There are a bunch of examples in the "sketches" directory (results in "results" directory)

2020-12-14T00:15:12.486200Z

And it's possible to just use the scaling stuff here: https://github.com/generateme/cljplot/blob/master/src/cljplot/scale.clj

phronmophobic 2020-12-14T00:15:21.486500Z

ohh, that kind of graph. For layouting out graphs (not charts), I've only seen wrappers around graphviz so far

2020-12-14T00:16:06.486700Z

Oh, yeah sorry, I misunderstood as well

phronmophobic 2020-12-14T00:18:02.486900Z

some libraries that use graphviz under the hood: β€’ https://github.com/clojure/tools.deps.graph β€’ https://github.com/daveray/dorothy (it says it's still subject to change, but it hasn't changed in years)

phronmophobic 2020-12-14T00:19:20.487400Z

I would also be interested in a library that does graph layout for you that runs on the jvm (no graphviz). would be great to hear if you find something

βž• 1
phronmophobic 2020-12-14T00:21:09.487600Z

hmm, there is also https://github.com/totakke/jungerer which wraps http://jrtom.github.io/jung/ which has several graph layout implementations

cjmurphy 2020-12-14T00:35:20.488Z

Thanks @smith.adriane. Yes I might take at look and see if easy to get something out with one of the JUNG implementations, for instance https://github.com/jrtom/jung/blob/master/jung-algorithms/src/main/java/edu/uci/ics/jung/layout/algorithms/SpringLayoutAlgorithm.java. Will definitely share if I can layout a graph from Clojure.

πŸ‘ 1
dpsutton 2020-12-14T05:53:17.488900Z

anyone ever seen > Syntax error (VerifyError) compiling new at (/task/sync_databases_test.clj:143:1). > Operand stack underflow

βœ… 1
2020-12-14T08:00:13.490400Z

You might try using deftype instead of defrecord there

2020-12-14T08:05:13.490600Z

method resolution is slightly different between java8 and post java9, which could explain the put method confusion passing on java 8 but failing on java 11

ghadi 2020-12-14T13:04:00.000600Z

I would really like to see the clojure code that produced a verifier error. (Shame on lein for disabling verification)

dpsutton 2020-12-14T14:26:19.005100Z

The verification was an explicit Arg we added here. This is another time I’ve been bitten by the stacktrace thrown into a random temp file on a machine in the cloud. Not a huge fan of that default

alexmiller 2020-12-14T14:46:06.008500Z

Disabling the verifier is a bad idea, there is no good reason to do that (which is why you can’t in newer Java’s)

dpsutton 2020-12-14T14:46:45.009400Z

yeah. someone added this PR for exactly that reason. it doesn't work going forward and is deprecated in 13+ i think

alexmiller 2020-12-14T14:47:04.009900Z

If you can boil this into a small repro, would definitely like to see an ask question or jira ticket

dpsutton 2020-12-14T14:47:08.010100Z

i just added the option to print the stack trace to stderr so maybe that will give a bit more info

dpsutton 2020-12-14T14:47:18.010300Z

if i can get it there i absolutely will

dpsutton 2020-12-14T14:56:39.013600Z

#error {
 :cause "Operand stack underflow\nException Details:\n  Location:\n    metabase/task/sync_databases_test/MockJobExecutionContext.put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; @8: areturn\n  Reason:\n    Attempt to pop empty stack.\n  Current Frame:\n    bci: @8\n    flags: { }\n    locals: { 'metabase/task/sync_databases_test/MockJobExecutionContext', 'java/lang/Object', 'java/lang/Object' }\n    stack: { }\n  Bytecode:\n    0000000: 2a2b 2cb9 017e 0300 b0                 \n"
 :via
 [{:type clojure.lang.Compiler$CompilerException
   :message "Syntax error compiling new at (/Users/dan/projects/clojure/metabase/test/metabase/task/sync_databases_test.clj:143:1)."
   :data #:clojure.error{:phase :compile-syntax-check, :line 143, :column 1, :source "/Users/dan/projects/clojure/metabase/test/metabase/task/sync_databases_test.clj", :symbol new}
   :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 7115]}
  {:type java.lang.VerifyError
   :message "Operand stack underflow\nException Details:\n  Location:\n    metabase/task/sync_databases_test/MockJobExecutionContext.put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; @8: areturn\n  Reason:\n    Attempt to pop empty stack.\n  Current Frame:\n    bci: @8\n    flags: { }\n    locals: { 'metabase/task/sync_databases_test/MockJobExecutionContext', 'java/lang/Object', 'java/lang/Object' }\n    stack: { }\n  Bytecode:\n    0000000: 2a2b 2cb9 017e 0300 b0                 \n"
   :at [java.lang.Class getDeclaredConstructors0 "Class.java" -2]}]
 :trace
 [[java.lang.Class getDeclaredConstructors0 "Class.java" -2]
  [java.lang.Class privateGetDeclaredConstructors "Class.java" 3138]
  [java.lang.Class getConstructors "Class.java" 1944]
  [clojure.lang.Compiler$NewExpr <init> "Compiler.java" 2575]
  [clojure.lang.Compiler$NewExpr$Parser parse "Compiler.java" 2667]
  [clojure.lang.Compiler analyzeSeq "Compiler.java" 7107]
  [clojure.lang.Compiler analyze "Compiler.java" 6789]
  [clojure.lang.Compiler analyze "Compiler.java" 6745]
  [clojure.lang.Compiler$BodyExpr$Parser parse "Compiler.java" 6120]
  [clojure.lang.Compiler$FnMethod parse "Compiler.java" 5467]
  [clojure.lang.Compiler$FnExpr parse "Compiler.java" 4029]
  [clojure.lang.Compiler analyzeSeq "Compiler.java" 7105]
  [clojure.lang.Compiler analyze "Compiler.java" 6789]
  [clojure.lang.Compiler analyzeSeq "Compiler.java" 7095]
  [clojure.lang.Compiler analyze "Compiler.java" 6789]
  [clojure.lang.Compiler access$300 "Compiler.java" 38]
  [clojure.lang.Compiler$DefExpr$Parser parse "Compiler.java" 596]
  [clojure.lang.Compiler analyzeSeq "Compiler.java" 7107]
  [clojure.lang.Compiler analyze "Compiler.java" 6789]
  [clojure.lang.Compiler analyzeSeq "Compiler.java" 7095]
  [clojure.lang.Compiler analyze "Compiler.java" 6789]
  [clojure.lang.Compiler analyze "Compiler.java" 6745]
  [clojure.lang.Compiler$BodyExpr$Parser parse "Compiler.java" 6118]
  [clojure.lang.Compiler$LetExpr$Parser parse "Compiler.java" 6436]
  [clojure.lang.Compiler analyzeSeq "Compiler.java" 7107]
  [clojure.lang.Compiler analyze "Compiler.java" 6789]
  [clojure.lang.Compiler analyze "Compiler.java" 6745]
  [clojure.lang.Compiler$BodyExpr$Parser parse "Compiler.java" 6120]

dpsutton 2020-12-14T14:57:51.013900Z

it seems @hiredman’s guess about deftype versus defrecord was correct. that's some amazing bytecode intuition

alexmiller 2020-12-14T16:17:03.019200Z

thx

dpsutton 2020-12-14T05:53:29.489100Z

> Attempt to pop empty stack.

dpsutton 2020-12-14T05:53:44.489200Z

Syntax error (VerifyError) compiling new at (********/task/sync_databases_test.clj:143:1).
Operand stack underflow
Exception Details:
  Location:
    ********/task/sync_databases_test/MockJobExecutionContext.put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; @8: areturn
  Reason:
    Attempt to pop empty stack.
  Current Frame:
    bci: @8
    flags: { }
    locals: { '********/task/sync_databases_test/MockJobExecutionContext', 'java/lang/Object', 'java/lang/Object' }
    stack: { }
  Bytecode:
    0000000: 2a2b 2cb9 017e 0300 b0                 


Full report at:
/tmp/clojure-18430136797529807953.edn
Tests failed.

dpsutton 2020-12-14T05:54:22.489400Z

a PR removed the jvm option "-Xverify:none" and this was the result

dpsutton 2020-12-14T06:07:39.489600Z

tests passed on java 8 image but broke with this error on java 11

dpsutton 2020-12-14T06:16:00.489800Z

> Running with these options enables execution of Java programs that violate the Java Virtual Machine Specification. hmm. i'm hoping we're not purposefully emitting programs that violate the jvm spec

2020-12-14T07:59:56.490200Z

Hard to say without more of the stack trace to see where the method is being called but my guess is one of the interfaces you are pulling into the mockjobexecutioncontext is also defining a put method (JobExecutionContext) and defrecord implicitly defines put method (as a map) and something is getting confused about which method is being called

zerusski 2020-12-14T12:46:12.496400Z

Hi. Is there an interface lower level than ILookup? I want to "proxy" lookups to a record field but can't figure out how to get record fields once I overwrite the ILookup interface for the record. So something like this:

(defrecord foo [id map]
  ILookup
  (valAt [o key] 
    (or (get o key) 
        (get-in o [map key])))
I'm guessing get and get-in here would create an infinite lookup loop. Is there a way to do that? Thanks

Franklin 2020-12-14T13:01:56.498700Z

are there any advantages/disadvantages of using clojure.test over midje. please feel free to share articles that can help me answer this question

p-himik 2020-12-14T13:03:10.499Z

By Sean Corfield, on this Slack some time ago: > I personally would also recommend not using Midje. It's considered non-idiomatic and drags in a lot of transitive dependencies that can be problematic. > Just use plain old clojure.test > Midje isn't compatible with any standard test runners or test tooling.

borkdude 2020-12-14T13:03:31.499700Z

<3 clojure.test despite its shortcomings

borkdude 2020-12-14T13:04:23.001300Z

my projects run with both the cognitest test runner and leiningen, so you get the benefit of using more standard tools as well

zerusski 2020-12-14T13:08:43.001600Z

Was trying to figure out what defrecord does in the impl of ILookup it generates and I absolutely do not understand that magic. Essentially it amounts to (get __extmap key) and I can't even figure out how this magical __extmap gets into scope (a global or some special runtime thing?) and this isn't even used. Confused

Franklin 2020-12-14T13:08:52.002Z

@p-himik, @borkdude thanks :simple_smile:

Franklin 2020-12-16T11:52:03.093100Z

I feel like when it comes to mocking/stubbing, clojure.test is falling short. is midje better at this?

borkdude 2020-12-16T11:53:53.093700Z

@franklineapiyo You can consider 1) dynamic vars to swap out existing functions or make tests more flexible, 2) with-redefs (watch out, not thread-safe)

Franklin 2020-12-16T11:55:36.094Z

With option 1) wouldn't I have to re-write the functions I would like to test to use dynamic vars to reference the functions I would like to stub?

borkdude 2020-12-16T11:57:42.094400Z

yes

Franklin 2020-12-16T11:58:56.094600Z

oh boy! that doesn't sound very nice πŸ˜„

borkdude 2020-12-16T11:59:34.094800Z

sometimes it's worth it. E.g. if you're testing a function that does #(System/exit x) that's pretty much your only option. Or use with-redefs.

borkdude 2020-12-16T12:00:07.095Z

Every other mocking technique probably uses this behind the covers anyway

Franklin 2020-12-16T12:02:55.095200Z

the problem I've found with using with-redefs is that the tests will not tell you when the stubbed function was not called with the correct/expected arguments; unless of course, you write these instructions into your stub. so, you may have to add this logic to every stub or write some kind of macro to do this. But midje does it out of the box!

Franklin 2020-12-16T12:03:58.095400Z

I'm starting to want to use midje. I just want you guys to check the math on why I'm about to use midje πŸ˜†

borkdude 2020-12-16T12:04:57.095600Z

you have to write the expectations somewhere > unless of course, you write these instructions into your stub that would be the logical place to me.

borkdude 2020-12-16T12:05:14.095800Z

it's a choice between code that's easy to reason about or some black box testing lib you will depend on

Franklin 2020-12-16T12:05:31.096Z

true, true

borkdude 2020-12-16T12:11:37.096600Z

> clojure.test is simpler and less magical, with a larger ecosystem of tools and plugins. this is why I use clojure.test

borkdude 2020-12-16T12:11:47.096800Z

feel free to make your own choices :)

Franklin 2020-12-16T12:16:36.097Z

Franklin 2020-12-16T12:18:20.097400Z

here's a GIF from a show I enjoy ☝️ . Thank you very much.

borkdude 2020-12-16T12:19:14.097600Z

haha. which show is this?

Franklin 2020-12-16T12:24:38.097800Z

House M.D.

valerauko 2020-12-14T13:45:42.002100Z

I think you just call the java .get on the map your record closes on? Potemkin has plenty of magic like this https://github.com/clj-commons/potemkin/blob/master/src/potemkin/collections.clj I also saw pohjavirta do something similar too. https://github.com/metosin/pohjavirta/blob/master/src/pohjavirta/request.clj

zerusski 2020-12-14T13:48:52.002500Z

problem isn't in delegation - it'll work out of the box since record field value would probably implement its own ILookup. Problem is obtaining record field value in the first place since we are overriding this record's interface

zerusski 2020-12-14T13:49:41.002700Z

I'll have a look in those libs. Thank you fro pointers!

zerusski 2020-12-14T13:50:22.002900Z

Potemkin is cheating by rolling out its own type abstraction. I'd rather not go there

alexmiller 2020-12-14T14:39:00.005900Z

If you are changing lookup semantics you’re already there

alexmiller 2020-12-14T14:39:08.006300Z

This is what deftype is for

zerusski 2020-12-14T14:44:52.007100Z

yeah that's what I figured. IIUC I'll have to extend all the usual interfaces the moment I switch to deftype. Fair enough

zerusski 2020-12-14T14:49:14.010500Z

I ended up solving the problem I had differently without proxying, cause in this case it lended itself to this other solution (typical - 9 out of 10 times you don't need special non Clojure sematics). But I still hoped that there was a simpler way to do such delegation.

Felix M 2020-12-14T15:05:36.017900Z

Hi, what my options for sprinkling a few reactive components in a server side rendered Clojure app without going full SPA, is this doable with Rum? I'm looking to have form inputs filter the the db and return the results client side without incurring a full page refresh. #beginners #programming-beginners

msolli 2020-12-16T06:06:43.069400Z

@heyhey This is doable in Rum, and exactly why I use it. I build a SaaS-type web app, where all the pages are HTML pages served by Rum components in .cljc files. Some are completely static, while others have quite complex behavior.

Felix M 2020-12-16T16:04:28.103800Z

@msolli thanks, that's exactly the type of set-up I had in mind. Glad to hear its being used successfully.

valerauko 2020-12-14T15:41:03.018800Z

The extmap is just fallback (when you assoc in extra stuff), defined fields go the mapcat's way which I think closes over the values https://github.com/clojure/clojure/blob/38bafca9e76cd6625d8dce5fb6d16b87845c8b9d/src/clj/clojure/core_deftype.clj#L194-L195

user=&gt; (defrecord Bar [a])
user.Bar
user=&gt; (.__extmap (assoc (-&gt;Bar 12) :c 42))
{:c 42}

2020-12-14T16:32:05.019400Z

you might get better answers in #clojurescript but I haven't seen anyone talk about using rum in years

πŸ‘ 1
erwinrooijakkers 2020-12-14T18:39:10.021500Z

I am trying to create a Clojure Google Cloud Function and I have to specify the entrypoint of a leiningen console app (via lein create new app hello-world):

$ gcloud functions deploy jar-example --entry-point=hello_world_core$_main --runtime=java11 --trigger-http --source=target/uberjar
This entry-point is not correct. / is not allowed. Any suggestions on how to specify the entry-point correctly?

mozinator2 2020-12-15T17:53:11.054100Z

There are messages in the #google-cloud channel on how to do this. You need to create a Java file as a wrapper

erwinrooijakkers 2020-12-14T18:42:38.021700Z

@kevin.van.rooijen had started building a server side rendered reactive application using Reagent at https://github.com/kwrooijen/yggdrasil. But this is not yet production ready I think, but the idea of server side rendering but having Reagent at your disposal (and perhaps even connection with the backend) seems interesting and useful to me. Not sure if there are any other solutions for this

kwrooijen 2020-12-14T18:44:32.022Z

And no documentation πŸ˜„

kwrooijen 2020-12-14T18:44:46.022200Z

Except for this https://github.com/kwrooijen/yggdrasil-playground

2020-12-14T18:59:17.023100Z

it should be hello_world.core$_main

πŸ™ 1
2020-12-14T19:02:51.024Z

hello_world.core$main or elloworld_core$_main or anything like that is almost certainly not correct

2020-12-14T19:03:19.024600Z

those are all "jvm" names for clojure functions, and the gcloud api will have no idea what to do with a clojure function

erwinrooijakkers 2020-12-14T19:16:51.026100Z

Thanks! I forgot the logic, this helps πŸ™‚. Still get an error though with --entry-point=hello_world.core$_main

Build failed: build succeeded but did not produce the class "hello_world.core" specified as the function target: Error: class not found: hello_world.core; Error ID: fb35dca7

erwinrooijakkers 2020-12-14T19:17:30.026400Z

maybe bash substitution

erwinrooijakkers 2020-12-14T19:18:58.026700Z

Ah and with β€˜β€™ it’s:

Invalid value 'hello_world.core$_main': Entry point name must contain only Latin letters (lower- or upper-case), digits, dot (.) and underscore (_), and must be at most 128 characters long. It can neither begin nor end with a dot (.), nor contain two consecutive dots (..).

2020-12-14T19:21:24.027500Z

you need to look at the documentation for gcloud functions and see what kind of thing it expects as an entry-point, instead of just putting the names of random things in

2020-12-14T19:27:24.029Z

if entry-point takes a class name, you'll need to ensure that the named class exists in the jar file, and is not a class that is generated while loading clojure code, because gcloud almost certainly doesn't know about loading clojure code

2020-12-14T19:28:02.029800Z

and if it is a class name, that class almost certainly will need at least a specific method, but likely to implement some interface

Felix M 2020-12-14T21:02:15.030100Z

@erwinrooijakkers Thanks, I'll check it out

tanzoniteblack 2020-12-14T23:24:48.030700Z

originally posted this to #beginners for lack of a good idea to put it, @arthur recommended I post this here instead.

p-himik 2020-12-15T09:26:47.033500Z

Some related projects, although with a larger scope of running the tasks concurrently and maybe in a distributed manner: - https://github.com/framed-data/overseer - https://github.com/mikub/titanoboa - https://github.com/schmee/daguerreo

phronmophobic 2020-12-14T23:31:49.031200Z

the only other library I can think of in the same space is https://github.com/hoplon/javelin, but it's cljs based. Another solution is to wrap functions using https://github.com/clojure/core.memoize and have it automatically cache repeated calculations.

tanzoniteblack 2020-12-14T23:36:37.031600Z

thanks