This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-01-23
Channels
- # arachne (3)
- # aws (1)
- # bangalore-clj (2)
- # beginners (19)
- # boot (151)
- # cider (72)
- # cljs-dev (9)
- # cljsjs (7)
- # cljsrn (37)
- # clojure (215)
- # clojure-austin (1)
- # clojure-denmark (2)
- # clojure-dev (68)
- # clojure-india (1)
- # clojure-ireland (2)
- # clojure-italy (4)
- # clojure-mke (1)
- # clojure-nl (4)
- # clojure-russia (4)
- # clojure-serbia (1)
- # clojure-spec (29)
- # clojure-uk (23)
- # clojurescript (23)
- # cursive (24)
- # datomic (71)
- # emacs (5)
- # events (1)
- # gsoc (11)
- # hoplon (20)
- # klipse (4)
- # lambdaisland (2)
- # leiningen (3)
- # luminus (3)
- # off-topic (30)
- # om (40)
- # om-next (1)
- # onyx (15)
- # pedestal (19)
- # perun (7)
- # planck (23)
- # proton (1)
- # protorepl (2)
- # re-frame (35)
- # reagent (21)
- # ring-swagger (38)
- # rum (19)
- # spacemacs (9)
- # untangled (11)
- # vim (5)
- # yada (4)
@grav still smells like a tree. I don't know of anything that does that but I bet you could do it by hand in 10-20 lines
Same place as in 1.8... what are you looking for? @seylerius
@seancorfield Don't know where it was in 1.8, either.
If you have Clojure loaded, you have clojure.edn
available -- the require should succeed.
Are you sure you're loading the correct version of Clojure? What does (clojure-version)
show?
user> (clojure-version)
"1.9.0-alpha14"
user=> (require '[clojure.edn :as edn])
nil
-- clojure.edn
is available from Clojure 1.5.0 onwards.Hi, i have a Record which implements Component's LifeCycle protocol, how do i add new methods to the record?
in this case, this throws error, how do i add my-method
without a protocol? do i just add Object
followed by (my-method...
?
if you think a protocol doesn't fit you could just write a function that takes the record as its first arg
@bbloom @gfredericks so, only way to add a method in record is by declaring a protocol for that record?
I wanted the method to 'stick' with record, instead of using it like my.namespace/my-func
@bbloom i have some abstraction on something that is implemented in java. it is sort of like a 'device'. I am using Record to hold the state for the device and i wanted to add some methods on the record which are actually for the device. eg: mount
for the device
i can do, my.ns/mount-device
, but since my record holds most of the state, i wanted it to be callable from the record itself: `(.mount record)
@neupsh what benefit does that provide you? do you need dynamic dispatch to the implementation?
@bbloom just easier grouping related methods (most of them are already in protocol, but there was one or two methods i wanted to add without protocol, but i will probably create a protocol for those, or just add a function)
@neupsh if you’ve got other eggs to fry, feel free - but if you’re new to clojure, you may want to stop and think a bit about why you feel that’s easier. there’s significant advantages to NOT doing that
@bbloom can you explain what the advantages are? i am new to clojure and this is not my primary development platform. I could certainly use guidance and pointers
for starters, functions are first class, so you can pass them around w/o having to wrap them. methods are not first class
additionally, functions are stored in vars, which have better interactive development properties
you can redefine them without having to find every instance of the object and update or replace it
ie instead of an object with a particular class, any map-like data with those keys in it works
the only real benefits of using methods are 1) (sometimes) perf 2) jvm interop 3) dynamic dispatch
if you feel your namespace name is too long to type at the call site, use a single-character namespace alias
@bbloom this method i wanted to add is very tightly related to the recod - mount
for a DeviceRecord
, actually the only methods for the records are the component's start/stop and i wanted to use mount
in the record itself (only because i saw mount
was very close to the device. the implementation of mount
would not be very reusable as i am dealing with only 1 device and the mount method would infact delegate to some inner method of one of the object it holds in its state. Do you think this usecase is still better of with function instead of the method?
@neupsh how tightly related the method is logically doesn’t really matter - do you need it to be a method for jvm interop or dynamic dispatch? if so, then make it a method, if not, use clojure’s preferred unit of logical organization: namespaces
@bbloom thanks for advice. i dont need interop for java side. It will only be called from clojure. I will go with the function in my namespace where the record is.
@simon You might find more folks willing to help at that level in the #beginners channel? That's where folks are happy to spend lots of time working through your early Clojure programs with you.
I need to concatenate two lists in a way that they are still a PersistentList afterwards. Perf not very important. Is there any shortcut to reducing into a new list?
@martinklepsch If performance doesn't matter, maybe (list (concat a b))
?
@beppu that will give me a list containing the result of concat
...
But the idea is good, let me see if I can do something similar 🙂
(into clojure.lang.PersistentList/EMPTY (concat '(1 2) '(3 4)))
;; => ‘(4 3 2 1)
nope 😄timer.core> (apply list (concat '(1 2) '(3 4)))
(1 2 3 4)
timer.core> (type (apply list (concat '(1 2) '(3 4))))
clojure.lang.PersistentList
@martinklepsch Why not just (into existing-pers-list [:foo :bar])
?
@rauh because that will reverse [:foo :bar]
(defn concat-persistent-list [l1 l2]
(reduce (fn [new-list item]
(conj new-list item))
l2
(reverse l1)))
that does the trick but I guess @beppu’s solution is a bit more concise
@martinklepsch Oh yeah that's right. So then (into ... (reverse ...))
?
@rauh valid point haha
sounds like a bad idea @leov
@leov Platform specific file (cljs) is used instead of common file (cljc)
thanks. It's just my fireplace.vim cannot multiplex between browser and server during eval of forms. I opened real terminal in tmux attached to figwheel as a workaround
(I see many people doing repl development with a standalone terminal, however fireplace integrated eval seems better, because you don't keep one more open window)
Those are all good points. Another benefit of protocols is, as opposed to their problems in tooling and interactive development, it might make the maintenance of some parts the program easier, since it serves like a TOC. But proper ns's provide the same, so it might be a matter of tooling. For example, cider has browse-ns, that list the functions associated with a namespace, along with their docs. Protocols do this without tooling. The question then is, how aggressive to create new ns's and new files? There might be some inertia doing that, which might cause a huge ns that has lots of functions in it, that make comprehension hard and maintenance a mess. Java effectively by its design forces you to separate out the separate functions by domain model for example, where as in Python for example, you can have a single module with multiple classes, encapsulating various methods, without impacting overall readability of the file. Ns pragmas a la Obj-C might help there, but I guess the proper solution is, I guess again namespaces. Could you elaborate a bit more on that @bbloom ?
I'm just starting it, and it feels so much more amazing than multiple files and I want a place to learn tricks / tips from
Literate programming....now there's a term I haven't heard in a long time.
@tbaldridge: this is taking your advice ot the extreme
The "generate" part is the fun bit of that....now your source lines won't really match up, right?
You get an error for a .clj file that was generated from a .org file...where do you go to make the edits?
when I open up a "code block" in org mode with org-special-edit, it puts that particular block in it's own buffer
@martinklepsch you could try (list* (concat a b))
(type (list* (concat '(1 2) '(3 4)))) ; => clojure.lang.Cons
@alexmiller would have been nice though 🙂
oh well :) ¯\(ツ)/¯
@bronsa my lists aren’t too long (don’t think I’ll ever reach 100) so perf isn’t too much of an issue
user=> (defn lconcat [a b] (into b (reverse a)))
#'user/lconcat
user=> (lconcat '(1 2 3) '(4 5 6))
(1 2 3 4 5 6)
user=> (class (lconcat '(1 2 3) '(4 5 6)))
clojure.lang.PersistentList
(defn concat-stack [l-front l-back]
;; (into '(4 5) (reverse '(1 2 3))) ; => '(1 2 3 4 5)
(into l-back (reverse l-front)))
🙂not very pretty but ¯\(ツ)/¯
@martinklepsch another option would be to define foldr
and then you could just (foldr conj b a)
-> threads as the second form, ->> as the last. so it depends on the functions you're threading through and where they expect their args
thanks @williewillus, still needs some time to digest
@martinklepsch (defn concat-list [a b] (into b (rseq (into [] a))))
still O(length(a)) but the constant factor should be better than with reverse
Can anyone answer why this doesn't work: (defn my-* ([x y] (* x y)) ([& rest] (reduce my-* 1 rest)))
I imagine it's like a pattern matching from top to bottom - but I might be wrong (I'm a newbie)
actually the function works for both 0 and 2 arguments - it' s just all other cases it fails
i don't know how you defined it in your repl, but that definition that you pasted here won't even compile
so my other question here: if two clauses can't be such that they handle the same amount of args, why can [x y]
and [x y & rest]
coexist?
@cgrand can’t use vectors, dealing with library code… didn’t know rseq
, good to know, thanks!
@zennist these rules are arbitrary (they could have been different): you can’t have the same fixed arity twice, there’s only one varag and it must start at least at the max fixed arity. Fixed arg wins over var arg in case of ambiguity.
@zennist essentially, the way clojure is implemented, optional arguments can only go at the end of a signature. My guess is that ambiguity at the end is allowed vs the ambiguity in the "middle" isn't for: - ease of implementation - a desire to make it clear that multiple arities in clojure are not pattern matching
at the end of day i find that sometimes to understand clojure better you have to be in the shoe of a Java dev
unfortunately i come from more of a functional programming background so sometimes struggle...
I think the wrong assumption you made is that clojure did some sort of pattern matching and that arity definition order mattered (it doesn't)
@zennist if you want the in-depth discussion, it's because of Java method overloading.
Clojure functions are implemented as classes with invoke(a), invoke(a, b), invoke(a, b, c), etc. Where "extra args".
So (fn [& args]) is invoke(ISeq args)
So (fn [& args] and (fn [a]) are ambiguous in dispatch
you could (theoretically) have
class Foo implements IFn {
Object invoke() {
doInvoke(null);
}
Object invoke(Object a) {
doInvoke(Cons(a, nil));
}
Object invoke (Object a, Object b) {
// 2-args impl
}
Object doInvoke(ISeq args) {
// varargs
}
}
I'm a bit confused now - @bronsa so does your example show that there isn't really any ambiguity for 2 args case?
@zennist I'm saying that there's not a technical reason (that i'm aware of) why clojure doesn't let you do it, rather, it's likely an implementation detail/a philosophical reason
@bronsa but in this example: what should I dispatch for (foo 1): (fn [a] ...) (fn [& a] ...)
I could ether call it as (foo 1) or (foo '(1))
@tbaldridge that's clearly 1 argument tho
Right, so it's an argument in favor of precedence dispatch. That's valid.
@tbaldridge : I better see the point you were making earrlier now -- things become bad when I have multiple blocks in org mode which all go to the same *.clj file -- in this case, editing each block in its own buffer does not sve me
Let me back up and say I agree with @bronsa with an additional dispatch in every invoke you could implement the support of something like (fn ([a b c] ...) ([& args] ...)) where the fixed arities always win out. But that would cost another branch
IIRC, Pixie supports that sort of behavior, but only because ifs are free (as long as the code always takes the same branch).
I really think it's just not legal clojure for philosophical reasons, not performance ones
my POV is that if that worked, people would get the impression that clojure did pattern matching
https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Compiler.java#L3968
I think we've already had this discussion already over IRC years ago, it's one of these things :)
one loop to build methodArray. If we wanted to allow [& _]
and [_]
to coexist we would need either two loops (one for fixed args, one to fill the blanks) or slightly more involved code
btw I refute the "familiar semantics" argument by virtue of java allowing void foo(Object.. x); void foo(Object a, Object b)
to coexits in a same class/interface
huh, I always assumed the compiler overrode invoke for known fixed arities
@bronsa you can have foo(Object.. x); void foo(Object a, Object b)
but the only way to call the first is as a foo(new Object[] { x })
not very vararg
@tbaldridge what do you mean? it kinda does
it just doesn't emit all the 20 invoke arities if you have a vararg arity -- it fallsback on RestFn doing its magic & just implements doInvoke
Right, so you don't pay any cost on the fixed arities, right?
nvm....
I have a new kid in the house and don't sleep much, I understand now 🙂
How can I see what the current leinengen profiles are programmatically?
I’m trying to catch a parsing exception from clojure.data.xml, but this doesn’t work:
(try (xml/parse-str "<hello>\u0000</hello>")
(catch Exception e
(println “nope”)))
The exception is still thrown.I don't think that code is throwing an exception. It seems to be swallowing the exception and printing an error
I isolated the exception in this project: https://github.com/borkdude/xml-exception
The problem seems to be in the combination of clojure.data.xml and [com.fasterxml/aalto-xml “1.0.0”]
When you do lein run
the exception appears, but you can also trigger it from the REPL by calling do-it
@borkdude I've been playing with it, and it's weird. I have no idea why that's not catchable.
@borkdude I caught it.
(try (xml/parse-str (seq "<hello>\u0000</hello>")) (catch Exception e e))
Is this related to this ticket? http://dev.clojure.org/jira/browse/CLJ-1332
Nice (!) interview question. 🙂
is there a thread-local version of with-redefs
? trying to adapt some test code that relies on it in order to run tests in parallel
trying to make a control structure to do this: try a request with a token. if the request fails, refresh the token and try the request again. can anyone recommend a good flow?
(or (request token) (request (new-token)))