beginners

Getting started with Clojure/ClojureScript? Welcome! Also try: https://ask.clojure.org. Check out resources at https://gist.github.com/yogthos/be323be0361c589570a6da4ccc85f58f.
2021-05-13T02:25:16.102200Z

Did you try using proxy instead? It can extend a Java class and override its methods as well, and is more convenient when it is possible to use it.

2021-05-13T02:34:51.102400Z

Otherwise you might need to show your macro implementation if you want help

2021-05-13T02:36:30.102700Z

Or do you need help with writing such a macro?

2021-05-13T02:43:36.102900Z

I see this a lot with lazy-seq implementation, some people will lazy-seq the rest, and some will lazy-seq the whole thing. I don't think there's always a reason why people chose one over the other, as more they just did.

2021-05-13T02:45:03.103100Z

In practice it means you shouldn't treat things as fully lazy, but mostly lazy, there's a few functions here and there that end up not being fully lazy, like line-seq, so if you want to be fully lazy, you should design things that way yourself.

Ivan Koz 2021-05-13T02:45:29.103300Z

most of the times documentation says "returns a lazy-sequence" however if first element was already realized the returned sequence is not that lazy

2021-05-13T02:56:39.103500Z

Ya, that's what I mean, you should most of the time think of something that says lazy or returns a lazy-seq as "mostly lazy" and not "strictly lazy". Because there's a lot of edge cases where you'll have more elements evaluated then you'd expect. So none of the lazy sequence machinery guarantees full 1 element at a time lazy was including the first element.

šŸ‘ 1
2021-05-13T02:58:03.104Z

Yes, this is kind of disappointing when you were actually wanting to be fully 1 element at a time lazy, and hoping you could just use Clojure's lazy sequence functions to do so.

Ivan Koz 2021-05-13T02:58:39.104200Z

Not so to say disappointing, just unexpected, not documented properly.

šŸ‘ 1
2021-05-13T02:59:44.104500Z

That's one of the reasons you'll hear advice that says, don't mix side-effects and sequence functions together. Cause if say you send an email on realizing an element, there's be a lot of occasion you might be surprised like oh.nonit sent way too many emails.

2021-05-13T03:00:40.104700Z

Ya, I agree with you there. More consistent terminology in the documentation would be good.

2021-05-13T03:02:48.104900Z

The whole lazy sequence in Clojure is best thought of as an optimization for performance and memory use. And not really as a mechanism to implement lazy evaluation for your own use cases.

Ivan Koz 2021-05-13T03:03:25.105200Z

yep, for that we have promises, futures

2021-05-13T03:04:47.105500Z

Ya, promise, delay, or using transducers. You can also do it with lazy-seq, but you need to be careful, cause some of the sequence functions will realize more than you might want. If you keep to your own functions and lazy-seq it can work as well.

2021-05-13T03:07:26.105800Z

Now why is line-seq like this is hard to say and probably speculation. I wonder if the type hint makes it it needs to be this way :thinking_face: It's possible if wrapped around lazy-seq the hint is lost? Or you know could just have been an afterthought, like no one thinking it mattered if the first line was read immediately or not.

Ivan Koz 2021-05-13T03:08:49.106100Z

or as we concluded to fail-fast if buffered reader\\file misbehaves

2021-05-13T03:09:32.106300Z

Ya possible

2021-05-13T03:12:49.106500Z

I've come to realize that most details in Clojure often have good reasons and were thought through with a trade off chosen, but that still, with all that thoughtful process, there are details that slip through and were "accidental" in a sense, or overlooked. And sometimes it's hard to say if you've got a case of something that's overlooked, or of something that was a conscious choice but wasn't documented.

2021-05-13T03:13:42.106800Z

Whenever you learn about some details like this, please go to http://ClojureDocs.org and add a notes or example for it. That stuff can really help others, even future you.

2021-05-13T03:48:49.107100Z

I think I need a specifically named Class, unfortunately. Unfortunately the actual macro is wrapped up in proprietary code. Let me try to put together a toy example and I'll come back.

2021-05-13T03:49:37.107300Z

