clojure

New to Clojure? Try the #beginners channel. Official docs: https://clojure.org/ Searchable message archives: https://clojurians-log.clojureverse.org/
vemv 2021-01-27T03:09:56.327300Z

to add one to the already mentioned: Eastwood maybe I'd call it "dynamic analysis" though because it works by evaling your code under tools.analyzer. In exchange one gets great accuracy

pseud 2021-01-27T06:25:49.333500Z

Had a fun time last night tweaking vim - like emacs, tweaking vim is an excellent place to waste hours getting ready to be productive, 10/10, highly recommended :rolling_on_the_floor_laughing: Anyway. I decided to setup Conjure, having had slightly more time with vim than last I tried it, everything made more sense and in general, the plugin is just fabulous (saying this in case its creator still lurks in here). However, in my case, I actually use CoC (conqueror of completion), a rather popular plugin for “intellisense” - code navigation, autocompletion and the like, and I encountered a bit of a problem: Using clojure-lsp I can have code navigation and refactoring tips from konda(?) etc. OR I can use coc-conjure to get the auto-completion and suggestions from the cider nrepl through which Conjure connects fed into coc — but not both..! My work-around has been to cram in deoplete, only use this for clojure and to fight with coc to disable any auto-suggestion/auto-complete functionality (just for clojure), in this way, I use CoC as a driver of the clojure-lsp process while deoplete gets its completion information through Conjure which in turn gets it from Cider. This seems hack’ish, but aside from some similar setup, e.g. another LSP plugin and then using CoC for completion, I cannot see what one should do in this case. Any input? Did I miss something stupidly obvious ? Curious to hear.

2021-01-27T06:35:32.333700Z

Kibit as well

flowthing 2021-01-27T06:41:44.333900Z

Don't know the answer, but you might have better luck getting help in #conjure or in the Conjure Discord (https://conjure.fun).

2021-01-27T08:54:56.340900Z

Hi all, I’m trying to find an old blog post that I only vaguely remember from years back - it was a deep dive into laziness, and a very technical, detailed post. Pretty sure it was written by one of the early clojure luminaries (e.g. someone like fogus, cemerick, technomancy, ztellman), but I’ve checked their blogs etc and can’t seem to find it. I know it wasn’t stuart sierra. I seem to remember it covering the subtleties around maximal laziness, mapcat etc… With lots of good examples comparing the differences… though to be honest I can’t really remember much about the topics other than it was to do with sequences. I know I’ll recognise it when I see it though 😆 Can anyone suggest where it might be??

1
2021-01-27T08:58:39.341Z

maybe this one - https://stuartsierra.com/2015/04/26/clojure-donts-concat it is about StackOverflow in concat

2021-01-27T08:59:28.341300Z

Nope not that one, I know it definitely wasn’t by stuart sierra 🙂

2021-01-27T08:59:38.341500Z

It was far more detailed than that

2021-01-27T09:12:31.342Z

I vaguely remember it having hand drawn illustrations in it; but could be wrong about that.

motform 2021-01-27T09:35:01.342200Z

Is there a simple way to "hook" a function so that it runs every time a form in evaluated, regardless of namespace? For example, I want to instrument core/hfun so that runs when I reevaluate either core/foo or impl/bar.

2021-01-27T09:39:43.342300Z

you might want to have a look at this library https://github.com/alexanderjamesking/spy it implements similar idea but for testing maybe its source code can give you a hint

2021-01-27T09:41:33.342600Z

Is that what motfrom is asking for? It sounds like he’s wanting to hook eval itself, not the functions. In which case you can do it by customising your repl. What repl are you using?

motform 2021-01-27T09:42:18.342800Z

For the eval itself, yes. I'm currently using nrepl, but I could switch to a socket repl if that makes things easier.

Ed 2021-01-27T09:42:21.343Z

or you could just wrap the defn in a do that calls the required function?

2021-01-27T09:42:31.343200Z

see here: https://insideclojure.org/2020/02/11/custom-repl/

2021-01-27T09:42:57.343500Z

this is for the default clojure repl; not nREPL

2021-01-27T09:43:14.343700Z

nREPL you can do it with a middleware… maybe other ways too

motform 2021-01-27T09:43:23.343900Z

Ah, cool! That's fine, I have no experience hacking nrepl but i guess it would be a middleware there

2021-01-27T09:44:53.344100Z

