Fork me on GitHub
#clojure
<
2020-05-12
>
wimomisterx01:05:34

Hi, is it not recommended to use core async channels in stateful transducers?

phronmophobic01:05:21

probably not. what are you trying to do?

phronmophobic01:05:50

since channels can be supplied transducers, it seems unlikely that there would be a use case where you would use a channel within a transducer

wimomisterx01:05:02

i'm trying to write a transducer does a partition-all but with a timeout. For example if I have (def foo (chan n (partition-all-with-timeout 3)) and I push from 1 to 10 into the channel, I'd like to get 10 out from the channel after x ms.

phronmophobic01:05:38

there’s a way to tell a transducer to “complete” which* will cause a transducer like partition-all to flush its remaining contents

phronmophobic01:05:10

I would still have the timeout on the “outside” of the transducer and once the timeout triggers, get the transducer to complete and flush any remaining contents

wimomisterx01:05:21

Oh cool! I'll dabble with that. Thanks alot! I'm new to transducers 😅

phronmophobic01:05:40

(def foo (chan 5 (partition-all 3)))

(doseq [i (range 10)]
  (async/put! foo i))

(async/poll! foo)
;; [0 1 2]
(async/poll! foo)
;; [3 4 5]
(async/poll! foo)
;; [6 7 8]
(async/poll! foo)
;; nil

(async/close! foo)

(async/poll! foo)
;; [9]

phronmophobic01:05:54

this definitely isn’t the best example, but hopefully it helps

phronmophobic01:05:33

in this example, closing the channel will case the transducer to “complete”

phronmophobic01:05:15

so if closing the channel is appropriate, then you just do: (go (<! (timeout 5000)) (close! foo)) to close the channel after 5 seconds

phronmophobic01:05:43

also, async/poll! is usually not what you want to use. I’m just using it for this example so I don’t accidentally block my repl 😬

wimomisterx01:05:33

hehe cool! Thanks alot :thumbsup:

fiddlerwoaroof02:05:32

Is there any practical way to implement apropos for any class that could be loaded?

fiddlerwoaroof02:05:59

(assuming that we are only concerned with classes that are loaded from the filesystem)

fiddlerwoaroof02:05:38

I find it really annoying when I read java documentation that says "use class X" but doesn't mention where the class should be imported from

😡 4
👆 4
andy.fingerhut03:05:33

For any class that could be loaded, where you believe you have already installed a JAR defining that class somehow before? Or one that you may never have copied to your computer before?

andy.fingerhut03:05:15

If the latter, then Google searches for things like "java someClassX" can often give information about the class, methods in its API, etc.

andy.fingerhut03:05:30

including a full hierarchical package name like java.lang.foo.bar.ClassX

andy.fingerhut03:05:09

If you have an example class "X" that you are having difficulty with, you can mention it here and someone may be able to demonstrate the process.

fiddlerwoaroof03:05:24

Assume I have the jar in my deps.edn or project.clj and it's been setup

fiddlerwoaroof03:05:37

I want a Java equivalent to (apropos "cat")

fiddlerwoaroof03:05:13

Of course I can google, but that just adds friction to exploring a new java library

andy.fingerhut03:05:38

JAR files are typically copied into your $HOME/.m2 directory the first time you run a program like clj or lein that has the project as a dependency.

seancorfield03:05:02

Java classes don't have the built-in documentation that Clojure namespaces and functions do.

fiddlerwoaroof03:05:53

Sure, but it should be possible to do something like "find all the classes that have 'Client' in their name"

seancorfield03:05:55

It's because of that built-in documentation -- docstrings -- that stuff like apropos can work as it does.

andy.fingerhut03:05:14

For an individual JAR file, you can run a command like jar tvf some-file.jar to see a list of all classes defined within it

andy.fingerhut03:05:02

You could write a program (and probably someone has, but not difficult to write a bash script to do this) that looks for all JAR files in your $HOME/.m2 recursively and does jar tvf ... on each one

fiddlerwoaroof03:05:02

@U0CMVHBL2 that interrupts my REPL flow

seancorfield03:05:10

If you haven't loaded the class, it won't be in memory. You could write something that scanned the classpath and looked inside every JAR file it found as well as any "loose" class files found on the classpath for a class name match.

andy.fingerhut03:05:20

Don't do it in the REPL, but in a terminal window

andy.fingerhut03:05:33

Or implement it in Clojure instead of as a bash script

seancorfield03:05:46

@U2YUELSSF If you wanted to write such a thing, you'd be replicating part of what something like depstar does -- it reads the classpath and reads any JARs it finds there.

fiddlerwoaroof03:05:48

Interesting, maybe I can use that as a library

fiddlerwoaroof03:05:01

I figured this out, which basically works:

