Fork me on GitHub

Hey everyone, I was going to tweet out of frustration, but I figured asking for help here was a better option. After 3 years of dabbling in clojure (I've built a couple trivial projects in it), listening to Rich's talks, and just generally being sold on the language, I'm trying to get started using it at work, which means figuring out builds, linting, testing, editor integrations, and all-around dev workflow. But after 30 hours or so in the last few weeks, I'm so frustrated. It's been a worse experience than building javascript with webpack 2, or developing with php/apache. A big part of it is my lack of familiarity with java, but it should not be this hard. I've asked plenty of questions on clojurians, read tons of documentation and source, but I'm stuck. I want to love the language, and I think once I "get it" I'll be good to go. I know this is a big ask, but is anyone here willing to spend a couple hours with me on the phone or screensharing to help me get started? I feel like I'm banging my head against the wall.

peter-kehl00:10:46 reads: "A Symbol is resolved: ... Else, it is not qualified and the first of the following applies: .... 1. If it names a special form it is considered a special form, and must be utilized accordingly. 2. A lookup is done in the current namespace to see if there is a mapping from the symbol to a class.... 3. If in a local scope (e.g. in a function definition or a let form), a lookup is done to see if it names a local binding (e.g. a function argument or let-bound name). If so, the value is the value of the local binding. 4. ..." However, aren't symbols in local scope considered over Java classes? (let [Object 1] Object) returns 1, not java.lang.Object. The same for (let [if 1] if). Hence, shouldn't (3) above be pushed up to be #1?


Feel free to pm me if you're up for something like that. Thanks.


@jstaab Hi Jon. Good your question. If you find any tutorials/resources on using Clojure at work, would you share them, please.


@peter.kehl I don't think Object is a special form, it's just a built-in name. Special forms are more things like if and def (full list here: These kinds of things are what lies at the base of most lisps, which are usually implemented mostly in terms of these building blocks. Object is a foreign language concept. I'd expect it to be #2, but maybe I'm misunderstanding what Object is.


pedantically, 'if' is not a special form, (if ...) which is why something like

user=> (let [if true] (if if true false))


I would not take the text there as definitive, but more as a "it is more or less like this", a complete description would, in my opinion, have to encompass reading(for at least syntax quote), macro expansion (for treatment of '.' sugar), and then compilation, which is what most of that description is concerned with


@jstaab Sometimes Eric Normand has spare capacity for mentoring people, perhaps made more likely with a commercial for-pay arrangement. You could try contacting him.


@andy.fingerhut thanks, I'll reach out!


Evaluation order of local scope vs. Java classes at still seems wrong. As per example with Object bound as a symbol.


@peter.kehl I think I would agree that #2 and #3 seem the wrong way round.


In reality, you'll "never" run into a conflict because class names are CamelCase but local bindings are kebab-case 🙂


Thanks @seancorfield. If you eat Middle Eastern, you may love a Camel-kebab. I'm filing a pull request.

😂 4

actually you get both behaviors, a name like can be def'ed just fine, but the compiler will always reject it when try to use it, because it always attempts to resolve it as a class, you can't let bind it because the compiler generates a class with a field name that the jvm rejects


But that name is "packaged qualified" and doesn't fall into those four rules...


Would be great to receive code review on this solution Any advice/feedback is always welcome! Feel free to comment in the PR 🙂


hi all 🙂


a question: what's the current best practice of using records vs. plain maps + specs?


I've read some opinions on maps vs. records, but they were all pre-spec; does spec make records less relevant for cases not involving Java interop?


How would I convert this java code to clojure?

publisher = Publisher.newBuilder(topicName).build();


I am trying

(def publisher (Publisher/newBuilder topicName))


But that is not working


Ah, I should use the threading macro?


the thing/method notation is for static methods


(.method obj) is for calling regular instance methods


is it normal for a beginner on clojure and FP, to take 4 hours to make your own version of the threading macro? i know everyone has it's own pace of learning, but sometimes i feel frustrated...


no its ubnormal


its very fast learning (for me)


and also i dont have idea what threading macro is


Especially FP takes its time to wrap your head around!


you can add code to slack with the "+" icon next to the message box, so you don't have to post it as an image 😉 makes it easier for everyone helping you, too

👍 4

i tried to make this with reduce, but soon realized that it was too difficult. later i tried to do directly using other abstractions, and no success, so i've made a decomposition of s-expressions and tried to go along with that, realized i've had to reverse the expression to make a simple one, then would have to start taking a list and applying every item to the next, and things got too hard... and i've tried to tackle the problem from another position, trying to take a simple collection and doing this kind of nesting on each other, and doing so without reduce... turns out that this was my code for using inside the macro with minimal changes


the way i code is extremely weird, i get lost quite a few times and then i find my own path doing all kinds of weird examinations and statements about the data...


thanks @curlyfry this works

(def publisher (-> (Publisher/newBuilder topicName) (.build)))


@cybersapiens97 Macros can be quite tricky to write and get correct, even for experienced Clojure developers.


@andy.fingerhut glad to hear that, it gives me more confidence 😅


@cybersapiens97FYI it took 4 years for the version of ->> that's in clojure.core now to be written, the previous one had some nasty interaction with other macros


so even expert clojure developers don't get it right the first time :)


it's useful to think of macros not as syntax transformations but as functions from data -> data (which is what they are!)


hmmm i see, i like writing macros because i love using recursion by my own... yeah i treated the macro input as s-expression, so it was easier to manipulate thinking that way


I think of programming as learning to play an instrument


it’s well established that getting good at say, guitar or piano, takes years of sustained practice, and it’s the same with programming


so just think of those 4 hours as that days daily practice session 🙂


makes sense, you could play that song you like, but it's never going to sound the same, on the hands of a experienced artist


but in time you can get better


exactly, don’t feel stressed that you don’t “get it” in 4 hours, persistence and patience is key 💪


I would like to get let params in clojurescript. I wrote a macro where I define the let params to get back.. but not so cool. I know, I can use at clojure part the &env and &form to get all data. How can I create a similar function at clojurescript part?


(defmacro debug-fn [& body]
  `(do (cljs.pprint/pprint {"ev: " ~'ev "buffer " ~'buffer "m " ~'m "cb " ~'cb "buffsub" ~'buffsub "prebuff " ~'prebuff "prebuff-1" ~'prebuff-1})


I use that like.. (debug (some-fn...)) at cljs


Could I get the let params automatically? ..because very boring to type all time the things..


@sb I think you can do the same in cljs, since the macros are clojure macros


@moxaj not works..


if you simply print the value of &env, what do you see?


yes, I would like to print the &env with a macro at clojurescript side


like this


you are printing during macroexpansion as a side effect



(defmacro debug [] 
  `(cljs.pprint/pprint {:form ~&form :env ~&env}))


Unfortunately, not works for me..


@sb right, should have been '~&form and '~&env, anyway, this should work:

(defmacro debug []
  `(cljs.pprint/pprint (hash-map ~@(->> &env :locals keys (mapcat (fn [x] [`'~x x]))))))

🍻 4

@moxaj thanks works!! 👍

Caio Guedes20:10:15

Guys, does exists any difference when you access a property with (.-myProperty ...) and (.myProperty ...) on interop?


,myProperty calls it as a function, .-myProperty gets the actual value of the property


.myProperty can match a field or a method. .-myProperty can only match a field. This only really matters in cljs where a field and method can have the same name


@noisesmith that's not correct, .-myProperty gets the function as a value if it's a function


you can do (apply (.-log js/console) ["Test"]) for example


I'll take your word for it - none of that works in jvm clojure



(.body js/document)
#object[TypeError TypeError: document.body is not a function]


(.-body js/document)
=> #object[HTMLBodyElement [object HTMLBodyElement]]


to word it a little differently, both .myProperty and .-myProperty access the property obj.myProperty, but (.myProperty obj) converts to the javascript obj.myProperty(); and (.-myProperty obj) converts to obj.myProperty;


as long as we specify that's all cljs only, agreed


you're right, I was assuming ClojureScript as that is where you mainly see the syntax

Caio Guedes20:10:38

:thinking_face: interesting… I got it! thanks!


Is the behavior of .- documented anywhere?


It seems a bit special-like in Clojure/Java and ClojureScript, and quite rare in Clojure/Java in my experience, but it does do something different than if the '-' is not there.


you probably basically never see .- in clojure as every Java class has their fields private


Thanks. The docs there explain to me why .- is not often seen in Clojure/Java --- because it works the same as . for fields in Clojure/Java, except in the rare circumstance that a 0-arg method and a field have the same name


is that shadowing even possible in jvm bytecode?


I don't know, and it is about 7 miles beyond my curiosity level to find out right now 🙂


I was happy to see it explicitly documented for Clojure/Java in an official place. Somehow I missed that detail before.


I made this algo which matches the most recent report to a date. I currently use map to do it. But the implementatiojn is inefficient, as it filters the reports with each map step. I was thinking to refactor it with doseq, but I dont know how to return values from doseq into a map, and also I have no idea, how I could setup a mutating variable. I was thinking of atoms, but this is only for multithreading? Any ideas??? Thanks!


reduce is the way to write reports


or, I should say, the general structure of generating reports is usually some kind of fold, and the most common fold implementation in clojure is reduce


@hiredman Thanks! I will try to write my problem with reduce then.


it looks sort of like what you are doing might be more of a join (in sql terms vs. a report which I tend to think of as using aggregate operators like count or avg)


in which case you should just clojure.core/for (for a cross product)


@hiredman I am basically merging two different timeseries that have different frequencies; I am assigning to a daily series elements from the "sort of" annual series. Since I know that the series are both ordered, I was thinking that it is efficient if I would remove unnecessary elements from the second series.


  (fn [{:keys [report output] :as accum} thing]
    (if (contains? thing :releasedate)
      (assoc accum :report thing)
      (update-in accum [:output] conj (assoc thing :report report))))
  {:report nil
   :output []}
  (sort-by ; merge sort if inputs are already sorted
   (fn [thing]
     (or (:releasedate thing)
         (:date thing)))
   (concat reports series))))


wow! Thank yo so much!


I am just trying to understand your code. My head is still spinning. 🙂 It is exactly what I was trying to do. I hope some day I will be able to write such code myself. I did read 2 books, did many samples, and still I sometimes sit for hours searching for the right approach. The non-mutation approach sometimes really needs a different approach 🙂


macros are always :clj


that is true. In this case, how can I split the code.. call from clj or cljs?


just don't put the #? in a macro, you can have the macro expand in to a function call, and the function body can have a #?


Ok, sounds good. I test it! Thanks


Sorry, maybe I’m tired. But how can I use a same name in this case?


defn > macro not works.


no, you can't do that


that is kind of the opposite of what I said


the easiest thing would actually be to just check if :env contains :locals in the macro


(if (contains? &env :locals) cljs-stuff clojure-stuff)


Thanks! That is great idea!! parrot


   (defn cljs-env?
     (boolean (:ns env))))