I don't think it's so much writing the macro as making the resulting class visible to aot at compile time.

2021-05-13T03:53:02.107500Z

Well there's a :name property you can pass to gen-class to give it whatever name you want (it's the fully qualified package name + class name)

2021-05-13T03:55:20.107800Z

If you run macroexpand-1 on your macro, do you get the correct gen-class call?

2021-05-13T03:57:59.108Z

Also, does your macro generate a (ns) or a (gen-class) ? I'd suggest the latter

2021-05-13T03:59:17.108300Z

And make sure your macro calls are top-level, otherwise they won't run at compile time

2021-05-13T04:00:18.108500Z

Well I get something that compiles and looks OK to me. When I put the name of the class in the :aot clause of my project file, the compiler claims not to see it. Maybe I'm not specifying it quite right. I'm away from my desk now, but I'll concentrate on that when I revisit the problem.

2021-05-13T04:00:40.108700Z

The macro generates gen-class statements.

2021-05-13T04:01:46.108900Z

I'm defining the macro in one module and calling it in my 'core' module at top-level.

2021-05-13T04:02:14.109100Z

Thanks for your help!

2021-05-13T04:02:48.109300Z

Oh, so don't put the class name in :aot

2021-05-13T04:03:17.109700Z

Put the namespace name of the clojure file that contains the calls to your macro

2021-05-13T04:04:12.109900Z

Ah. So if the full path is my.ns.MyClass, the aot should be 'my.ns'?

2021-05-13T04:05:14.110100Z

No, it should be like:

(ns foo.bar)
 
(gen-class
  :name my.ns.Class
  ...)
And in :aot in project.clj you want to put foo.bar

2021-05-13T04:06:07.110300Z

Ah! The ns containing the the macro call?

2021-05-13T04:06:09.110500Z

Which I mean, yes if you class is called foo.bar.MyClass (assuming my example), then you just want to put foo.bar

2021-05-13T04:06:17.110700Z

Yes the macro call

2021-05-13T04:06:49.110900Z

OK. Yeah. Sure, that makes perfect sense now.

2021-05-13T04:07:22.111100Z

Basically you don't compile the gen-class, you compile a Clojure source file which will contain calls to (gen-class ...) inside it at the top level, and when compiling that Clojure source file, the compiler will also emit Class files for each of the gen-class directives it encounters.

2021-05-13T04:09:36.111300Z

Yes, yes, yes. That was the missing piece of my mental model. Thanks @didibus! I have to step away now, but I thank you for clearing that up for me!

2021-05-13T04:10:07.111500Z

No problem, hopefully that'll solve your issue.

arielalexi 2021-05-13T08:17:36.114100Z

Hey everyone šŸ™‚ I was wondering is there an easy way to convert a project that was created with a project.clj file (the project was created with leiningen ) to dep.edn project?

2021-05-13T08:38:12.114300Z

https://github.com/hagmonk/depify

šŸ‘ 2
stagmoose 2021-05-13T08:52:23.115800Z

- Hi, recently I am trying to use [react-flow](https://github.com/wbkd/react-flow) in my project and I am really new to cljs šŸ˜¢. - I am using shadow-cljs in my project and I've install the npm package using npm install react-flow-renderer and put (:require ["react-flow-renderer" :default ReactFlow]) in my core.cljs file - But for the next step I tried to implement this demo in [ React Flow - Overview Example](https://reactflow.dev/examples/) page yet didn't know how to start. - In that example page, I know I should probably represent the array of data objects in initial-elements.js using [ js-obj ](https://cljs.github.io/api/cljs.core/js-obj) (am I correct ? :rolling_on_the_floor_laughing:) - But next, in the index.js , how could I wrap jsx syntax in cljs, for example , this part:

return (
    <ReactFlow
      elements={elements}
      onElementsRemove={onElementsRemove}
      onConnect={onConnect}
      onLoad={onLoad}
      snapToGrid={true}
      snapGrid={[15, 15]}
    >
      <MiniMap
        nodeStrokeColor={(n) => {
          if (n.style?.background) return n.style.background;
          if (n.type === 'input') return '#0041d0';
          if (n.type === 'output') return '#ff0072';
          if (n.type === 'default') return '#1a192b';

          return '#eee';
        }}
        nodeColor={(n) => {
          if (n.style?.background) return n.style.background;

          return '#fff';
        }}
        nodeBorderRadius={2}
      />
      <Controls />
      <Background color="#aaa" gap={16} />
    </ReactFlow>
  );
- Is there anyone have relevant experience or know how to solve this problem. Thanks in advance! šŸ»

Adrian Smith 2021-05-14T12:29:05.215300Z

Could probably use reagent to replicate those jsx components using cljs data structures

stagmoose 2021-05-14T13:13:13.219800Z

@sfyire Thanks for your kind reply. This is my attempt to translate but it didn't work.

stagmoose 2021-05-14T13:14:19.220Z

(ReactFlow {:elements elements
             :style graph-styles}))