oh, I didn’t catch that this should be a property of the repl which is not the only way to run clojure programs

2021-01-27T09:46:21.344300Z

yeah it’s certainly worth asking what your use case is. Hooking eval in the repl is only going to work in dev; though you probably don’t want to do it anywhere else 🙂

motform 2021-01-27T09:46:23.344500Z

no problem! my usecase is a simple static site generator for use in the repl. The idea is that an eval could trigger the build-function. Not as nice as Oz-like live reload, but good enough for what I'm doing and would not require any (cl)js.

motform 2021-01-27T09:47:39.344700Z

which also means that yes, it is purely for development use : ) Doing that in any sort of production env would be... interesing

motform 2021-01-27T09:47:54.344900Z

i "enjoyed" the top heading in this repo https://github.com/technomancy/robert-hooke (obviously a different thing, but still)

2021-01-27T09:48:33.345300Z

I’m not convinced eval granularity is going to align with wanting to rebuild a site, but knock yourself out 🙂

motform 2021-01-27T09:49:29.345500Z

No, that's a fair point. I'm not sure either.

2021-01-27T09:49:58.345700Z

It sounds like a bad idea to me

motform 2021-01-27T09:50:24.345900Z

rebuilding is trivial so time is not the issue, but it would be nice to be able to control rebuilds to certains namespaces, like the one I'm using for garden

motform 2021-01-27T09:50:33.346100Z

and for some templates

2021-01-27T09:50:47.346300Z

You could just call rebuild yourself at the REPL… or set up a filesystem watch to rebuild on save

2021-01-27T09:51:47.346500Z

Personally I’d be tempted to do something like sticking a rebuild function in user.clj and just run (user/rebuild) which will then work from any namespace when you want to rebuild.

motform 2021-01-27T09:52:38.346800Z

that's what I'm doing right now, calling the rebuild and then refreshing the browser with a watch. but calling that rebuild requires navigating to a different file and navigating to that form, which adds some friction when you are doing things like editing css or smaller template changes

2021-01-27T09:53:31.347Z

use an editor hotkey to send the form to the repl

motform 2021-01-27T09:53:54.347200Z

having it in user is not a bad idea. idealy, one could make an emacs keybind to send that eval (user/rebuild) in the repl without having to be on in that specific place

motform 2021-01-27T09:53:59.347400Z

that's what I'm doing right now, calling the rebuild and then refreshing the browser with a watch. but calling that rebuild requires navigating to a different file and navigating to that form, which adds some friction when you are doing things like editing css or smaller template changes

motform 2021-01-27T09:54:13.347600Z

(messages should be in the reverse order)

Hagenek 2021-01-27T12:19:38.348500Z

Anyone familiar with speclj ? I am getting this error after setting up a new project with lein new speclj and then running lein test.

Exception in thread "main" java.io.FileNotFoundException: Could not locate speclj__init.class or speclj.clj on classpath., compiling:(clojure_functions/reduce_spec.clj:1:1)
I also see that it is using Clojure 1.8.0, is there a newer framework that I should use instead for BDD/TDD? EDIT: Switched over to trying Midje now, it seems more like what I am looking for.

teodorlu 2021-01-27T12:22:56.348900Z

I was thinking that Aphyr might have posted about this, but I can't find anything in particular. Here's one about sequences, which mentions lazyness: https://aphyr.com/posts/304-clojure-from-the-ground-up-sequences

teodorlu 2021-01-27T12:23:20.349100Z

(I appreciate that these oldie-but-goldie posts get some new light)

2021-01-27T12:25:47.349300Z

Thanks, but unfortunately that’s not the one… I think it was more about the implementation and edge cases, rather than how to use the library.

👍 1
2021-01-27T12:29:20.349500Z

could you check if your project.clj has speclj declared as dependency for dev profile?

Hagenek 2021-01-27T12:31:23.349700Z

my project.clj: (_defproject_ clojure-functions "0.1.0-SNAPSHOT"   _:description_ "FIXME: write description"   _:url_ "<http://example.com/FIXME>"   _:license_ {_:name_ "Eclipse Public License"             _:url_ "<http://www.eclipse.org/legal/epl-v10.html>"}   _:main_ clojure-functions.core   _:dependencies_ [[org.clojure/clojure "1.8.0"]]   _:profiles_ {_:dev_ {_:dependencies_ [[speclj "3.3.2"]]}}   _:plugins_ [[speclj "3.3.2"]]   _:test-paths_ ["spec"])

