Fork me on GitHub
#exercism
<
2020-04-12
>
pez14:04:58

My mentor adviced me that .. is unidiomatic with Java interop. Where can I read about that?

hindol14:04:31

Given that .. is created for the purpose of painless Java interop, the advice itself is suspect.

hindol14:04:09

Maybe I am missing some context. Maybe the full comment has some explanation.

pez15:04:36

I kind of like using .. so if that part of the comment can be disregarded, according to you, I am happy to do that.

hindol15:04:15

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]).

pez15:04:44

Cool. Thanks!

hindol15:04:50

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.

pez15:04:12

Thanks, I agree with all that you write here. I'll try tp apply it on the exercise.

pez16:04:29

I started with adding some doc strings. Not sure what to do next, because I think things are pretty clear. Haha.

hindol21:04:12

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.

hindol14:04:38

If you need reading material, this is a good start: https://clojure.org/reference/java_interop

pez07:04:16

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*)

pez07:04:05

If I evaluate java.lang.String and (identity java.lang.String), they both evaluate to the same thing. What gives?

pez07:04:34

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...

hindol08:04:27

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.

hindol08:04:39

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.

hindol08:04:00

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.

hindol08:04:51

I wonder if the mentor confused . with ...

hindol08:04:07

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).

hindol08:04:16

(. (identity String) isInstance "Hello, world!") ;; works
(. String isInstance "Hello, world!") ;; throws

hindol08:04:19

So, I can conclusively say that (identity C) creates an instance of Class<C> instead of an instance of C.

pez10:04:41

Yes, reading about the . special form, I also started thinking that maybe that's what the mentor confused .. with.

pez13:04:02

I've updated my solution slightly. Not sure it is much simpler, but maybe a little.

hindol16:04:43

The flow of logic between yours and mine are pretty similar actually. Don't think it can be improved much further.

hindol16:04:17

I feel mine is slightly more readable, but I am biased, 😀

pez17:04:50

I'm not a mentor, so can't see and apply my biased opinion. 😎

pez18:04:22

I like it. Will read a bit more carefully, but at first glance: awesome.

hindol18:04:19

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.

hindol18:04:49

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.

pez18:04:20

Which one should we pick next? 😃

hindol18:04:16

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?

pez19:04:56

Started with Bank Account here. Will do Poker next. But not looking at yours first. 😃

pez19:04:04

Submitted Bank Account. Now going for Poker.

hindol19:04:17

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.

pez20:04:08

What is as-> meant for then?

pez21:04:35

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.

dharrigan15:04:44

I'm not too sure about Exercism, I've had suspect advice from a Mentor too.

dharrigan15:04:16

I ignored their suggestion as what they were saying isn't formalised anywhere, and it was just about styling.

pez15:04:25

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.

pez15:04:32

A cool use of this channel would be as a forum where mentors can calibrate some. But maybe the platform has such features?

hindol15:04:38

I don't think the platform has such a feature. But there is a Slack channel where mentors can discuss stuff.

Bobby Towers21:04:53

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.

hindol21:04:12

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.

pez07:04:16

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*)