This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-04-24
Channels
- # aws-lambda (1)
- # beginners (99)
- # boot (46)
- # cider (8)
- # cljs-dev (20)
- # cljsrn (37)
- # clojure (189)
- # clojure-dev (22)
- # clojure-dusseldorf (28)
- # clojure-italy (1)
- # clojure-russia (28)
- # clojure-spec (10)
- # clojure-uk (33)
- # clojurebridge (1)
- # clojurescript (64)
- # core-matrix (2)
- # css (3)
- # cursive (3)
- # datascript (34)
- # datomic (101)
- # defnpodcast (2)
- # dirac (5)
- # events (1)
- # funcool (3)
- # ldnclj (1)
- # lumo (11)
- # mount (1)
- # off-topic (95)
- # pedestal (2)
- # perun (10)
- # re-frame (3)
- # reagent (6)
- # ring-swagger (4)
- # specter (102)
- # test-check (1)
- # untangled (1)
- # vim (8)
- # yada (17)
(deftype LVar [vname])
(defmethod print-method LVar [v w]
(.write w (str "[LVar: " (.-vname v) "]")))
^^ the above code works in Clojure, but not in Cljs. Why ?I mean... Well, you have a deftype there. Do you use defmethod on a deftype in CLJ? I forgot.
In any case, I believe you set the IPrintWithWriter protocol on your deftype in CLJS, do do what you're wanting.
@john the way printing is set up in jvm clojure everything uses print-method for pr (the printing that is done in a repl)
@noisesmith ah, okay.
(with a default to str if no print-method dispatch is defined for that type)
v is unbound
it works if you replace (.-vname v)
with vname
fields are always in scope in method bodies
and should those opts be used?
Hi there. I am looking for a way to shorten namespaced keywords without actually referring that namespace. Can it be done?
The reason being: I have two libraries that I would like to share a common vocabulary, but other than that they don't depend on each other.
I'm considering introducing an artificial third library with basically just an empty namespace. I can then namespace the keywords there and have both my real libraries depend on that, but it seems clunky.
@frederic I think a direct call to alias
would do it
so instead of requiring your namespace in the ns
declaration just call alias
further down
@cmal There is sente: https://github.com/ptaoussanis/sente and IIRC http-kit can create websockets out of the box
how do I define = over a deftype? I'm reading http://blog.klipse.tech/clojurescript/2016/04/26/deftype-explained.html and but I can't extend "IEquiv" for some reason
Has anyone used https://github.com/ymilky/franzy kafka client with https://github.com/tolitius/mount? - I am not sure how to cleanly close the client/consumer connections with mount. It results into ConcurrentModificationException and creating consumer/producer at each request is not a good idea. @ymilky - any inputs?
@stathissideris thank you for the tip
after some trying around : alias would be useful to avoid dependency cycles inside a single project
across multiple projects it’s not so great, because the aliased namespace still needs to exist
Hi, I required sente
in my ns but I use sente/cb-success?
it tells me No such var: sente/cb-success?
, why?
@anujsays if the KafkaConsumer is not thread safe I would not use it as a component like that with mount. What do the docs say? Is it ok to open one consumer per "request"? Or maybe you need a pool of readily available consumers? If its not thread safe I would think kafka expects clients to be created and closed regularly.
Yes @sveri that makes sense. I was just carried away with the best practices that do talk about wrapping it with mount but couldn't find an example- https://github.com/ymilky/franzy/blob/master/doc/best_practices.md to do that.
Also, did you see this issue: https://github.com/ymilky/franzy/issues/6 ?
Yes, there is a fork https://github.com/MastodonC/franzy that has received updates along-with https://github.com/lbradstreet/franzy
@anujsays : Seems like it using https://kafka.apache.org/090/javadoc/index.html?org/apache/kafka/clients/consumer/KafkaConsumer.html under the hoods. And the docs says that it is not thread safe and will throw ConcurrentModificationException if called with out synchronization. Here are the
1. One Consumer Per Thread
A simple option is to give each thread its own consumer instance. Here are the pros and cons of this approach:
PRO: It is the easiest to implement
PRO: It is often the fastest as no inter-thread co-ordination is needed
PRO: It makes in-order processing on a per-partition basis very easy to implement (each thread just processes messages in the order it receives them).
CON: More consumers means more TCP connections to the cluster (one per thread). In general Kafka handles connections very efficiently so this is generally a small cost.
CON: Multiple consumers means more requests being sent to the server and slightly less batching of data which can cause some drop in I/O throughput.
CON: The number of total threads across all processes will be limited by the total number of partitions. Here are the options suggested by the docs:
2. Decouple Consumption and Processing
Another alternative is to have one or more consumer threads that do all data consumption and hands off ConsumerRecords instances to a blocking queue consumed by a pool of processor threads that actually handle the record processing. This option likewise has pros and cons:
PRO: This option allows independently scaling the number of consumers and processors. This makes it possible to have a single consumer that feeds many processor threads, avoiding any limitation on partitions.
CON: Guaranteeing order across the processors requires particular care as the threads will execute independently an earlier chunk of data may actually be processed after a later chunk of data just due to the luck of thread execution timing. For processing that has no ordering requirements this is not a problem.
CON: Manually committing the position becomes harder as it requires that all threads co-ordinate to ensure that processing is complete for that partition.
There are many possible variations on this approach. For example each processor thread can have its own queue, and the consumer threads can hash into these queues using the TopicPartition to ensure in-order consumption and simplify commit.
@anujsays kafka consumers are usually started in separate threads. take a look at "starting multiple kafka consumer threads" example: https://gist.github.com/tolitius/cc968a2adcc9dccc24cf15386fc44345 it uses gregor
, but the concept is no different with vanilla kafka java api
Hello all, is there any way to generate clojure like static method to be called from java as string reflection?
Is (last (last (:schema (first (:options (schema.core/spec Record))))))
the best way to extract a schema out of a record with schema? looks a bit convoluted.
Is there a shorthand for:
(let [nv (get mpt expr)]
(if nv
(walk mpt nv)
expr))
I'm expecting some way to simplify the use of "nv" hereThanks @sreenath.n and @tolitius
not really, and any sort of macro there would probably complicate the code @qqq
@tbaldridge : there's not something with if-let, cond-let, when-let, or an "it" ?
yeah that works (I read your code wrong)
e.g: even when not writing a stateful transducer altogether, using (def my-xf (map (something-that-closes-over-a-volatile)))
is still valid?
@pyr it's ok to use volatiles only if you can ensure by other means that updates are sequential
in your case the volatile will be shared by all instances of the transducer, and multiple instances can run concurrently
In the clojure way, if I pass a function data that is: (1) syntatcailly valid (2) semantically valid (3) but the function can't properly handle it should the proper result be: (1) throw an exception or (2) return an err msg ?
@leonoel it would be a case of: (defn volatile-map-fn [] (let [state (volatile! {})] (fn [elem] ...))) (def my-xf (map (volatile-map-fn)))
@qqq AFAIK Clojure does not have a specific opinion on error handling. I'd throw a slingshot exception.
+1 for that, with ex-info you can throw a fair amount of information with the error (including the internal state of your function that caused the input data to be invalid)
is this a good practice for big software projects, as sometimes it screws up cljs -> web browser -> pause on exceptions
Sure, but to put it bluntly, when I encounter that problem I find a better tool/web browser, that allows finer grained control over exceptions.
But from what you originally said, this truely is an error, so that's what exceptions are for, no?
Hello all, I have this in java
probe.registerHubpostCallback(this,"hubpostCallback")
, the hubpostCallback is Java static method, is there any way to convert it to clojure?that looks like it might be calling a static method on an instance, which is, IIRC something java lets you do
but not something clojure does, so you would have to find out what class probe is, and call the static method on that class
are you asking about a way to convert the hubpostCallback static method that is being called to clojure?
static methods are sort of annoying, it must be using reflection to invoke the method, so the question is if the code invoking the method requires that it be static in some way, I sort of doubt it, I would try something like
(probe/registerHubpostCallback (fn [] (println "Hello World")) "call")
Hi I'm trying to eval a file that contains code that, when evaluated, write to this very file. I'm not expecting my modifications to the file to be taken by Clojure's reader so this is not as mad as it sounds. My problem is the following: the program hangs when I try to write to the file. If I commit my modifications to an atom and write them to the file after load
has done its job, then everything is alright. The errors from the reader are syntax errors of various kinds: basically the reader sees my changes to the file and get lost in parenthesis mismatches or whichever errors the modification causes. Ideally I would like the reader to slurp the whole file then proceed to do it's reader-job. How can I achieve that ?
oh thanks, i'll give it a shot right away
there's a bit of a learning curve, but the basic idea is that you transform a "fileset" and filesets are immutable. so you can xform file X and write it to X - but it will be a "new" X, if that makes sense - you never actually overwrite the input file. the folks on #boot are very helpful.
may be you can do a copy of the file that you want to evaluate. And then read from the duplicated file. When each form has been read and evaluated, write the result back to the original file. cc: @tristefigure
Probably before writing the results back to the original file, you can check the last modified date and make sure that you are indeed evaluating the latest changes 😉
I hadn't thought of that, this looks like the right solution . thanks !
Why is no one else asking: "why is a file, when being evaled, writing to itself, and thus depending on file system semantics? is there no other way to structure this?"
@tristefigure, you might be biting you own behind! That said, one way to achieve what you want is to slurp then read-string
no and so far the solution I have adopted is to write to a tmp-file that overwrite the target file once load has done its job
@qqq: I'm building an in-file debugger
to add instrumentation results as comments
This works pretty well, except for long computations : you need to wait for the whole file to be executed before seeing any result
how does writing to the same file allow you to see results earlier than writing to a tmp file ?
Because the file is opened in your editor, the tmp file is at an obscure path, many clicks away
mmh, we have terminals for that.
It's okay, I'm having quite some fun in this conversation actually
And i have to confess. I'm more about the art than the programming
Well this seems to be a "hard" problem involving hairy concepts such as InputStreams, I'll set it aside for later, and carry on with my art-project.
generally, that kind of thing is done through an editor integration, for example cider (the emacs stuff for clojure) will, after you evaluate a form, add some temporary contents to the buffer indicating the result of evaluating the form. cider doesn't actually write that stuff to the file, it tell emacs the result of evaluating whatever, then the emacs lisp side of cider sticks some temporary data in the buffer to display it, it is never written to a file.
there are some format commands that will send your code over to the middleware and then edit the buffer. format edn and the like
yeah, but what happens with is almost certainly emacs sends the stuff to format to clojure, clojure formats it and sends it back to emacs, then emacs replaces the unformatted bits with the formatted bits
I mean, I don't know, I haven't looked at it, and never use anything more complicated that cider-connect from cider, but that is typically how that kind of thing is done
it separates evaluation and program execution (clojure) from file editing and presentation (emacs, whatever)
Yet one can't comme without the other one
I have a java object that I'm being handed by a factory method. We then use a macro to construct a new object using reify, based on the constructed java object, in order to override a single method with a different implementation.
I need this object to implement a protocol, but because the object (and thus the class name) is dynamically generated, I cannot give the class to extend
(et al) .. at least I don't think I can. So my current solution is to have java.lang.Object
implement my protocol, and this works, as my object is of course an Object
; so it's a 'catch-all'. However, this is ugly, and I don't like it.
Any suggestions?
@joshjones do you know which tool is generated the object ?
yes, it is an external project which generates the object. We considered instantiating the object ourselves, but then we get even more involved in the inner workings of the library, as the constructor is very involved and does a lot of internal work. In short, we need to just assume that we are handed the object from the factory method, and have that to work with.
as you stated the object is generated, it depends which tool is actually generating the object, in function you can or not "guess" the name of the object
we have a macro which takes the object and uses reify
to construct a new one. AFAIK reify
will not allow us to specify the name of the new object, but will generate it
rewrite your macro to generate a defrecord, and take the class of the object, instead of an instance of the object, call your macro at the top level, then just wrap the object in the record
for that case, I would like not even write the macro, just some code that generates the defrecord code, then just paste in the generated defrecord code. you aren't creating a new control flow construct, and the classes and methods involved in that kind of thing aren't likely to change ever
Hello all, I defined
(ns custom
(:gen-class
:name Custom
:main false
:prefix "-"
:methods [[probe [] void]
#^{:static true} [processaMensagemCustom [com.nimsoft.nimbus.NimSession com.nimsoft.nimbus.PDS] void]]))
(defn -probe [] (str ""))
(defn -processaMensagemCustom [] (str ""))
(ns core
(:import (Custom)))
But when I do lein uberjar
say that can´t find Custom. Why?you can't import it, the name Custom puts it in the default package, you can only import things that are in named packages
whatever you are doing, I strongly recommend avoiding gen-class and aot compilation if you can
looking at http://docs.nimsoft.com/prodhelp/en_US/Monitor/SDK/Java/com/nimsoft/nimbus/NimProbe.html the example shows some kind of callback being registered that isn't a static method (looks like a slightly different kind of register call than your original question) so I would still suggest trying something like (.registerHubpostCallback probe (fn [] (println "Hello World")) "call"))
where probe is an instance of NimProbe as constructed in the javadoc examples there
it will probably throw an error either about mismatched types of arguments or mismatched counts of arguments, either way you can work from there
like, open a repl, type (.registerHubpostCallback (NimProbe. "RandomProbe","1.0","MyCompany",args) (fn [] (println "Hello World")) "call"))
and see what happens
but,
public void registerHubpostCallback(Object object, String methodname)
throws NimException
{
setHubpostCallback(object, methodname);
}
protected void setHubpostCallback(Object object, String methodname)
{
this.hubpostObject = object;
this.hubpostMethodName = methodname;
}
(fn [] (println "Hello World"))
evaluates to an Object and "call"
is a String naming a method on the Object
user=> (supers (class (fn [] (println "Hello World"))))
#{clojure.lang.IMeta java.util.Comparator clojure.lang.AFn clojure.lang.IFn clojure.lang.Fn java.util.concurrent.Callable clojure.lang.IObj clojure.lang.AFunction java.io.Serializable java.lang.Runnable java.lang.Object}
user=>
user=> (->> (fn [] (println "Hello World")) (class) (.getMethods) (map #(.getName %)) (distinct))
("invoke" "withMeta" "meta" "compare" "applyTo" "call" "applyToHelper" "throwArity" "run" "wait" "equals" "toString" "hashCode" "getClass" "notify" "notifyAll" "reversed" "thenComparing" "thenComparingInt" "thenComparingLong" "thenComparingDouble")
user=>
hah, I was wonder what the heck reversed and all the comparing stuff is, those are the result of the new default method stuff in java 1.8 I guess
(defn probe []
(let [nimProbe (NimProbe. "custom" "1.0" "COMPANY CO." nil)]
(doto
nimProbe
(. setSubscribeSubject "QOS_CUSTOM")
(. registerHubpostCallback (fn [sessao dados] (println dados)) "call"))
(do-while (. nimProbe doForever) (do (println "Loop iniciado")))))
so look at the stack trace, go to the place where the error came from, which will be around where it is attempting to call the call method, my guess is it is trying to reflectively find a method with that name and the arguments it expects
if that is the case, you sadly cannot use a regular fn, but you should be able to use definterface and reify
(definterface SomeName (someMethod [this ^TypeOfArg1 arg1 ^TypeOfArg2 arg2]))
fill in the real argument types there, replace the (fn ...)
with (reify SomeName (someMethod [this arg1 arg2] (println "Hello World")))
and replace the "call" method name with "someMethod"
Like this?
(definterface CallbackThis
(^void processaMensagemCustom [^com.nimsoft.nimbus.NimSession session ^com.nimsoft.nimbus.PDS pdsData]))
(defn probe []
(let [nimProbe (NimProbe. "custom" "1.0" "COMPANY CO." nil)]
(.setSubscribeSubject nimProbe "QOS_CUSTOM")
(.registerHubpostCallback
nimProbe
(reify
CallbackThis
(processaMensagemCustom [this arg1 arg2] (println "Hello World")))
"processaMensagemCustom")
(do-while (.doForever nimProbe) (do (println "Loop iniciado")))))
when defining macros, when an error happens, it seems to all get pointed at point of macro expansion ; for multi line macro applications, I'd prefer to get better line number info
this is really hard to do, macros are a src to target transformation, and source and line number information only make sense for the src, and the target may have nothing at all to do with the src
which is to say, you may want it, but you cannot have it without significant changes to the clojure macro system
(as-> (expr) $
(.... $ ... )
(.... $ .... )
(.... $ .... ) ; if err happens on this line, we get error msg pointing to this line
(.... $ .... ))
so as->
is an macro right? yet, how does it expand in such a way that when an exception happens, we get pointed to the right "line/clause" before the expansion ?
and I really need to get correct line numbers, otherwise future me is going to hate current me