(defmacro debugy []
  (if (cljs-env? &env) 
    `(cljs.pprint/pprint (hash-map ~@(->> &env :locals keys (mapcat (fn [x] [`'~x x])))))
    (->> (keys &env)
         (map (fn [k] [`'~k k])) (into {})) 


solution, maybe useful somebody


Hello Everyone, I am having this vector of map and I want to update all the keys :col4 depending upon col2. if :col2 = California_LA, then :col4 = Los Angeles else :col4 = San Francisco. [{:col1 Alex :col2 California_LA :col3 1111111111 :col4 } {:col1 Berry :col2 California :col3 2222222222 :col4 } {:col1 Charles :col2 California_LosAngeles :col3 3333333333 :col4 } {:col1 DJ :col2 California :col3 4444444444 :col4 } {:col1 Ernie :col2 California_LA :col3 5555555555 :col4 } {:col1 Fred :col2 California :col3 6666666666 :col4 } {:col1 Greg :col2 California_LA :col3 7777777777 :col4 }] Any Suggestion?


so you want to transform each element in a collection so the general idea is (map f coll). so write a function that takes in one of your items and does this


don't think about the collection just transform a single one


How do ClojureScript programmers store dates/datetimes for shipping around via Transit and then doing comparisons on? I'm looking for the equivalent of Python's builtin and datetime.datetime, but I have a feeling that JavaScript Date() is not the right answer.


I used either Date or an ISO string representation to convert on the other end


@noisesmith do you know if cljs.time produces JS date/datetimes or are they some ClojureScript specific format?


not off the top of my head, I've never used it


perhaps something from goog


Unrelated question - did something happen in 2016? I seem to keep running into ClojureScript projects and blogs that were last updated in 2016.


I think it became easier to use stuff from npm, and optimized builds without needing to define externs manually? If I recall that stuff was happening around that time, and it makes "wrapper" libraries much less needed

👍 4