(defn classpropos [pattern]
  (run! (comp println
              (memfn getName))
        (into []
              (filter #(re-matches pattern (.getName %)))
              (.getAllClasses
                (ClassPath/from
                  (.getContextClassLoader
                    (Thread/currentThread)))))))

fiddlerwoaroof03:05:52

Thanks, I think this'll work for now

fiddlerwoaroof03:05:29

I often use clj to follow along with documentation for Java libraries, but it's really annoying having to figure out where the classes come from because the docs assume your IDE will find the class for you

seancorfield03:05:12

@U2YUELSSF Just checking: did you already try Clojure's javadoc function to locate docs for a given class?

fiddlerwoaroof03:05:55

@seancorfield doesn't that require knowing the fully qualified name?

fiddlerwoaroof03:05:30

Just to be clear, the point of apropos is to find symbols that contain a string: e.g.:

user=> (apropos "cat")
(clojure.core/cat clojure.core/concat clojure.core/lazy-cat clojure.core/mapcat clojure.core/replicate clojure.spec.alpha/cat clojure.spec.alpha/cat-impl clojure.spec.gen.alpha/cat)

fiddlerwoaroof03:05:10

I use it all the time in CL when I have a general idea what I want to do, but don't know the specific function that implements it.

seancorfield03:05:50

Ah, OK. Just wanted to check your use case.

fiddlerwoaroof04:05:44

I hope I’m not being too pedantic, I tend to overexplain when I suspect someone is misunderstanding me.

andy.fingerhut04:05:11

The name apropos exists in Clojure, but it does not scan for Java class names, only Clojure Var names.

seancorfield05:05:57

A lot of Java documentation I've seen not only doesn't tell you which packages things are in (and doesn't show the import statements) but it also doesn't tell you the Maven group/artifact IDs! 🙂 That means you can't even find the right thing to add to your project in the first place...

noah03:05:34

Is there a (reasonably idiomatic) way to spec a function that takes no arguments? I have a function like this, but am not sure what to put for :args.

(defn get-free-port
  "Returns an available port."
  []
  (let [socket (.ServerSocket. 0)]
    (.close ^.ServerSocket socket)
    (.getLocalPort ^.ServerSocket socket)))

(s/fdef get-free-port
  :args >>>Not sure what to put here.<<<
  :ret (s/& int? #(< 1023 % 49152)))

seancorfield03:05:15

@noah (s/cat) means a sequence of zero things in Spec.

seancorfield03:05:47

(I think that question cropped up on StackOverflow recently -- was that you asking that?)

👍 4
noah03:05:49

@seancorfield Wasn't me, and didn't find it as I was googling, for some reason. Must not have thought of the right search terms. Thanks!

4
noah03:05:57

There's a bug in the code I posted above btw. It should be (s/and int? ...) not (s/& int? ...)

dpsutton05:05:43

little rubber duck help.

duckie 12
dpsutton05:05:53

~/p/c/acl ❯❯❯ tree scratch
scratch
└── remove.clj

0 directories, 1 file
~/p/c/acl ❯❯❯ clj -Sdeps '{:paths ["scratch"]}' -Spath
scratch:/Users/dan/.m2/repository/...
remove.clj in scratch, its on the classpath but
~/p/c/acl ❯❯❯ clj -Sdeps '{:paths ["scratch"]}' -m scratch.remove
Execution error (FileNotFoundException) at clojure.main/main (main.java:40).
Could not locate scratch/remove__init.class, scratch/remove.clj or scratch/remove.cljc on classpath.

dpsutton05:05:33

not finding it. i know its something obvious but not seeing it

seancorfield05:05:33

You want it to look for remove on the classpath (not scratch.remove).

seancorfield05:05:56

scratch is like src -- the ns path is relative to src but does not include src

👍 4
dpsutton05:05:13

oh of course! thanks @seancorfield

seancorfield05:05:17

My work is here done... bed time! 🙂

dpsutton05:05:11

same! and thanks again

mikroskeem11:05:19

heya, i'm looking for a replacement for https://github.com/ztellman/aleph

mikroskeem14:05:25

http-kit iirc had issues with not supporting streaming properly, all body was buffered into memory

mikroskeem14:05:29

which is quite nasty

mikroskeem14:05:03

using :as :stream simply gives you https://github.com/http-kit/http-kit/blob/master/src/java/org/httpkit/BytesInputStream.java, which as you can see is basically byte array wrapper 😕

mike_ananev03:05:44

If you are doing web dev you can try this lib https://github.com/sunng87/ring-jetty9-adapter

mikroskeem10:05:25

thanks, but i'd like to have netty based solution

mikroskeem11:05:07

can anyone suggest me anything good? i've seen ring-jetty stuff but

mikroskeem11:05:12

jetty is bit heavy for me

mikroskeem11:05:30

especially if other libraries which i use also utilize netty

mpenet11:05:05

ring-jetty is super fine

mpenet11:05:21

otherwise you can try vertx, if you want to stuck with thin netty based

mikroskeem14:05:29

interesting, will definitely look into it

mpenet11:05:27

it's quite easy to wrap

mpenet11:05:34

and the api is not horrible

valerauko12:05:48

why are you getting rid of aleph btw?

mikroskeem14:05:12

not being updated, has few nasty bugs

valerauko09:05:58

could you share those bugs you ran into? i was thinking of forking it and keeping it up to date

mikroskeem10:05:15

there's one recent issue reported by me

👍 4
mikroskeem10:05:35

and netty is pretty old; netty got important update recently

👍 4
lukasz14:05:40

Is there a standard way of checking if a dependency is available? I'm working on a library, and I'd like to provide a component namespace. It's usage is optional, and requiring the my-lib.component namespace shouldn't blow up if the application doesn't use Component as a dependency (in deps.edn/project.clj). At the moment, I'm wrapping require in a try-catch in the my-lib.component namespace, but it feels like there should be a better way to do this.

dominicm14:05:36

@lukaszkorecki why shouldn't it blow up. That namespace isn't usable without component.

lukasz14:05:35

Yes, but accidentally requiring it, reloading etc shouldn't cause any issues - it's optional after all

noisesmith14:05:37

you can attempt to resolve a var in an ns, and fallback if it resolves to nil

noisesmith14:05:25

scratch=> (resolve 'clojure.core/+)
#'clojure.core/+
scratch=> (resolve 'does.not.exist/foo)
nil

lukasz14:05:25

Right - that does sound somewhat "cleaner" than a require

noisesmith14:05:49

this means that part of your API is now either requiring some ns or not requiring it I guess

noisesmith14:05:34

because resolve will fail even if the ns is available, if nobody has loaded it yet

dominicm14:05:53

@lukaszkorecki it won't be reloaded under normal circumstances & if its required by accident then blowing up seems like a good thing to do

lukasz15:05:58

Good point: it's just that I want to make dependency on Component truly optional, including gracefully handling requiring the my-lib.component namespace. Maybe I'm too protective of potential users ;-)

dominicm16:05:00

fwiw, there's prior art here in clojure.spec's use of test.check

👀 4
seancorfield17:05:48

There are also ways to construct Component-compatible things without actually requiring Component these days.

seancorfield17:05:38

See https://github.com/seancorfield/next-jdbc/blob/master/src/next/jdbc/connection.clj#L249 for an example of a Component-compatible entity that is a safe no-op if Component isn't on your class path.

lukasz17:05:26

Oh that's neat - I forgot about the ability to implement protocols via metadata. I didn't think about using it that way - thanks!

dpsutton15:05:37

bash-3.2$ clj -Sdeps $(cat scratch/remove.deps.edn) -m remove
Error while parsing option "--config-data {:deps": java.lang.RuntimeException: EOF while reading
how can i use a file as a dep?

dpsutton15:05:14

ah, using " quotes around the expansion. thanks 🙂

dominicm15:05:46

As a rule in bash, if you see a $ it should have a " around it (somewhere). At this point, paranoia wins out for me, and I always do it.

noisesmith15:05:52

it's like every $ is a @, and you need "" in order to get

noisesmith15:05:52

or something like that

dpsutton15:05:10

i'm using fish and running into problems is my problem

Black15:05:07

Is there any easy way to read file and skip n bytes?

noisesmith15:05:17

http://clojure.java.io/input-stream on an http://clojure.java.io/file should give you a FileInputStream which has a skip method https://docs.oracle.com/javase/7/docs/api/java/io/FileInputStream.html#skip(long)

scratch=> (-> "../../../.profile" (io/file) (io/input-stream) (doto (.skip 20)) (slurp) (subs 0 10))
"ON\" ]; the"

❤️ 4
hiredman15:05:47

For more advanced jumping use RandomAccessFile

plins16:05:05

using core.match , its possible to have the same clause for two matches? like its possible in C-like languages with a switch?

Spaceman17:05:10

is there a way to automatically change the file's namespace when I change its directory?

Spaceman17:05:19

so if I change the directory from foo to foo1 of a bunch of files bar%d, how to automatically change all of them from foo.bar1 -> foo1.bar1, foo.bar2 -> foo1.bar2 etc?

Spaceman17:05:06

like I have a Leiningen + spacemacs + cider project if it's easier through any of those tools

noisesmith17:05:40

this might help if you haven't looked at it yet https://github.com/clojure-emacs/clj-refactor.el

Spaceman17:05:25

my Melpa shows a discover-clj-refactor but not a clj-refactor