I believe the problem come from this part but haven't figure out how to solve it.

stagmoose 2021-05-14T13:16:11.220200Z

This is my browser's warnings. Thanks again šŸ™

stagmoose 2021-05-14T14:39:41.220800Z

Update: I finally got to solve it by using :> in reagent

Endre Bakken Stovner 2021-05-13T12:17:19.117100Z

I am trying to translate the following calls to cljs:

var g = new dagre.graphlib.Graph();
g.setGraph({});
g.setDefaultEdgeLabel(function() { return {}; });
g.setNode("kspacey",    { label: "Kevin Spacey",  width: 144, height: 100 });
My attempt:
(let [g (dagre/graphlib.Graph.)
        _ (g.setGraph (js->clj {}))
        _ (g.setDefaultEdgeLabel (js->clj #(fn [] {})))
        _ g.setNode("kspacey",    { label: "Kevin Spacey",  width: 144, height: 100 });
It fails with

Endre Bakken Stovner 2021-05-13T12:17:54.117700Z

Any tips? Also, is this a question more suited for #clojurescript?

Endre Bakken Stovner 2021-05-13T12:18:39.118300Z

Note that I am not trying to use the g object in the hiccup. I am just trying to create it in a let.

Jakob Durstberger 2021-05-13T12:23:43.120900Z

This might be helpful https://lwhorton.github.io/2018/10/20/clojurescript-interop-with-javascript.html#function-invocation The way to invoke functions is `([func-name] [target] parms) and js->clj us used to convert javascript types into clojure types. You probably want the opposite clj->js I think this should be closer. not sure about the dare/graphlib.Graph though

(let [g (dagre/graphlib.Graph.)
        _ (.setGraph g (clj->js {}))
        _ (.setDefaultEdgeLabel g (fn [] {}))

Endre Bakken Stovner 2021-05-13T12:25:28.121300Z

D'oh, I meant the other way around. cljs->js.

Endre Bakken Stovner 2021-05-13T12:25:33.121500Z

Thanks for the link.

Edward Ciafardini 2021-05-13T12:28:09.122700Z

Hey there - I am trying to use clojure to separate an integer of variable length (ie 15_5_212518674225 => 1-5-5-2-1-2-5-1-8-6-7-4-2-2-5) into two separate vectors splitting every other number. The int would turn into this after the split: [1 5 1 5 8 7 2 5] and [5 2 2 1 6 4 2] .

Jakob Durstberger 2021-05-13T12:29:01.122800Z

Iā€™d probably pull the setGraph setDefaultEdgeLabel and setNode into the let body. And you can use -> and thread the calls like so

(-> g
  (.setGraph (clj->js {}))
  (.setDefaultEdgeLabel (fn [] {})))

Endre Bakken Stovner 2021-05-13T12:39:25.123800Z

Probably not pretty but:

(let [n 155212518674225 n-str (str n)]  [(take-nth 2 n-str) (take-nth 2 (rest n-str))]) ;; [(\1 \5 \1 \5 \8 \7 \2 \5) (\5 \2 \2 \1 \6 \4 \2)]

Jakob Durstberger 2021-05-13T12:42:45.123900Z

I think thatā€™s not too bad. My first idea was way worse šŸ˜„ Youā€™d probably have to convert the characters back to integers

(let [n 155212518674225
      n-str (str n)
      nums (map #(Integer/valueOf (str %)) n-str)]  
  [(take-nth 2 nums) (take-nth 2 (rest nums))])

šŸ‘ 1
Endre Bakken Stovner 2021-05-13T12:46:17.124200Z

The above worked, thanks!

Jakob Durstberger 2021-05-13T13:00:14.124500Z

:thumbsup: no worries šŸ™‚

puercopop 2021-05-13T14:03:39.129600Z

I'm looking for the equivalent of macrolet for cljs. I found clojure/tools.macro but it only seems to be for clojure not clojurescript.

R.A. Porter 2021-05-13T14:07:49.130200Z

Yours are much shorter and simpler than mine, certainly...

(let [n 155212518674225]
    (->> n
         str
         (partition 2 2 [\x])
         (apply map vector)
         (map #(filter #{\0 \1 \2 \3 \4 \5 \6 \7 \8 \9} %))
         (map #(map str %))
         (map #(map (fn [x] (Integer/parseInt x)) %))
         (map vec)))

Edward Ciafardini 2021-05-13T14:14:37.130400Z

oooo pretty :)

orpheus 2021-05-13T14:50:20.132800Z

Hello everyone. How do I use the repl to call a function and use itā€™s result (an access token) in other functions? In bash I call a login function and save the accessToken to a variable I can use in my other rest calls, whatā€™s the clojure-idiomatic way to do this? Iā€™d like to be able to call (login environment) and then have my following calls use the accessToken from that login result

emilaasa 2021-05-13T15:10:56.135400Z

If I was just messing around in the REPL exploring some api, I'd do (def access-token (login environment)) and use the access-token directly, that would define a var which is a global variable inside that namespace.

emilaasa 2021-05-13T15:12:46.135600Z

When running production code it might be more likely that I had the token as an environment variable and used System/getenv to pull in the variable, possibly in a let block instead to limit it's scope.

emilaasa 2021-05-13T15:14:08.135800Z

Doing something like: export YOUR_TOKEN=topsecret lein repl Will make your token avaliable with (System/getenv "YOUR_TOKEN")

B Treebeard 2021-05-13T15:40:38.137500Z

Hello everyone. Why does this snippet

(->> ["A" "B" "C"]
     (map #(println %))
     ((fn [x]
        (println "Done!"))))
produce this output?
Done!
nil
I.e., why arenā€™t A, B and C printed out?

B Treebeard 2021-05-13T15:41:26.138300Z

(Iā€™m only looking for some hints so that I can figure out what to Google to understand this behaviour better.)

dpsutton 2021-05-13T15:44:02.139300Z

map is lazy. there's nothing realizing that sequence. the only thing that happens to it is that it's passed to a function, ignored, and "Done!" is printed. So nothing cares about the lazy sequence so it doesn't do any work

B Treebeard 2021-05-13T15:44:19.139500Z

Ah, of course! Thanks!

B Treebeard 2021-05-13T15:48:44.140Z

And nowā€¦

(->> ["A" "B" "C"]
     (mapv #(println %))
     ((constantly (println "Done!"))))
gives me
Done!
A
B
C
nil

B Treebeard 2021-05-13T15:48:56.140400Z

Why does the Done! turn up first? :thinking_face:

B Treebeard 2021-05-13T15:50:15.141200Z

Presumably itā€™s something to do with constantly as with ((fn [x] (println "Done!"))) I get the ā€œexpectedā€ order in the output.

dpsutton 2021-05-13T15:50:46.141900Z

(constantly (println "Done"!)) will evaluate it's argument, a println which returns nil, and you end up with a function that takes arbitrary input and returns nil

orpheus 2021-05-13T15:54:28.143300Z

Iā€™ll give it a shot thank you!

B Treebeard 2021-05-13T15:54:32.143600Z

Ah, the println within the constantly is being evaluated when the function that will be returned is being generated. That makes sense, thanks again. šŸ‘

orpheus 2021-05-13T16:01:39.143700Z

@emilaasa in a production environment if you had to hit another server to get a accessToken, how would you save that variable for use in other rest calls? in this scenario it couldnā€™t be an env variable because it needs to be fetched

2021-05-13T17:21:20.144Z

You could use an atom to store it:

(def access-token (atom nil))

(reset! access-token (login environment))

(do-something @access-token)

šŸ™Œ 1
emilaasa 2021-05-13T17:39:38.144300Z

@titanroark depends - does it need to be renewed under the runtime of the program?

orpheus 2021-05-13T17:40:06.144500Z

yeah during runtime, itā€™ll need to be changed/updated depending on the service I now want to hit

emilaasa 2021-05-13T17:47:04.144700Z

Maybe you can stay immutable and not change/update it and make your life easier?

orpheus 2021-05-13T17:49:29.144900Z

Hm.. Iā€™d like to stay as functional as possible but I want to be able to target different service endpoints on demand. To do that I need the access token for each service-environment. If I were to stay purely functional, Iā€™d have to call login before each request I make which is way too much overhead.

evocatus 2021-05-13T18:19:31.146800Z

Hi! I'm playing with my own stupid merge sort implementation. And while mesuring performance I noticed a huge difference depending on how I generate numbers. this (repeatedlyĀ 1000000Ā (partialĀ rand-intĀ 1000000)) is 70000x slower than

(def N 1000000)
(repeatedly N (partial rand-int N))

evocatus 2021-05-13T18:24:09.147800Z

a list comprehension (forĀ [_Ā (rangeĀ N)]Ā (rand-intĀ N)) is as slow as the first expression I mentioned

dpsutton 2021-05-13T18:25:25.148400Z

repeatedly returns a lazy sequence. so most likely you are doing 70000x less work and seeing that take that much less time šŸ™‚

dpsutton 2021-05-13T18:25:51.148900Z

or realizing the sequence in some cases and not in others

evocatus 2021-05-13T18:26:23.149500Z

but the first and second expressions are IDENTICAL except for using predefined constant or not

evocatus 2021-05-13T18:28:02.150100Z

and the time difference I mentioned applies to clojure.core/sort too, not my function only

dpsutton 2021-05-13T18:29:33.150700Z

what exact forms are you running in the repl?

evocatus 2021-05-13T18:32:36.151400Z

dpsutton 2021-05-13T18:32:38.151500Z

user=> (time (do (repeatedly N (partial rand-int N)) nil))
"Elapsed time: 0.022722 msecs"
nil
user=> (time (do (repeatedly 1000000 (partial rand-int 1000000)) nil))
"Elapsed time: 0.022792 msecs"
nil
these behave more or less identically for me, and they are very quick as i'm constructing a lazy sequence and not realizing any of it

evocatus 2021-05-13T18:32:57.151900Z

sorry for bothering you, I can't reproduce the time difference anymore

evocatus 2021-05-13T18:33:20.152400Z

but it was there

dpsutton 2021-05-13T18:33:21.152500Z

you're most likely seeing the differences in the cached lazy sequence and realizing it.

dpsutton 2021-05-13T18:34:00.153300Z

so sort will realize all of v and then sort it, the other sorts will benefit from having a cached lazy sequence and just do their sorting, rather than computing all of the random numbers and then sorting

evocatus 2021-05-13T18:34:36.153800Z

but I call time not on combined function but on each sort method separately

evocatus 2021-05-13T18:34:56.154300Z

and I called it several times changing the let form parameter

evocatus 2021-05-13T18:35:24.154900Z

and the first function in list - clojure.core/sort produced such different timings

evocatus 2021-05-13T18:35:46.155Z

dpsutton 2021-05-13T18:37:04.155500Z

yes. because the first time you access a lazy sequence you have to compute the items in it. subsequent accesses to it use the already computed values

dpsutton 2021-05-13T18:38:00.156300Z

(let [coll (map #(do (Thread/sleep 1000) %) (reverse (range 4)))]
  (time (sort coll))
  (time (sort coll))
  (time (sort coll)))
"Elapsed time: 4014.109926 msecs"
"Elapsed time: 0.008128 msecs"
"Elapsed time: 0.004072 msecs"
(0 1 2 3)

evocatus 2021-05-13T18:38:15.156700Z

I see now, thanks

evocatus 2021-05-13T18:38:44.157400Z

I was puzzled because I was changing the source code and evaluating the changed version

evocatus 2021-05-13T18:39:52.158800Z

does REPL intern such things?

evocatus 2021-05-13T18:40:47.159500Z

my REPL output changes from yours - I have close times with both subsequent function calls inside the let form

dpsutton 2021-05-13T18:41:06.159900Z

i'm not following

dpsutton 2021-05-13T18:41:24.160100Z

can you post the output?

evocatus 2021-05-13T18:43:00.160700Z

it's right above yours output

evocatus 2021-05-13T18:43:17.161200Z

the result of evaluating the let form twice

dpsutton 2021-05-13T18:43:49.162100Z

oh evaluating the left form twice. if you are creating a new lazy seq every time it will be computed every time

šŸ‘ 1
Geoffrey Gaillard 2021-05-13T19:02:57.168100Z

Hello! I'm wondering how to disable clojure.test tests in prod mode. The idiomatic way seems to not include the test folder in the classpath using an alias. But I have a technical constraint that some tests are co-located with the source code. Is there a way to set clojure.test/*load-tests* to false from deps.edn, and ensuring it during AOT compilation?

dpsutton 2021-05-13T19:12:35.169100Z

Are your tests running or you just donā€™t want to define them?

2021-05-13T19:30:37.169200Z

The best attack will be on the constraint that forces you to put tests and source in the same place

2021-05-13T19:34:14.169300Z

Putting those in separate folders is common practice in clojure and I can't think of another language where that isn't how projects are layed out, maybe C?

NoahTheDuke 2021-05-13T19:41:55.170Z

we do it with typescript at my job (thing.ts, thing.test.ts, thing.spec.ts). i hate it, but i don't get to make that decision, lol.

dpsutton 2021-05-13T19:51:05.170400Z

I think Rust has support for same file tests. it's actually quite nice.

dpsutton 2021-05-13T19:55:55.171900Z

eg: <https://github.com/bodil/im-rs/blob/master/src/sort.rs#L184>

2021-05-13T19:56:00.172100Z

sure, you can even do it in clojure, I just mean conventionally most projects don't

dpsutton 2021-05-13T19:56:11.172400Z

yeah. i think it might be a convention in Rust

dpsutton 2021-05-13T19:57:07.172800Z

> However, because unit tests go in the same files as the code <https://doc.rust-lang.org/book/ch11-03-test-organization.html>

2021-05-13T19:57:40.173400Z

so whatever "technical constraint" there is that is forcing you to co-locate them is likely a misunderstanding or a soft constraint

Geoffrey Gaillard 2021-05-13T20:05:11.179500Z

I agree the constraint is odd, but I don't have control over it. It's a complex design choice with subtle implications. Targeting the constraint seems the best approach at first, but it's just not possible. Tests should not be defined in prod mode. When clojure.test/*load-tests* is false , deftest expands to nil. I just want to find a practical way to set it to false from clojure cli, deps.edn or a similar way. Is there a way to do so?

seancorfield 2021-05-13T20:06:06.180400Z

How are you running your code in production?

Geoffrey Gaillard 2021-05-13T20:07:34.181400Z

Using clj with a -main

seancorfield 2021-05-13T20:07:57.181900Z

Any reason youā€™re not building an uberjar and running it just using java -jar in production?

Geoffrey Gaillard 2021-05-13T20:09:15.182900Z

No reason so far, it could perfectly be done with an uberjar.

Geoffrey Gaillard 2021-05-13T20:09:37.183200Z

And probably should

Geoffrey Gaillard 2021-05-13T20:11:56.183300Z

I'd be happy to discuss the technical constraint, it's an interesting one, but since addressing the constraint itself is not an option I'd prefer to make it another thread :)

dpsutton 2021-05-13T20:12:46.183700Z

you can achieve this with an appropriate -e call right?

dpsutton 2021-05-13T20:13:21.184400Z

i wonder if there would be interest in that being initialized from a jvm property as well

Geoffrey Gaillard 2021-05-13T20:17:39.187100Z

If -e has the right precedence it might work, I'll give it a try. How would the jvm property map to *load-tests*? Should I read the property from my -main and set *load-tests* accordingly?

dpsutton 2021-05-13T20:18:49.187700Z

if the dynamic var was initialized to some jvm property otherwise true. No i'm musing about a change i might suggest on ask.clojure

Geoffrey Gaillard 2021-05-13T20:23:38.191Z

Ah! I'm allowed to wrap deftest in a custom macro. So my-deftest could read this property and expand to clojure.test/deftest or nil accordingly. This is another approach I might try.

dpsutton 2021-05-13T20:24:49.191200Z

deftest is already that macro

Geoffrey Gaillard 2021-05-13T20:26:37.192600Z

But is decides to expand or not on *load-tests*

2021-05-13T20:28:37.192700Z

ok, I'll bite, what is the constraint

seancorfield 2021-05-13T20:32:14.197200Z

If you decide to switch to an uberjar, depstar has a mechanism for a ā€œcustom compileā€ function, so you could provide your own function that invokes compile inside a binding of *load-tests*.

seancorfield 2021-05-13T20:34:06.198700Z

(but I would strongly advise ā€œfixingā€ the root cause here and arranging for your tests to be in a separate tests folder tree instead of mixed in with your src)

Geoffrey Gaillard 2021-05-13T20:39:46.203100Z

This is interesting and seems clean! I'll check depstar. I'll communicate more about the root cause and use case in the near future. @dpsutton @hiredman @nbtheduke and @seancorfield thank you very much for your help and kind advices. I think it unblocked me and I'll be able to move forward.

šŸ‘ 1
ramseyst 2021-05-13T21:38:35.206500Z

Hello Clojure wizards, please forgive my Clojure baby-talk. Does anyone know how to define a reflexive relation in core.logic? I can define a simple asymmetric relation like this:

(ns logictest.core
  (:gen-class))

(require '[clojure.core.logic.pldb :as pldb])
(require '[clojure.core.logic :as l])
(pldb/db-rel thing t)
(pldb/db-rel relation x y)
(def facts (pldb/db [thing 'a] [thing 'b] [relation 'a 'b]))
When I try to run pldb code to ask the question "what thing is related to 'b"?,
(pldb/with-db facts (l/run* [foo] (relation foo 'b)))
pleasingly, I get back 'a:
(a)
but when I run this form to try to ask "what thing is related to 'a,
(pldb/with-db facts (l/run* [foo] (relation foo 'a)))
I get (). But I would like to define relation to be symmetric. Is there a way to do that? I tried to study the code for pldb/db-rel to see if there is a hidden option to make a relation reflexive, but it is a bit beyond me, at my novice level of Clojure.

2021-05-13T21:40:07.206800Z

no

2021-05-13T21:40:43.207200Z

the way to do that is a conde in your logic program

šŸ™Œ 1
2021-05-13T21:42:40.208300Z

(pldb/with-db facts
  (l/run* [foo]
    (l/conde
     [(relation foo 'a)]
     [(relation 'a foo)])))

ramseyst 2021-05-13T21:42:44.208400Z

thank you!!!

ramseyst 2021-05-13T21:45:29.208600Z

You are the best! This works!

(defn in-symmetric-pair [relation x y] (l/conde [(relation x y)] [(relation y x)]))
(pldb/with-db facts (l/run* [foo] (in-symmetric-pair relation foo 'a)))

ramseyst 2021-05-13T21:45:45.208800Z

Thanks so much.

vinurs 2021-05-13T23:16:43.209700Z

i have a vector like this [[1 2] [ 6 4]] is there a simple function that can add 1 and 6, and 2 with 4, then generate [7 6]

JuĪ»ian (he/him) 2021-05-14T12:14:22.215100Z

be aware that it returns a list instead of a vector

phronmophobic 2021-05-13T23:29:53.209800Z

&gt; (apply map + [[1 2] [ 6 4]])
(7 6)
seems to work

vinurs 2021-05-13T23:31:16.210Z

thanks