Fork me on GitHub
#beginners
<
2019-05-17
>
Marco Nicolodi01:05:11

I'm storing a vector in memory, to kind of simulate a database:

(def ^:private state (atom []))

(defn store
  [simulation]
   (swap! state (fn [_] simulation)))

(defn retrieve [] @state)
It has a function to store and retrieve. The state is an atom. This is my application code:
(defn place-dinosaur [coords]
  (domain/serialize-simulation
    (store
      (domain/place-dinosaur (retrieve) coords))))
I'm feeling that might be some inconsistencies between retrieve and store. I'm I right? I mean, one deref is inside retrieve, and there's a swap also inside store, meaning that it's just a datastructure between these calls, that does not careabout other threads. Is there a mechanism to orchestrate that?

seancorfield03:05:16

@marcocontatopro You could use (reset! state simulation) inside store instead of that swap! call.

kari06:05:24

I already asked this earlier yesterday and @alexmiller and @seancorfield kindly told me to use test-vars when calling deftest in repl. I have deftest get-product-groups-test in namespace simpleserver.domain.domain-test. If I call it in repl like: (clojure.test/test-vars [#'simpleserver.domain.domain-test/get-product-groups-test]) I can see in log that all test fixtures and the actual deftest is being called, but it returns nil and there is no difference if I make a change in a deftest to make if fail (or the test succeeds). Should I do something else to see whether the test fails or succeeds when I call it like that in repl?

snurppa07:05:08

I quickly tested it and seems to output FAIL to stdout from REPL. Have you re-compiled your test? Example from my REPL:

Loading test/clj/app/query/query_test.clj... done
(clojure.test/test-var #'app.query.query-test/failing-test)
=> nil
Loading test/clj/app/query/query_test.clj... done
(clojure.test/test-var #'app.query.query-test/failing-test)

FAIL in (failing-test) (query_test.clj:22)
1 +1=2
expected: (= (+ 1 1) 1)
  actual: (not (= 2 1))
=> nil
So the first call to test-var is successful test, I only get nil. Then I change the code to fail, reloaded the file an run test again -> FAIL output in stdout, return value still nil.

Vasco Ferreira09:05:52

Hello, I'm learning clojure and I'm trying to use a google java library to the translator API (https://cloud.google.com/translate/docs/quickstart-client-libraries#client-libraries-usage-java) In the API docs, the library is imported with:

<dependency>
  <groupId>com.google.cloud</groupId>
  <artifactId>google-cloud-translate</artifactId>
  <version>1.49.0</version>
</dependency>
I imported it as: [com.google.cloud/google-cloud-translate "1.49.0"] and used lein deps to download it. My core.clj is as follows:
(:import [com.google.cloud.translate.Translate])
(:import [com.google.cloud.translate.Translate.TranslateOption])
(:import [com.google.cloud.translate.TranslateOptions])
(:import [com.google.cloud.translate.Translation])

(def translate ((.getDefaultInstance (.getService))) TranslateOptions.)

(def translate (->> (.getService)
                    (.getDefaultInstance)
                    (TranslateOptions.)))
But this doesn't work. It says that there is no class Translate. How can I make this work?

WhittlesJr11:05:28

Try

(ns my-namespace
  (:import [com.google.cloud.translate Translate TranslateOptions Translation]
           [com.google.cloud.translate.Translate TranslateOption]))

penryu11:05:04

@vasco_mmf The (:import ...) form is only valid inside the (ns ...) macro.

penryu11:05:26

What @alex.joseph.whitt said.

Vasco Ferreira13:05:34

Thank you @alex.joseph.whitt, it worked for the first, but the second is giving an error java.lang.ClassNotFoundException: com.google.cloud.translate.Translate.TranslateOption This is my whole code:

(ns google-translation-java-interop.core
  (:gen-class)
  (:import [com.google.cloud.translate Translate TranslateOptions Translation]
           [com.google.cloud.translate.Translate TranslateOption]))

(def translate (. (. TranslateOptions getDefaultInstance) getService))

(def text-to-translate "Hello, World!")

(def translation
  (. translate translate
     text-to-translate
     (. sourceLanguage TranslateOption "en")
     (. targetLanguage TranslateOption "ru")))

(println (. translation getTranslatedText))

art13:05:06

@vasco_mmf (:import com.google.cloud.translate.Translate) then call Translate$TranslateOptions

art13:05:31

> Classname$NestedClassName

art13:05:56

idk its api tho

WhittlesJr13:05:52

Oh if it's a nested class then I think you'd want this instead:

(ns google-translation-java-interop.core
  (:gen-class)
  (:import [com.google.cloud.translate Translate Translate$TranslateOption TranslateOptions Translation]]))

art14:05:50

ah right, obviously the Translate$TranslateOption needs to be also imported

WhittlesJr14:05:59

By the way, has someone already done what you're working on? https://github.com/kolov/glingo

Vasco Ferreira14:05:13

I'm trying to do it by myself ๐Ÿ˜„

WhittlesJr14:05:58

Well practice is practice! (oh there seem to be several other libraries as well)

Yehonathan Sharvit14:05:28

In case you are struggling with learning Clojure, you can always get re-energised by remembering that โ€œJava is confusing while Clojure is simpleโ€ ๐Ÿ˜Ž. Of course, as Rich Hickey taught us โ€œSimple is not always easyโ€๐Ÿค” https://blog.klipse.tech/clojure/2019/05/10/java-is-confusing-clojure-is-simple.html

Vasco Ferreira14:05:52

I still have some trouble when thinking in a functional way. I did a simple quicksort algorithm in python and tried to do it in Clojure, it was mind opening. Python:

def quicksort(array):
    """Sort an array using the quick sort algorithm.
    Takes an array as argument.
    This implementation is recursive."""

    if len(array) <= 1:
        return array

    # Get the element in the center of the array
    middle_point = int(len(array) / 2)

    # Calculate the median of 3 values, the first,
    # the middle and the last elements of the array
    pivot = np.median([array[0], array[middle_point], array[len(array)-1]])

    # Filter array values by its relation with the pivot
    smaller = [x for x in array if x < pivot]
    equal = [x for x in array if x== pivot]
    larger = [x for x in array if x > pivot]

    return quicksort(smaller) + equal + quicksort(larger)
Clojure:
(defn quick-sort [[pivot & coll]]
  (when pivot
    (concat (quick-sort (filter #(< % pivot) coll))
            [pivot]
            (quick-sort (filter #(>= % pivot) coll)))))

Vasco Ferreira15:05:04

What am I doing wrong with this part? This is the error I'm getting: No matching method found: translate for class com.google.cloud.translate.TranslateImpl

(def translate (.. TranslateOptions (getDefaultInstance) getService))

(defn translate! [txt src-lang target-lang]
  (. translate translate
                    text-to-translate
                    (. Translate$TranslateOption sourceLanguage "en")
                    (. Translate$TranslateOption targetLanguage "ru")))
This is the java code:
Translation translation =
        translate.translate(
            text,
            TranslateOption.sourceLanguage("en"),
            TranslateOption.targetLanguage("ru"));

Marco Nicolodi15:05:48

Hey, I want to use this snapshot testing lib: https://github.com/juxt/snap#usage It says I should install with {:deps {juxt/snap {:git/url "" :sha "..."}}} but that's not the lein :dependencies keys. Do you know what kind of sintax is this?

lilactown15:05:36

@marcocontatopro that is deps.edn syntax

lilactown15:05:58

it doesnโ€™t look like theyโ€™ve published the library to a maven repository

Marco Nicolodi15:05:30

Yes i didnt found the package in the clojars website...

Marco Nicolodi15:05:13

With javascript's NPM i'm able to download a dependency from githab, is there a way to do that with lein?

lilactown15:05:31

I donโ€™t think leiningen supports git deps unfortunately

Marco Nicolodi15:05:19

Ok, then. I think i will download the source code for now. Thank you so much guys. You have been awesome on helping the beginners ๐Ÿ™‚

lilactown15:05:26

there are a couple plugins you could try: https://github.com/reifyhealth/lein-git-down

lilactown15:05:43

but yeah, simply downloading the source code is probably the easiest + simplest way

markmarkmark15:05:34

@vasco_mmf I'm not sure, but I'll bet that the translate method uses varargs in Java. Varargs aren't supported directly in Clojure so you have to explicitly wrap those parameters in an array.

kari17:05:05

I have bought practically all mainstream Clojure books and also some less known Clojure books. But there are two Clojure books I'm still looking for: 1. Effective Clojure Development - 100 Clojure Coding and REPL Tricks You Must Know. 2. Idiomatic Clojure - Learn to Use the Full Power of the Clojure Standard Library.

kari17:05:54

... the reason being: 1. I'm still learning (bit by bit, from various sources) how to use e.g. repl efficiently (e.g. "Do not write expressions in the repl editor - write expressions in a file and send the expressions for evaluation to the repl using a hotkey") 2. To know that you can do e.g. stuff like:

(->> items
     (map (juxt (comp :S :pgid) (comp :S :pgname)))
     (into {}))
instead of:
(reduce
  (fn
    [mymap item]
    (assoc mymap
      (-> item :pgid :S) (-> item :pgname :S)))
  {}
  items)
(there is nothing wrong with reduce, recur etc. but I'd like to learn other ways as well)

kari17:05:53

Where can I find these two books?

seancorfield17:05:30

I've never heard of them, so I'll be interested in the answer to that...

seancorfield17:05:15

@kari.marttila where did you hear about those books?

kari17:05:57

Sorry @seancorfield, just my Finnish black humor - meaning that I hope some Clojure guru would write those books for us mortal ones. ๐Ÿ™‚

kari17:05:23

I would immediately buy a copy. ๐Ÿ™‚

seancorfield17:05:32

:rolling_on_the_floor_laughing: Ah yes, I would like to read those too!

seancorfield17:05:57

I'd say the closest today is Clojure Cookbook for #1 and Clojure Applied for #2?

alexmiller17:05:58

the Clojure Cookbook was supposed to be kind of like 1

alexmiller17:05:21

there's the upcoming book from Renzo that might also be a candidate for 2

ballpark17:05:40

I love Clojure books, and love to read about how experts believe Clojure should be written. A few that I've found are Joy of Clojure, Elements of Clojure, and Clojure Applied

seancorfield17:05:53

@kari.marttila I'd highly recommend Eric Normand's REPL-Driven Development course for #1 as well.

kari17:05:37

Ok. Good to know. I make a order request to our corporation's horrific purchasing system immediately. And you can bet that I don't touch that system without a good reason.

seancorfield17:05:42

(I'd highly recommend this for everyone by the way!)

seancorfield17:05:55

And I just noticed Eric has added four more lessons that I haven't watched yet ๐Ÿ‘€ The guy is a machine!

kari17:05:36

Oh, god. It's a commercial course. And not a book you can order. I can already see the email discussion with our purchasing department that they tell me that they cannot order that Video course for reasons X, Y and Z. ๐Ÿ™‚

kari17:05:40

Is it so good a course that I'm going to skip our purchasing department and buy the course with my personal money? ๐Ÿ™‚ (Which I am very reluctant to use as all my three daughters know very well). ๐Ÿ™‚

seancorfield17:05:09

Yeah, I think it's good enough to pay personal money for. But that's mostly because I'm a big, big advocate of RDD and think everyone should be exposed to a productive workflow based on it.

kari17:05:07

Thanks. ๐Ÿ™‚

manutter5117:05:59

I believe he has some free/sample courses you could look at to help you decide.

kari17:05:39

Yihaa! That book is in the only online book store that they can order books without a major hassle: https://www.adlibris.com/fi/kirja/clojure-the-essential-reference-9781617293580 ๐Ÿ™‚

kari17:05:54

What a lucky day! ๐Ÿ™‚

dpsutton17:05:07

i believe there's an option to purchase and download, not a license per month

dpsutton17:05:31

he could also probably craft something to satisfy your purchasing department. he's a nice and reasonable fella

kari17:05:59

This is what I'm going to do next (though I already hate the idea). I'm going to start VPN session. I go to that horrific purchasing system. I fill all those weird fields, click next button add the urls as attachment, click next again, read the error message that I forgot to fill in some field and start the process again. Maybe in the 10th round I have made the order for that book and the functional tv yearly membership. Then I'm ready to have a lengthy email conversation with our purchase department why they should order the video course even though it is not in their list of preferred training providers . And all this because of my love to Clojure. ๐Ÿ™‚

seancorfield17:05:06

Good for you! I mostly buy books etc directly and sometimes I expense them (in theory, we can always expense training purchases at work easily, but I usually just forget).

seancorfield17:05:50

I also want the book forever and I'd feel guilty about work buying me books that I took away with me if I ever left ๐Ÿ™‚

kari17:05:45

Kari, do it now!

kari17:05:00

Ok, ok, I'm doing it.

kari17:05:41

All right. I'm in the system and this time I didn't have to change my password and try 20 different passwords before it accepted a new password. The first obstacle is over.

kari17:05:25

I guess the purchasing system is deliberately so horrific so that employees would not spend money for anything. ๐Ÿ™‚

kari17:05:09

Non-catalog request. Oh, god here we go.

kari18:05:07

Note to approver: "An essential Clojure book to teach me idiomatic ways to use Clojure." ๐Ÿ™‚

kari18:05:58

I knew this. They have changed the project numbers - again, and the system won't accept the previous project number for the purchase. I'm going to make seppuku now.

kari18:05:18

The easier one, the book is ordered. Let's see what happens this time. I had to put a note there: "NOTE: The purchasing project number X was not found in the system so I used number Y . If this is an issue I hope that you can move this order to the right project number. " I hate bureaucracy over anything.

kari18:05:21

Yearly subscription for http://functional.tv ordered. Let's see what happens.

kari18:05:19

BTW. I was working earlier in a new "start-up" department in our corporation. I actually could just send an email to our department secretary that I want books X, Y and Z and she ordered them from Amazon, can you believe that! Anyway. One day the secretary brought me a new book delivery. Some younger "front-end" developer was laughing beside me with his friends: "Is someone really reading books nowadays - everything is in the net!"

kari18:05:39

Yeah, right. I didn't bother to teach these guys some cognitive psychology. If someone has spent a year figuring out what is the best structure and format to deliver his/her ideas of some complex topic so that a reader can grasp those ideas reading a book of some 300 pages - I would say that it is worth to read the book.

Chris Swanson18:05:47

I don't think you'll be disappointed - I'd forgotten about Eric's courses (wasn't coding clojure for a while) , and I just signed back up. His stuff is great , very high quality.

kari18:05:23

Ok. Thanks for the recommendation. If the purchasing department approves the order (and they are able to make the order) I'm good. Otherwise I guess I have to buy the monthly subscription with my personal money and try to watch the most important stuff in a month.

kari18:05:59

And back to business. How do I learn to "see" what's the current status of my repl (I mean what namespaces have been loaded etc.). Since I remember that someone said earlier that he just keeps the repl running for days without the need of restarting it. I experience practically every day some weird things in my repl (namespace not found...) and I have to restart repl, refresh namespaces, restart Mount states etc. and magically everything works again.

holyjak18:05:30

hm, I never had such a need so cannot help. I dont know your workflow but I use Cursive (I expect most tooling to be similar), when working with a namespace I load-file it , which also (re)loads all namespaces needed. Hopefully Eric's REPL course will help you.

kari18:05:06

Ok. Hopefully I get to purchase the course. I also use Cursive and nowadays I write my experimental expressions in a scratch file (without a namespace and send the expressions from there for evaluation to repl).

holyjak18:05:27

regarsing some workflob best practices

kari18:05:11

Thanks. I need to read that ClojureVerse discussion carefully.

Marco Nicolodi19:05:17

Any high level resource for setting up ring-swagger?

seancorfield21:05:39

user=> (count (loaded-libs))
405
user=>
That REPL has been running for four days.

seancorfield21:05:29

(I can't remember why I restarted it late on Monday night... probably because I rebooted my Mac for a security update?)

lilactown22:05:25

it would be cool to easily get a list of loaded ns, last evalโ€™d form, etc.

noisesmith22:05:46

(all-ns) all defined namespaces - in my clj repl that's a superset of loaded-libs

lilactown22:05:49

the data for the first one is probably readily available. last evalโ€™d form is probably all in nrepl

seancorfield22:05:19

Yeah, (all-ns) will include namespaces created on the fly? The difference for me is

#{"flatland.ordered.map" "ws.domain.member.update" "flatland.ordered.set" "ws.domain.member.validation"}

noisesmith22:05:57

yeah, those flatland namespaces are in my difference too

noisesmith22:05:22

I wonder if deps.edn is using flatland.ordered to map to keep those dependency hash-maps straight

alexmiller22:05:51

Itโ€™s not

noisesmith22:05:09

maybe there's something about how those deps load then...

alexmiller22:05:23

The codes all on the add-lib branch if you want to look at it

seancorfield22:05:17

For me, flatland is coming in via lacinia @noisesmith

seancorfield22:05:07

And I'm going to guess that flatland.ordered creates the .map and .set namespaces without actually requiring them from disk?

noisesmith22:05:19

that must be it

seancorfield22:05:19

FWIW, in our code, ws.domain.member specifically calls create-ns to provide aliases to specs and keywords that act "as-if" they came from the .update and .validation namespaces.

seancorfield22:05:39

Ah, ws.profile.field does that

(alias 'mu (create-ns 'ws.domain.member.update))
(alias 'mv (create-ns 'ws.domain.member.validation))