This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-04-08
Channels
- # announcements (8)
- # aws (2)
- # babashka (11)
- # babashka-sci-dev (39)
- # beginners (62)
- # calva (5)
- # cider (1)
- # clj-kondo (50)
- # cljdoc (2)
- # cljs-dev (6)
- # clojure (52)
- # clojure-austin (22)
- # clojure-czech (13)
- # clojure-europe (88)
- # clojure-nl (1)
- # clojure-norway (5)
- # clojure-uk (6)
- # clojuredesign-podcast (13)
- # clojurescript (45)
- # community-development (3)
- # core-typed (31)
- # cursive (12)
- # datahike (2)
- # datalevin (7)
- # datomic (5)
- # events (1)
- # exercism (11)
- # fulcro (27)
- # gratitude (1)
- # holy-lambda (3)
- # hoplon (2)
- # introduce-yourself (2)
- # jobs (1)
- # lambdaisland (3)
- # lsp (110)
- # malli (2)
- # meander (4)
- # music (2)
- # off-topic (50)
- # overtone (1)
- # pathom (13)
- # polylith (26)
- # re-frame (4)
- # releases (2)
- # rewrite-clj (3)
- # ring (12)
- # shadow-cljs (20)
- # specter (4)
- # tools-deps (8)
- # xtdb (40)
So, walking around in the Clojure source code with my foot gun, I saw
clojure.lang.PersistentVector/adopt
which seemed to be exactly what I was looking for. Until it wasn’t. Because it doesn’t “work” for arrays containing more than 32 elements. Thanks to @chris441 and his work on speeding up json and csv parsing I’ve become aware of clojure.lang.LazilyPersistentVector/createOwning
which does The Exact Right Thing(TM)
But the question still remains for me, why do we have adopt
?
A quick grep through the Clojure source seems to indicate that it’s not used?
It used to be used by Clojure itself, for tuples.
Now Clojure doesn't use tuples anymore, and the implementation has changed dropping the need for adopt
. But the functionality is still there to avoid breaking potential code that uses it.
Correction - Clojure does use tuples, but in a very narrow context, and just as a class with static methods that end up creating vectors. And looking at the dates, I'm not actually sure why the relevant functionality that was created and then abandoned in a week wasn't completely removed, given that some other functionality co-located with it was removed. Maybe just a forgotten piece of code.
Perhaps it would be reasonable to let adopt
delegate to LazilyPersistentVector/createOwning
?
Why? It does what it was designed to do. It sounds like you simply don't need that method at all.
Well, yes it does, until it doesn’t. Like it seems to work when you test with smaller collections, and then exceptions starts being thrown once you’re over 32 items in your collection.
And it’s fair that it wasn’t designed for larger collections, but it doesn’t state that in any way, and you have to bang on it to figure it out, right?
And of course, you could consider spelunking around the clojure sources with a foot gun is not something one should do, and that adopt
should be considered an implementation detail. I get that.
> but it doesn’t state that in any way
Right, because it's not public API. So there be dragons.
> you could consider spelunking around the clojure sources with a foot gun is not something one should do
I recommend at least adding git blame
or something similar to your foot-shooting arsenal. :) It helps clear out many things.
If you look at our dirty laundry, it might be messy. This is all internal stuff that you shouldn't use directly. BUT if you have a use case where you want to do something you can't, that's a great reason for an ask Clojure question
I’ll refrain from bringing my foot gun the next time I walk into someones dirty laundry 🙂
Maybe a package private Annotation should be added to signal parts of the interface that are there for backwards compatibility
question asked https://ask.clojure.org/index.php/11750/interface-to-safely-construct-persistent-datastructures
I’m trying to port a shell script. What should I do if I need to yield the terminal to an interactive program/command?
i was writing a little thing that did that for fzf https://gist.github.com/corasaurus-hex/429d07ef9b3bd4ad2b42e945c6285a2e
some discussion of my attempts to do this here: https://clojurians.slack.com/archives/C03S1KBA2/p1576185715132100
the tldr was:
(-> (ProcessBuilder. ["/some/command"])
(.inheritIO)
(.start)
(.waitFor))
and this works for me for basic readline-type interactive subprocesses, but I never got it to work fully for commands that use the terminal in more sophisticated ways (specifically, Emacs)A terminal is more than stdin/stdout. There's also a tty device involved. Some cli tools will want to deal with this tty directly through the ioctl syscall.
I found this with some googling https://gamlor.info/posts-output/2021-05-29-tty-in-java/en/
Which links to https://github.com/JetBrains/pty4j
Thanks all. These should definitely cover me
> basic readline-type interactive subprocesses,
Then you should create a channel yourself with a buffer of the right size and use it with onto-chan!
.
When you can't tell how large your input is, Clojure can't tell that either. That's exactly why buffers of different kinds exist, to implement different strategies of dealing with data that comes faster than it can be processed.
Exactly - when you can't tell how large it is, and yet you need to keep getting water, you have to figure out the size of a barrel and how many barrels you need.
If you're already using manifold
, then sure, why not.
Note that it will be (I think, judging by the source) equivalent to just using to-chan!
.
I should add to my messages above about buffers and limits - just using to-chan!
with an implicitly created channel is alright when you want to process elements on "as needed" basis, without looking ahead. Because (chan)
will have no buffer - any put!
will wait for a take!
.
Is there a way to get a string as a file object with the string as the contents in java?
(print (slurp (StringIO "abc"))) ;; outputs abc
(with-open [r (io/reader (char-array "hello"))] (slurp r))
Yeah, so readers can have contents, file objects don't have contents though, you can think of them like just storing a file path. You could make a temporary file and store the contents in it and then the file object would "contain" those contents. But the reader way that you've done is better.
Does anyone ever find they want to use transduce
not for the xform
arg, but for a reducing function which can have a completion step?
Yes. I first saw this in the kixi library readme (https://github.com/MastodonC/kixi.stats) but have since used it occasionally
I usually just use a ->
with reduce
honestly. I think the main purpose of actually using transduce
for it would be if your reducing function was stateful.
it could be nice for reducing functions provided in a library though to keep the two conceptually linked steps together