2021-01-27T12:31:39.349900Z

did you run lein test or lein spec ?

Hagenek 2021-01-27T12:31:46.350100Z

lein test

2021-01-27T12:32:28.350600Z

you should use lein spec instead I think this is the most convenient way to run specs

Hagenek 2021-01-27T12:32:56.350800Z

Ok! I guess I dont know the difference between spec and test 😃

2021-01-27T12:33:37.351Z

lein test is an option of leiningen itself speclj introduce one more option to run itself

✌️ 1
Hagenek 2021-01-27T12:34:46.351200Z

Yes, and lein test is dependant on the :main NS file in the project file. After changing that to the correct (from clojure-functions.core to clojure.functions.reduce) the lein test gave me the correct error I think

Hagenek 2021-01-27T12:39:11.351500Z

Well well I got it working now, thanks a lot 😃 I should have read the documentation more thoroughly, I have a tendency to expect things to just work a certain way

2021-01-27T12:43:46.351700Z

that is ok ) there are no persons who knows everything) I also learned that difference just now)

Helins 2021-01-27T13:28:31.353900Z

Will this always be true? That no new map is created when a value is updated to an identical one?

(def m {:a 42})

(identical? m
            (assoc m :a 42))

alexmiller 2021-01-27T13:29:02.354300Z

yes

👍 1
alexmiller 2021-01-27T13:29:32.354700Z

sorry, I misread, no I would not guarantee that

alexmiller 2021-01-27T13:30:12.355100Z

I would guarantee they are equal

alexmiller 2021-01-27T13:31:04.356400Z

but whether they are identical is an implementation question

Helins 2021-01-27T13:31:16.356600Z

Right, so when remaining 'identical' is important, it is best to get and assoc if needed rather than using update (same applies to xxx-in variants)

alexmiller 2021-01-27T13:31:51.356900Z

I'd say it's bad to rely on identity in the first place

alexmiller 2021-01-27T13:31:57.357100Z

and then you don't care

Helins 2021-01-27T13:33:03.357900Z

In the grand scheme of things yes. I am wondering about some possible optimizations for a project but otherwise I agree this would be too much of a burden.

vlaaad 2021-01-27T13:42:02.358900Z

(update m :key identity) does not return identical result on records btw @adam678

👍 1
alexmiller 2021-01-27T13:51:56.359800Z

current dev environment results from 2021 Clojure survey - still time to register your own choices! https://www.surveymonkey.com/r/clojure2021

👍 3
1
1
kirill.salykin 2021-01-27T15:25:46.362300Z

Hi, please advice how I can split byte-array into two byte-arrays (based on index) basically i want to split ouput of this

(defn random-bytes
  [size]
  (let [seed (byte-array size)]
    (.nextBytes (SecureRandom.) seed)
    seed))
thanks

2021-01-27T15:29:37.364600Z

You can create two new byte-array objects (which are the same as Java arrays with primitive type byte for the elements) with the lengths of the two pieces you want, and copy the parts of the original array into those two new arrays. If this is a hot inner loop, you can do the copying via the JVM method call System/arrayCopy. You could also write a loop in Clojure over the indexes of the array you want to copy, and copy the bytes one at a time in that loop.

🙏 1
alexmiller 2021-01-27T15:34:09.364800Z

also see newer java.util.Arrays

🙏 1
2021-01-27T15:38:34.365600Z

Don't think I'd used the methods of that class before. copyOfRange looks useful for this purpose.

clyfe 2021-01-27T15:47:35.366800Z

Clojure homebrew install says 1.10.2.774 but run says 1.10.1 details in thread.

clyfe 2021-01-27T15:48:03.366900Z

grazfather 2021-01-27T15:52:19.367600Z

hash -d clj

grazfather 2021-01-27T15:52:23.367800Z

then try again

clyfe 2021-01-27T15:54:32.368Z

> ➜ ~ hash -d clj > hash: no such directory name: clj

2021-01-27T16:02:01.368200Z

clojure version might be overwritten by local deps.edn check if you have it in $HOME/.clojure/deps.edn

👍 1
🎯 1
1
alexmiller 2021-01-27T16:09:25.369900Z

clojure version is whatever dep you've declared

alexmiller 2021-01-27T16:09:41.370100Z

new 1.10.2.x wil ldefault to 1.10.2 in root, but you can override in user or project

