This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-04-12
Channels
- # announcements (1)
- # babashka (124)
- # beginners (98)
- # calva (54)
- # cider (32)
- # cljdoc (5)
- # cljs-dev (131)
- # cljsrn (1)
- # clojure (107)
- # clojure-australia (2)
- # clojure-europe (2)
- # clojure-losangeles (1)
- # clojure-norway (3)
- # clojure-uk (28)
- # clojurescript (21)
- # conjure (86)
- # core-async (7)
- # cursive (3)
- # datascript (5)
- # datomic (28)
- # defnpodcast (2)
- # devcards (1)
- # exercism (47)
- # fulcro (22)
- # graalvm (29)
- # graphql (1)
- # malli (5)
- # nrepl (31)
- # off-topic (111)
- # re-frame (23)
- # reitit (4)
- # spacemacs (6)
- # tools-deps (10)
- # tree-sitter (1)
- # xtdb (6)
My mentor adviced me that ..
is unidiomatic with Java interop. Where can I read about that?
Given that ..
is created for the purpose of painless Java interop, the advice itself is suspect.
The comment is here: https://exercism.io/mentor/solutions/2d316846219d4bc0ac79d1aeaf3888d7
I kind of like using ..
so if that part of the comment can be disregarded, according to you, I am happy to do that.
Your specific use of ..
is not unidiomatic at all. An analogy is using ->
to get a nested map key's value vs. using get-in
. Do what feels right for the context you are in.
(-> m :path :to :key)
vs. (get-in m [:path :to :key])
.
P.S. I saw your solution earlier but did not comment because I have not solved that specific exercise myself, 😀 I agree about simplifying the functions a bit. [The below comment is strictly my opinion, I am not speaking for the community.] My thumbrule is, a function should have a docstring and only a docstring. If I have to sprinkle comments in the middle of the function, it is a candidate for simplification. Also, I love one quote from Google's Java best practices related to single responsibility principle. Here is the gist, "If you cannot explain in one sentence what a class does, that class should be broken into multiple classes." (Not exact quote, but the gist of it.) I apply the same rule to my functions.
I started with adding some doc strings. Not sure what to do next, because I think things are pretty clear. Haha.
I saw the same thing being discussed in the beginners channel and some prefer using -> instead of .. because it supports both Clojure functions and interop functions. Does not mean .. is unidiomatic. It is still used in places in the official guides.
If you need reading material, this is a good start: https://clojure.org/reference/java_interop
So, the docs says note that the preferred form at the top expands `Classname` to `(identity Classname)` . Referring to:
(.instanceMember Classname args*) ==>
(. (identity Classname) instanceMember args*)
If I evaluate java.lang.String
and (identity java.lang.String)
, they both evaluate to the same thing. What gives?
Also this If the second operand is a symbol and no args are supplied it is taken to be a field access - the name of the field is the name of the symbol, and the value of the expression is the value of the field, unless there is a no argument public method of the same name, in which case it resolves to a call to the method. If the second operand is a symbol starting with -, the member-symbol will resolve only as field access (never as a 0-arity method) and should be preferred when that is the intent.
Why do you think the -
prefix is made optional in this way? Wouldn't it be cleaner if it was a method call w/o that prefix and field access with? I'm thinking the flexibility probably has some use somewhere...
I looked around a bit and here's what I've found. There is a slight distinction between a class and a class object (not instance). https://stackoverflow.com/questions/32266326/clojures-dot-special-form-weirdness That does not answer any of your questions though.
Java Class
class has a few methods, and if you wanted to call those, you'd need an instance of Class<T>, where T is another class.
And .
is not usually used unless you are doing some very low level stuff. You'll see .
used a lot in Clojure's own source code.
Some experiments,
(. (identity Math) ceil 1.5) ;; throws
(. Math ceil 1.5) ;; works
(Math/ceil 1.5) ;; works
So, indeed Math
is not the same as (identity Math)
.(. (identity String) isInstance "Hello, world!") ;; works
(. String isInstance "Hello, world!") ;; throws
So, I can conclusively say that (identity C)
creates an instance of Class<C>
instead of an instance of C
.
Yes, reading about the .
special form, I also started thinking that maybe that's what the mentor confused ..
with.
Okay, I bit the bullet and did https://exercism.io/mentor/solutions/3eb3f35ecba841759901c75f03e8014c.
The flow of logic between yours and mine are pretty similar actually. Don't think it can be improved much further.
What about this? I published. https://exercism.io/tracks/clojure/exercises/meetup/solutions/3eb3f35ecba841759901c75f03e8014c
Not much different from yours really. But I did plus 1 month then minus 1 day to get to the last day of the month. Used that as days-count
. Think that is a little more accurate.
And I exploited the fact that the second Sunday is actually the first Sunday when you start looking from the 8th day of the month etc.
Well I did Poker back then: https://exercism.io/tracks/clojure/exercises/poker/solutions/0f472f22aac44a0faa69d7a0f5f93c3b Now I find my solution not so good. Can you do it better?
Peeked at the Bank Account solution. I think as-> is usually bad style. Clojure functions belong to two categories. One category takes in collection and outputs a collection. These are the functions where you can omit the collection and you get a transducer. The collection is always the last parameter. Use thread last macro ->> with these. The other category takes the most important thing as the first element. Use thread first with these. Don't mix the two with as->. Use a let binding to hold the intermediate value if you need to.
Read https://www.google.com/url?sa=t&source=web&rct=j&url=https://stuartsierra.com/2018/07/06/threading-with-style&ved=2ahUKEwiZxbuQoOboAhVDfisKHU-ZBtIQFjAAegQIAhAC&usg=AOvVaw0gj97wAGJ13R67hrzJzb3q&cshid=1586810094665 and https://www.google.com/url?sa=t&source=web&rct=j&url=https://stuartsierra.com/2018/07/15/clojure-donts-thread-as&ved=2ahUKEwiZxbuQoOboAhVDfisKHU-ZBtIQFjABegQIAhAI&usg=AOvVaw0YpYfV4J73RZlLTiSEPHJB&cshid=1586810176760
Thanks! I've actually read those, but it was long ago and they flew over my head. Still not sure about it. I like how data flows through a threading. I'll sleep on it. Haha.
I ignored their suggestion as what they were saying isn't formalised anywhere, and it was just about styling.
Yeah, I also disregard some comments at times. But generally, there has been stuff to learn with almost all feedback I've received, so my default is to try find what the lesson is.
A cool use of this channel would be as a forum where mentors can calibrate some. But maybe the platform has such features?
I don't think the platform has such a feature. But there is a Slack channel where mentors can discuss stuff.
That was one of my inspirations for becoming a mentor, wanting to do a little to fix some of the rough edges I experienced as a student. One thing is that there is a certain pressure that the mentor naturally feels to suggest something, else it be interpreted as lazy.
I saw the same thing being discussed in the beginners channel and some prefer using -> instead of .. because it supports both Clojure functions and interop functions. Does not mean .. is unidiomatic. It is still used in places in the official guides.