This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-04-06
Channels
- # architecture (2)
- # aws (6)
- # bangalore-clj (3)
- # beginners (7)
- # boot (29)
- # cider (26)
- # cljs-dev (52)
- # cljsrn (1)
- # clojure (249)
- # clojure-dev (9)
- # clojure-italy (2)
- # clojure-norway (3)
- # clojure-russia (178)
- # clojure-uk (30)
- # clojureremote (6)
- # clojurescript (91)
- # core-async (4)
- # cursive (8)
- # datascript (3)
- # datavis (1)
- # datomic (6)
- # emacs (3)
- # figwheel (2)
- # hoplon (14)
- # incanter (6)
- # luminus (8)
- # mount (7)
- # off-topic (22)
- # om (25)
- # onyx (41)
- # pedestal (7)
- # re-frame (9)
- # ring (1)
- # spacemacs (4)
- # sql (1)
- # uncomplicate (1)
- # unrepl (37)
- # untangled (90)
- # yada (77)
Let’s suppose I have deftype looking next way:
(deftype ^{A: a} Name [])
I want define macro generating deftype:
(defmacro dotype [name]
`(deftype ^{A :a} ~name []))
However, I’m losing information about metadata.
(macroexpand-1 '(dotype T))
;> (clojure.core/deftype T [])
I tried to use tricks with vary-meta to avoid using ^{} in macro. Unfortunately, deftype doesn’t support IObj interface (doesn’t support metadata), and all my tries didn’t work.
Please suggest the way to implement this macro. thanks!rmuslimov the macroexpand won't show metadata unless you bind *print-meta*
true
oh - wait, it's a map at that point (or should be...) ... never mind
@noisesmith cool thanks, didn’t know about it
(defmacro dotype [name]
`(deftype ~(with-meta name {:a :a}) []))
(set! *print-meta* true)
(macroexpand-1 '(dotype T))
;> (clojure.core/deftype ^{:a :a} T [])
but here i works, when I’m using with-meta: Unable to resolve symbol: A in this context
I’m playing with this example: https://github.com/slipset/soap-box/blob/master/src/soap_box/server.clj#L36
these are not type annotations
it's an annotation - the annotation is imported from javax.jws in the example
(the class of the annotation that is)
you can use ^{:type Foo} if all you want is a type annotation, but the ^{Foo bar} form is for when you want to attach the key Foo, in this specific context for an annotation (but we also use annotations like :doc etc.)
maybe you already understand this and I misunderstand the conversation at this point
in a java program, it would look like @Foo
, but we use metadata instead of the @ syntax
High Level Problem: I want to use Spec for validation during production. For example, a schema of a database, and using Spec to verify that the input matches the schema. Low Level Question: Now, during production, spec/asserts will be turned off. My question now is: are these certain spec tests that will be run even when spec/asserts is turned off?
does a namespace implement anything? ie, #namespace[cider.nrepl.middleware.stacktrace]
? what is this? is it just a symbol with a reader notation? does it implement anything, have any fields?
@dpsutton namespaces actually do quite a lot if you dig around in the implementation. They are global, mutable unreadable objects
I need a reliable translation from namespace to where a file would be found if it's part of the project, like what require does but only source not dependencies
I've written a "use tools.namespace and filter out things that are in a dir tree / not in jarfiles" function before.
I'm building a cider feature to filter the stack Trace down to just your application and it's surprisingly difficult to figure out the name of a project
@dpsutton well, I'm allowed to install any number of namespaces with any paths I like in one project
clojure doesn't enforce any rules about that (except the namespace name having to map to the classpath relative path for require to work, of course)
based on talking yesterday, if i can get the canonical representation of a file from a namespace, i can then check if that file exists. this is true, yes? but i'm worried if this is run and connected rather than jacked in
With specter, is there a way to use walker but still collect the path to the found thing?
@dpsutton my point is that "project name" isn't going to be a reliable thing you can check for- I can create files with all kinds of silly paths that have nothing to do with each other, under one project
why would connecting change how your mapping to files works?
i was prototyping using the file location and the user.dir but that doesn't work once compiled
why would you need user.dir - the file paths are absolute
or do you only want file paths if they are under user.dir - what about just assuming that if it came from a file on disk and not inside a jar, the user considers it "theirs"?
i resolved the file from the var metadata and checked if it started with the user.dir
but the file metadata loses that prefix when compiled into a jar for testing or however that works
if you use io/resource you get either a jar uri, or a file uri, for the resource
io/resource takes a relative path - you can infer relative path from the namespace name
and it's funny how simple a problem this is, it's just difficult to determine what the common ns part is for the user's code
when would the definition come from a file on disk, and not be something the user owns?
I mean directly, without using a jar uri
i'm a .NET guy at work so I'm really out of my depth in the guts of how the jvm lays things out. so i'm learning and when i'm understanding more i'll have the patch
some is clojure.core/some
+user=> ( "clojure/core.clj")
#object[java.net.URL 0x41d426b5 "jar:file:/home/justin/bin/bench!/clojure/core.clj"]
oh i wasn't using jar uri's at all, and in fact that would have signalled that it wasn't from the project
if I ask for foo/bar.clj instead it would give me a file uri
i know i've seen temp2342352.clj as filenames in the past when watching the nrepl traffic so i'm hesitant to rely on filename
but only the user's own code will be in that right?
you could exclude /tmp/ to be safe?
that just seems to make things simpler
alternatively, you could parse project.clj and look at their source paths
and correlate that with pwd
that's fair
you could look at classpath and filter for files
=> (System/getProperty "java.class.path")
"/home/justin/bin/bench:src"
for each entry, test if it is a directory
yes - that's my clojure.jar repl (I name the jar bench because it's executable and contains criterium)
this is from lein repl
=> (System/getProperty "java.class.path")
"/home/justin/target/classes:/home/justin/.m2/repository/org/clojure/tools.nrepl/0.2.12/tools.nrepl-0.2.12.jar:/home/justin/.m2/repository/clojure-complete/clojure-complete/0.2.4/clojure-complete-0.2.4.jar:/home/justin/.m2/repository/criterium/criterium/0.4.2/criterium-0.4.2.jar:/home/justin/.m2/repository/org/clojure/tools.trace/0.7.6/tools.trace-0.7.6.jar:/home/justin/.m2/repository/alembic/alembic/0.2.0/alembic-0.2.0.jar:/home/justin/.m2/repository/lein-as-resource/lein-as-resource/2.1.3/lein-as-resource-2.1.3.jar:/home/justin/.m2/repository/org/flatland/classlojure/0.7.0/classlojure-0.7.0.jar:/home/justin/.m2/repository/org/tcrawley/dynapath/0.2.3/dynapath-0.2.3.jar:/home/justin/.m2/repository/org/clojure/clojure/1.8.0/clojure-1.8.0.jar"
right
but you can actually test instead of inferring from name 😄
and it looks like tools.namespace can search a directory for namespaces inside a directory
so then, any namespaces matching the namespaces from directories and not jars must be the users code
very likely, at least...
(nsfind/find-namespaces
(map
(filter (complement #(.endsWith % ".jar"))
(clojure.string/split classpath #":"))))
(cider.nrepl.test-session
cider.nrepl.test-transport
cider.test-ns.first-test-ns
...
thanks <@U051SS2EU> this might be something i can attack here
i'll need to do reading if the classpath separator is consistent across platforms etc but this feels promising
thanks @noisesmith
@dpsutton the classpath delimiter is consistent, but as seen in my first example, not all jars end with .jar
but you can call io/file on the classpath entry, and check .isDirectory
yeah i was just doing that as an easy way to toss out the jars. thanks for all of the help. jars not ending in .jar
is definitely some useful info
different functions that are perfectly interchangeable, it would make sense to me if they would be equal
well, to me function (as of ifn?) is an interface, it is up to the underlying type to define equality or not
moreover, it's always possible to know if two functions are equal because all objects have an equals method
@leonoel Just for fun, don't do this:
(defn my-fn-eq?
[f1 f2]
(and (= (class f1) (class f2))
(= (vals (.& f1)) (vals (.& f2)))
(= (keys (.& f1)) (keys (.& f2)))))
(let [f1 (partial + 1)
f2 (partial + 1)]
(my-fn-eq? f1 f2))
Hi i am having problems with lazyness or some kind of optimizations i think: I try to solve a problem on hackerrank https://www.hackerrank.com/challenges/cube-summation so far i went from doall reduce to doseq with atom (i try to avoid atoms) latest bit more ugly try:
(require '[clojure.string :as s])
(let [n-tests (Integer. (read-line))]
(doseq [_ (range n-tests)]
(let [[n ops] (s/split (s/trim (read-line)) #" ")
result (atom (mapv (fn [_] 0) (range (Integer. n))))]
(doseq [_ (range (Integer. ops))]
(let [[action & numbers] (s/split (s/trim (read-line)) #" ")]
(if (= action "UPDATE")
(swap! result (fn [r] (update r (- (Integer. (first numbers)) 1)
#(+ % (Integer. (last numbers))))))
(println (apply + (subvec @result (- (Integer. (first numbers)) 1) (Integer. (last numbers)))))))))))
put it never prints when i expect it to print (it asks for the next input, before it prints the previous printthe issue i get is:
Your Output (stdout)
~ no response on stdout ~
so i guess it expects me to print at the time it sends the querysame with dotimes
it asks me for next input before it prints previous println
tried to add flush
same result
example for closing components https://github.com/danielsz/system/blob/master/src/system/components/elasticsearch.clj
@peterromfeld what is your input ?
2
4 5
UPDATE 2 2 2 4
QUERY 1 1 1 3 3 3
UPDATE 1 1 1 23
QUERY 2 2 2 4 4 4
QUERY 1 1 1 3 3 3
2 4
UPDATE 2 2 2 1
QUERY 1 1 1 1 1 1
QUERY 1 1 1 2 2 2
QUERY 2 2 2 2 2 2
@borkdude from java perspective i guess you make a object that has a close
or stop
method after you started it
would it be absolutely true, or at least a reasonable assumption given standard practices, that every namespace in a users project shares some common prefix?
@dpsutton i found it the hard way that its verry good to have everything in your project namespaced by some unique project name or you can get easy into clashes with things like user
and co
@dpsutton i dont fully understand your question, you can use whatever namespace you want, but to make sure you dont clash with other namespaces its best practice to use prefixes
we tried to flatten our directory structure and soon got the problem that user
ns
is already taken, so going forward i would always prefix my project namespaces
@leonoel yes that the expected output 🙂
@peterromfeld i'm building a feature in CIDER that will flag user's code in stack traces. I'm inspecting the classpath and finding local namespaces to find all loaded namespaces. However, due to lein profiles, not all of the code is on the classpath (think test ns's here) so i'd like to build a way to match against known namespaces and match likely namespaces as well. So i'm reducing all of the namespaces to a common prefix, and I'd like to know if this exists in general
@leonoel but not working and think its because read-line
executes before println
@dpsutton for me personal it sound to much magic, and user should explicit tell his namespace prefix
@istvan i dont know of a newbie guide for transducers or laziness, and for practical i dont have experienced performance bottlenecks that transducers solve so far (usually there are enough other bottlenecks), what i liked for profiling to find actual issues is https://github.com/ptaoussanis/tufte 😉
formerly timbre (they spliced it now)
in addition ive seen that added complexity with more junior team mebers slows down team-performance more, then complex code helps application performance in relation
i believe if you consider yourself a newbee you should look more into how to make small composeable functions, improve your naming to make other better understand your code, (my personal favourite, how to make more poweruse of datastructures to escape nesting - in some cases you need nesting for frontend rendering)
I’ll still happily believe there are lots of things that don’t really need it but I’ve now used it in a few places and it’s pretty slick
but hopefully that will get better over time as I get more experienced, docs get better, and common idioms get added to specter
(I previously thought: uh that’s cool but what’s with the upper case also I don’t really know if I’m going to use this)
the graphql lib from walmart labs has a lot of transformations, walking, also uses ordered maps via flatland lib internally etc, etc, lots of potential uses for specter imho there
@triss it's better to just not turn keys into keywords
but there's clojure.walk/prewalk which makes it easy to detect map-entries and rewrite their keys
thanks @noisesmith i’ll see how easy ho i like dealing with string keys
it's a legitimate difference of philosophy of course, but given that there are many valid json keys that are nonsense as keywords, I prefer just to keep it as strings
^^^ It's also faster to not convert them to keywords, and keywords don't really ever get garbage collected, so if you're parsing a very very large number of json documents with very varying keys over time....
@tanzoniteblack happily that's no longer true (keywords are now weak refs)
oh really? Awesome
what version did that change in?
I still stand by the other arguments against keywordizing though :)
@tanzoniteblack the commit is from 2010 https://github.com/clojure/clojure/commit/02559a4aad442253b601870f7c9aa04c91baf235
well then...
@peterromfeld as regards to hackerrank I would recommend to separate the sideeffects (reading input, writing output) from computation - otherwise it's hard to reason about the function. I came up with something like this
Although it's not efficient - will timeout for more complex test cases - it should work for simple cases.
I prefer exercism to hackerrank. The clojure problems on exercism seem to be made by a clojurian rather than translated from another language.
Is it more interesting to have problems tailored to the language you choose?
Not especially. Parsing stdin for input gets old, fast though. On exercism you work on problems with a real app locally so you can use all of your own tooling without having to copy and paste.
@jstew i've been doing hackerrank problems, and hadn't heard of exercism, so I will check that out. I feel like the stdin thing is only a problem once or twice, I have a function I write and just basically copy into each solution. Will check out exercism though, thanks.
I just checked exercism and am excited to give it a whirl. thank you for pointing that out @jstew
are these equivalent: (.log js/console 43 {:g 1})
and (apply #(.log js/console %) '(43 {:g 1}))
there's also .apply
, which does require an extra argument
but for console.log it doesn't matter. var f=console.log; f("foo");
works, at least in chrome
so you can (.apply js/console.log nil "foo")
Say, looking at this page: https://clojurescript.org/reference/javascript-library-preprocessing ...am I correct that this isn't currently available via the cljsbuild lein plugin?
....since I don't have a place to define a (defmethod)
that is available to the clojurescript compiler?
@timgilbert don't actually do this, but you can put arbitrary code in a project.clj inside a ~
if a function I write will throw an error if its input is anything except a string, should I change the function to allow for any kind of input? Or is it idiomatic to have it throw an exception?
in my opinion you should throw a more descriptive error as to why it only accepts strings
alternatively, call clojure.core/str
on your input
and that makes sense that there should be a good reason why it would only accept strings
i'm a bit unsure on profile s, can I reliably switch on a profile
to run a program differently in dev vs prod?
If so, how can I find out dynamically which profile
is being run? (if not, is there a better alternative?)
lein profiles are entirely about how lein is configured, and you should not be using lein at all after you have deployed (to dev or production or whatever)
Do I need Clojurescript to run Datascript? I want a little in-memory DB for a server I'm building
@hiredman should it be my own config variable then, for switching on whether it's dev/prod?
I am not a huge fan of a single dev/prod switch, I prefer something like a configuration file
the simplest configuration file is just a file containing a clojure map that you read in using read
i have a function that takes a numeric id
- what is a good way to make sure it actually is positive integer? should i do a precondition? is that a common thing to do?
I tend to use preconditions for that kind of thing
@hiredman i actually agree with dev/prod switch is bad mentality... not sure how to do this otherwise tho I've got a huge Component system map, and need to remove one component from a huge map when in development, and don't want 2 massive, almost identical edn/clj files defining the map. Is there a way around a conditional switch I'm not seeing?
These days you could also use spec
@josh.freckleton (component/start (cond-> (build-system) (System/getenv "NO_THING") (assoc :thing :dummy))
@josh.freckleton: I agree this is kind of a pain point. In the past I have sometimes used lein profiles to include one of two possible additional source paths for this kind of thing, like env/prod
and env/dev
But I actually found it to wind up causing me a lot more trouble than it was worth
These days I tend to have my apps figure out what environment they're running in on start-up, regardles of what build was used to create them
...which you could do by inspecting the URL or maybe looking for a cookie to set "dev mode", etc
I have this repo that I haven't pushed or worked on in a while "morphogenesis" which is supposed to be a library for using a rules engine to manage configuration
One way this is helpful is that it makes it easier to debug problems caused by advanced compilation if you were only deploying your :advanced build in a production environment
most configuration systems seem to be about trying to limit the amount of conditional configuration to a few prescribe things(override or configuration inheritance rules), but for any long lived large project conditional configuration takes over everything
so if you want to parameterize how your system map is created, write a function that creates your system map, don't just def it at the top level
I like that example code, would this be similar in spirit, or would you forsee pains in swapping out your
(System/getenv ...)
with a similar
(env :dev-flag)
(from environ
) and :dev-flag
is in profiles.clj
the component Lifecycle protocol is extended to Object as a noop, so you can put anything in the system map and it will be fine
as I said, I don't like a coarse grained thing like a dev/prod switch, so whatever mechanism I used I would prefer something like enable/disable thing
I agree, something closer to feature-flags is easier to manage than build parameters in my experience.
contains?
works with false and nil
(contains? #{:a :b :c} :a)
(contains? #{:a :b :c false nil} nil)
(contains? #{:a :b :c false nil} false)
are all trueRe: config, maybe have a quick look at Aero? It solved my issues in an elegant way. YMMV of course
are named arguments common in clojure? i'm creating a wrapper for Bugzilla .. so i'd like to query like :project Firefox :status :NEW
.. should my (query-bugs ...)
just take a map like (query-bugs {:project Firefox :status :NEW})
or is there a way to make that a bit more strict?
I see Practical Common Lisp creates a DSL for querying an MP3 database .. maybe that is an interesting example.
@st3fan somewhat common. There is a way to do that by destructuring a variable arguments list into a map.
(defn a [& {:keys [arg1 arg2 arg3]}] (println "my args are" arg1 arg2 arg3))
Still, not super strict, since unrecognised arguments are ignored.