alexmiller 2021-01-27T16:09:58.370300Z

you can use any clojure tool version with any clojure version

seancorfield 2021-01-27T18:18:18.370800Z

@claudius.nicolae Just as a follow-up to that, if you look at my user-level deps.edn file, you'll see I have aliases for every version of Clojure all the way back to 1.0 (and three different aliases for the specific sub-versions of Clojure 1.10): https://github.com/seancorfield/dot-clojure/blob/develop/deps.edn#L171-L188

seancorfield 2021-01-27T18:18:43.371100Z

That can be very useful for testing code against several different versions of Clojure, via the CLI.

👍 1
matheusashton 2021-01-27T18:53:47.375700Z

Hello! I'm not sure if here is the right place, and if isn't I'm sorry in advance, but can anybody help me to understand a problem? I have this function:

(ns core.reader
  (:require [<http://clojure.java.io|clojure.java.io> :as io]))

(defn read-lines
  "reads an input and returns a ISeq of the lines"
  [input]
  (line-seq (io/reader input)))
receiving *in* as argument and I'm testing it like this:
(ns core.reader-test
  (:require [core.reader :as reader]
            [clojure.test :refer :all]))

(deftest core-reader-test
  (testing "read from stdin"
    (let [result (with-in-str (reader/read-lines *in*) "is\n42")]
      (is (= "is" (first result)))
      (is (= "42" (last result))))))
but when I run lein test the test hangs waiting for a input, in theory with-in-str should provide data to stdin and the test should not hang, can somebody spot what am I doing wrong?

2021-01-27T18:55:39.376100Z

@matheusashton have you tried adding a final newline?

matheusashton 2021-01-27T18:56:11.376300Z

hmmm no, I'll try

2021-01-27T18:57:53.377200Z

@matheusashton never mind- you need a doall, or else the read-lines executes outside the with-in-str body

2021-01-27T18:58:05.377500Z

laziness plus dynamic bindings are a bad mix

2021-01-27T19:00:19.377700Z

but that still isn't unblocking it...

2021-01-27T19:00:58.378Z

@matheusashton also you have the args of with-in-str flipped

dpsutton 2021-01-27T19:01:48.379Z

I’d also make a my own output stream and not muck about with “in

2021-01-27T19:02:10.379300Z

(cmd)user=&gt; (with-in-str "is\n42" (doall (read-lines *in*)))
("is" "42")
(cmd)user=&gt; (with-in-str "is\n42" (read-lines *in*))
Error printing return value (IOException) at java.io.PushbackReader/ensureOpen (PushbackReader.java:73).

2021-01-27T19:02:23.379500Z

@dpsutton inputstream, surely

dpsutton 2021-01-27T19:02:56.380500Z

Yeah. I always get the terms backwards. I always forget if output stream has output or accepts output

2021-01-27T19:03:21.381Z

@dpsutton my mental model is that everything is from the perspective of the object as a first person entity

2021-01-27T19:03:29.381400Z

if you can call a read method, it's an input stream

dpsutton 2021-01-27T19:03:57.382600Z

That makes sense. I think I put myself as the consumer and think “I need output from something. Ah a stream”

dpsutton 2021-01-27T19:04:12.383200Z

But I’ll probably remember it now so thanks

2021-01-27T19:04:16.383300Z

but that's projecting! it's your input

2021-01-27T19:04:19.383500Z

it's someone else's output

2021-01-27T19:06:08.384200Z

also there are things like StringReader that are really nobody's "output" per se, just a view of their data as if it were

Mno 2021-01-27T19:07:05.385500Z

Sounds like a proverb: "one man's output is another man's input."

2021-01-27T19:07:26.386Z

@matheusashton I think this is simpler than what you are doing currently

user=&gt; (read-lines (java.io.StringReader. "is\n42"))
("is" "42")

matheusashton 2021-01-27T19:15:43.389600Z

@noisesmith thanks! I'll try to fix the things that you've pointed, the input of my program will be the contents of a file (I cannot read the file inside the program because I don't know the filename) so I need to read it from *in* , I was trying to make like an integration test, that's why I tried to dynamic bind *in* , I run my program like lein run &lt; file

2021-01-27T19:16:33.390200Z

@matheusashton my example above makes it read from a string, you don't need to send a string to in, then read in, you can just read from the string

2021-01-27T19:17:35.391700Z

maybe use with-in-str if you need to test -main, but usually I'd make sure -main is trivial and test the individual components in ways that don't require process level resources

matheusashton 2021-01-27T19:17:50.391900Z

yes, but I was trying to make an integration test, simulating the real behaviour

2021-01-27T19:18:19.392300Z

StringReader is as real as *in* is, and also simpler

matheusashton 2021-01-27T19:20:14.392700Z

hmm ok

2021-01-27T19:21:09.393600Z

in this instance, it's simpler because *in* changes value as your object changes scope, and thanks to laziness your result would change scope before being realized if you didn't force it

2021-01-27T19:23:05.395100Z

as a big picture example, I'd set things up like this: (defn app [stream] ...) (defn -main [&amp; args] (app *in*))

2021-01-27T19:23:36.395700Z

where "app" has all the logic aside from implementation details (Iike which specific reader you are reading lines from)

2021-01-27T19:24:18.396500Z

now app can be tested without relying on global / process level state like *in*

matheusashton 2021-01-27T19:24:53.396700Z

ok, got it!

matheusashton 2021-01-27T19:25:01.397Z

Thank you very much!

2021-01-27T19:25:48.397900Z

this pattern makes testing much easier (but it's only as good as the quality of your stubs - swapping one reader for another is great, your hand made stub for your protocol might be iffier...)

matheusashton 2021-01-27T19:27:29.398100Z

sure

matheusashton 2021-01-27T19:28:59.399600Z

also, my -main is like this:

(defn -main
  [&amp; args]
  (-&gt;&gt; *in*
       (read-lines)
       (map parse-json)
       (map println)))
but if I try to lein run &lt; file it reads the lines but doesn't print parsed maps, is this something about lazyness too?

matheusashton 2021-01-27T19:31:19.400200Z

parse-json is simply cheshire's parse-string

2021-01-27T19:31:48.400600Z

right, nothing is consuming the return value of map, so why would it calculate anything?

2021-01-27T19:31:59.400900Z

perhaps you want (run! println) instead at the end

matheusashton 2021-01-27T19:32:35.401900Z

oh right, it doesn't realize the whole pipe until something needs right?

2021-01-27T19:33:41.403200Z

@matheusashton right, because every function in the pipeline is lazy, it doesn't promise to calculate any more results than are consumed, and in the case of -main when not run from a repl, nobody consumes it

2021-01-27T19:34:15.403700Z

the repl consumes it in order to print (and would give you a big annoying list of nils from each println call)

matheusashton 2021-01-27T19:36:15.404Z

ok, thanks! Learned a lot today 😄

richiardiandrea 2021-01-27T19:47:18.405100Z

Hi all, long time ago, I was using a library that could generate HTTP call functions from clojure.specs. I do not remember the name now though. Is anybody using something like that?

clyfe 2021-01-27T19:49:06.405200Z

swagger? martian?

richiardiandrea 2021-01-27T19:52:32.405700Z

ah martian! Thank you 😄

Helins 2021-01-27T20:20:42.409700Z

Calling clojure.tools.namespace.repl/refresh in a macro used in CLJS prints an error (ie. :error-while-loading some.namespace) but the rest of the macro continues. No exception is thrown and clojure.core/*e is unbounded. Any idea how to retrieve the error? Right now I throw the exception myself in some.namespace so I know what is going on. I guess that the macro and refresh are not executed on the same thread but I don't know why (since refresh is called from the macro).

2021-01-27T20:39:21.411500Z

*e does not have a binding established when you are compiling your clojurescript, so refresh cannot set! It

Helins 2021-01-27T20:43:58.412500Z

@hiredman Oh right, it looks a bit weird but (binding [clojure.core/*e nil] ...) works, thanks!

Dominic Pearson 2021-01-27T21:12:27.412900Z

hi folks. does anyone have any experience with jdbc and hugsql? i am looking at the docs and trying to figure out how to wrap inserts in a transaction. the docs are stated as: https://www.hugsql.org/#using-transactions -- however it does not specify how to actually create a transaction. looking at https://github.com/funcool/clojure.jdbc/blob/master/src/jdbc/transaction.clj was not so enlightening either. maybe someone has an idea? i am trying to concurrently iterate on a collection of data and want to insert transformed data to a sqlite database. sqlite inserts should be wrapped in a transaction for performance reasons, and to avoid errors like "[SQLITE_BUSY] The database file is locked (database is locked)". i am using a manifold stream (like an async channel) to put to a thread that batches inserts into X amount before committing, or after a timeout is reached. i'm using hugsql so would like to take the data in and construct a transaction with the various inserts in and commit after a certain time is reached or a certain amount of inserts is fetched from the stream. any input welcome!

Dominic Pearson 2021-01-27T21:29:54.415300Z

doh, figured it out. with-db-transaction is not a function but a macro, so of course the spec did not make immediate sense. the parameters, [tx db], do not require a tx variable to be created beforehand but instead set a binding within the body, so tx is a transaction created from db and tx takes the place of db in any hugsql calls. lisp syntax is magical but at times confusing without clear idiot-proof commentary.

2021-01-27T21:31:07.416100Z

funcool's clojure.jdbc is also not the library you want to be using

2021-01-27T21:48:16.420700Z

funcool's clojure.jdbc has a bit of a cloud over it since some of the early code for the project looks like it could just be copied and pasted from clojure.java.jdbc (in violation of clojure.java.jdbc's license), reading funcool's docs my guess is their position is something like "clojure.jdbc is an implementation of the same api as clojure.java.jdbc so their are bound to be similarities" , but it's not a good look

2021-01-27T21:48:55.421200Z

also they picked a name that used to be a common shorthand used in the community for the library they forked claim to have rewritten from scratch

2021-01-27T21:50:38.422100Z

yes, and rich has indicated clojure.* belongs to him as far as namespaces go

seancorfield 2021-01-27T21:51:35.422900Z

I can link to the Google Groups discussion about the clojure.jdbc author and the whole copying code and stripping all the license and copyright notices...

seancorfield 2021-01-27T21:51:57.423300Z

It still burns that someone would steal my code and pass it off as their own.

seancorfield 2021-01-27T21:52:19.423800Z

But at this point, my main argument about funcool's clojure.jdbc is that it is unmaintained.

seancorfield 2021-01-27T21:53:51.424600Z

HugSQL supports next.jdbc. And next.jdbc's documentation has a getting started guide for HugSQL. So that's the official recommendation.

Dominic Pearson 2021-01-27T22:23:56.425500Z

thanks. my code is old, spent 2020 not really functional 😄 next.jdbc is definitely something i want to pick up. and yes, that was a mis-google, i am indeed using clojure.java.jdbc.

Dominic Pearson 2021-01-27T22:32:11.428500Z

am also a little worried about using ztellman's manifold. seems zach is particularly busy/inactive lately, and noticed that manifold streams try-take! seems to increment :pending-takes continuously even if timeout was reached, not resetting it.

enki.buffers&gt; (def y (stream/stream))
#'enki.buffers/y
enki.buffers&gt; (dotimes [n 16384] (stream/try-take! y 1))
nil
enki.buffers&gt; y
&lt;&lt; stream: {:pending-puts 0, :drained? false, :buffer-size 0, :permanent? false, :type "manifold", :sink? true, :closed? false, :pending-takes 16384, :buffer-capacity 0, :source? true} &gt;&gt;
enki.buffers&gt; (stream/try-take! y 1)
Jan 27, 2021 11:29:29 PM clojure.tools.logging$eval451$fn__455 invoke
WARNING: excessive pending takes (&gt; 16384), closing stream
java.lang.IllegalStateException
	at manifold.stream.default.Stream.take(default.clj:234)
	at enki.buffers$eval38629.invokeStatic(form-init9188607286898067210.clj:17367)
	at enki.buffers$eval38629.invoke(form-init9188607286898067210.clj:17367)
	at clojure.lang.Compiler.eval(Compiler.java:7177)
	at clojure.lang.Compiler.eval(Compiler.java:7132)
	at clojure.core$eval.invokeStatic(core.clj:3214)
	at clojure.core$eval.invoke(core.clj:3210)
	at nrepl.middleware.interruptible_eval$evaluate$fn__29511$fn__29512.invoke(interruptible_eval.clj:87)
	at clojure.lang.AFn.applyToHelper(AFn.java:152)
	at clojure.lang.AFn.applyTo(AFn.java:144)
	at clojure.core$apply.invokeStatic(core.clj:665)
	at clojure.core$with_bindings_STAR_.invokeStatic(core.clj:1973)
	at clojure.core$with_bindings_STAR_.doInvoke(core.clj:1973)
	at clojure.lang.RestFn.invoke(RestFn.java:425)
	at nrepl.middleware.interruptible_eval$evaluate$fn__29511.invoke(interruptible_eval.clj:87)
	at clojure.main$repl$read_eval_print__9086$fn__9089.invoke(main.clj:437)
	at clojure.main$repl$read_eval_print__9086.invoke(main.clj:437)
	at clojure.main$repl$fn__9095.invoke(main.clj:458)
	at clojure.main$repl.invokeStatic(main.clj:458)
	at clojure.main$repl.doInvoke(main.clj:368)
	at clojure.lang.RestFn.invoke(RestFn.java:1523)
	at nrepl.middleware.interruptible_eval$evaluate.invokeStatic(interruptible_eval.clj:84)
	at nrepl.middleware.interruptible_eval$evaluate.invoke(interruptible_eval.clj:56)
	at nrepl.middleware.interruptible_eval$interruptible_eval$fn__29542$fn__29546.invoke(interruptible_eval.clj:152)
	at clojure.lang.AFn.run(AFn.java:22)
	at nrepl.middleware.session$session_exec$main_loop__29609$fn__29613.invoke(session.clj:202)
	at nrepl.middleware.session$session_exec$main_loop__29609.invoke(session.clj:201)
	at clojure.lang.AFn.run(AFn.java:22)
	at java.base/java.lang.Thread.run(Thread.java:832)

#&lt;SuccessDeferred@11f12ad4: false&gt;
enki.buffers&gt; (def y (stream/stream))
#'enki.buffers/y
enki.buffers&gt; (dotimes [n 16384] (stream/try-take! y 1))
nil
enki.buffers&gt; (stream/put! y 1)
#&lt;Deferred@50a88030: :not-delivered&gt;
enki.buffers&gt; (stream/try-take! y 1)
#&lt;SuccessDeferred@6429f73e: 1&gt;
enki.buffers&gt; y
&lt;&lt; stream: {:pending-puts 0, :drained? false, :buffer-size 0, :permanent? false, :type "manifold", :sink? true, :closed? false, :pending-takes 0, :buffer-capacity 0, :source? true} &gt;&gt;
I would expect that takes that timed out (so would never actually fetch from the stream) would not cause this sort of pressure and would clear from the queue. i'll fire off an email.

seancorfield 2021-01-27T22:33:37.429700Z

Manifold has just transferred to the #clj-commons organization and a new maintainer is coming up to speed...

🎉 3
seancorfield 2021-01-27T22:34:36.430200Z

So you could try asking in that channel or open an issue at https://github.com/clj-commons/manifold

Dominic Pearson 2021-01-27T22:36:04.430800Z

Thanks. Yes, will open an issue and may well look at fixing it myself when it's daylight.

2021-01-27T22:45:54.432400Z

I think I just wrote a (as of yet not applied) patch (really a series of patches) for something very like this in core.async.

2021-01-27T22:47:36.433700Z

and it is exactly that, when you have non-deterministic choice, in this case get a value from this stream or timeout, it is not enough to commit to one of the choices, you also need to go back and cleanup the choice not taken

2021-01-27T22:53:28.436700Z

core.async has some code that is run on every put/take/close of a channel that prevents build ups of non-active handlers, but if you are doing operations on channels that don't get a lot of operations (commonly timeout channels, and timeouts have other issues that make this worse) channels can hold on to handlers (and any closed over values) longer then they should

Dominic Pearson 2021-01-27T22:57:30.439700Z

my use case is fetching data to add to sqlite transactions in a separate thread. concurrent inserts fail due to locking, so using a channel to batch inserts is a workaround. however i do not want to specifically wait for N inserts, rather flush on N or after X seconds (to avoid losing data or delays to commits). so a way to either fetch, or time out & commit & loop, is the approach i was going for.

Dominic Pearson 2021-01-27T22:59:07.440700Z

it's been ~1 year or so since i've touched this, or the ecosystem, so i'll have a look around at what is available and how to best approach it. for now, it is midnight, and tomorrow i have work. 🙂 cheers

2021-01-27T23:00:46.441500Z

depending on this that and the other you might be fine with using a java.util.concurrent.LinkedBlockingQueue and passing a timeout to the poll method instead of a manifold stream

2021-01-27T23:08:43.442700Z

mmm, yeah, not actually like the core.async timeouts issue I was thinking, manifold just needs to scan pending puts for realized defers

2021-01-27T23:09:03.443Z

(and remove them)