This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-10-18
Channels
- # 100-days-of-code (6)
- # announcements (4)
- # beginners (126)
- # cider (49)
- # cljdoc (28)
- # cljsrn (3)
- # clojure (89)
- # clojure-dev (19)
- # clojure-greece (2)
- # clojure-italy (13)
- # clojure-mexico (1)
- # clojure-nl (13)
- # clojure-spec (108)
- # clojure-sweden (1)
- # clojure-uk (48)
- # clojurescript (31)
- # cloverage (3)
- # core-async (16)
- # cursive (28)
- # data-science (3)
- # datascript (1)
- # datomic (60)
- # defnpodcast (1)
- # docker (17)
- # editors (18)
- # emacs (16)
- # events (1)
- # figwheel (22)
- # figwheel-main (4)
- # graphql (26)
- # jobs (2)
- # off-topic (9)
- # om-next (2)
- # overtone (4)
- # perun (1)
- # re-frame (2)
- # reagent (18)
- # reitit (1)
- # ring-swagger (2)
- # shadow-cljs (2)
- # tools-deps (49)
- # uncomplicate (1)
- # unrepl (1)
- # vim (2)
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.
https://clojure.org/reference/evaluation 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?
@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: https://clojure.org/reference/special_forms). 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))
true
user=>
worksI 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 https://clojure.org/reference/evaluation 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.
actually you get both behaviors, a name like foo.bar
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 🙂 https://github.com/LeandroTk/learning-functional/pull/12/files
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();
hey guys
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...
here's my version https://i.imgur.com/sbgiFss.png
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
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
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
it’s well established that getting good at say, guitar or piano, takes years of sustained practice, and it’s the same with programming
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})
~@body))
Could I get the let params automatically? ..because very boring to type all time the things..
@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]))))))
Published simple guide on how to do cljs on AWS Lambda https://medium.com/@mihailstumkins/clojurescript-quick-start-for-serverless-and-aws-lambda-e646ff136baf?source=linkShare-4b1d49e34d5c-1539865321
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
I'll take your word for it - none of that works in jvm clojure
meanwhile
(.body js/document)
#object[TypeError TypeError: document.body is not a function]
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
: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.
https://clojure.org/reference/java_interop and https://clojurescript.org/about/differences#_host_interop
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!
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
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)
@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.
(:output
(reduce
(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))))
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 🙂
it is, I think, sort of a https://en.wikipedia.org/wiki/Sort-merge_join
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 #?
the easiest thing would actually be to just check if :env contains :locals in the macro
#?(:clj
(defn cljs-env?
[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 {}))
))
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
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 datetime.date
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
thanks @noisesmith
@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
yeah - it's using a bunch of goog types https://github.com/andrewmcveigh/cljs-time/blob/master/src/cljs_time/core.cljs#L162
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