Fork me on GitHub
#beginners
<
2021-02-26
>
rafalw02:02:40

Hi, I'm reading https://github.com/linpengcheng/PurefunctionPipelineDataflow/blob/master/doc/relational_model_on_hashmap.md and I wonder what this "empty" commas at the end mean

(defn join [db main_table join_table join_col]
  (let [f #(let [x (-> db main_table %2)]
              (->> x
		   join_col
		   (get (db join_table) ,)
		   (merge x ,)
		   (assoc %1 %2 ,)))]
  (->> db
       main_table  
       keys
       (reduce f {} ,)
       doall)))  
any hints ? never saw anything like this ...

hiredman02:02:50

Commas in clojure are whitespace, the reader ignores them

hiredman02:02:44

So they don't mean anything to clojure, but some people do that kind of thing to mark where threading macros will insert their arguments

👍 3
hiredman02:02:18

I don't much care for it

rafalw02:02:52

thanks, I understan now ....

Adrian Imanuel02:02:58

hi i tried to understand this https://clojuredocs.org/clojure.core/read-line in my doom-emacs, it'll prompt an input, but once i input it in my repl, it stuck, it doesn't return like that. how to do that in emacs?

(do (print "What's your name? ") 
           (flush) 
           (read-line))
What's your name? Clojure
"Clojure"
i have to ctrl+c twice and result in error
Execution error (InterruptedException) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject/await (AbstractQueuedSynchronizer.java:1627).
null

dpsutton03:02:47

emacs uses nrepl so things are a bit more complicated. when you attempt this, you'll notice in the bottom of your emacs window a prompt that looks like this:

Adrian Imanuel03:02:49

@U11BV7MTK I want to thank you from deepest of my soul!

😭 3
dpsutton03:02:07

why you're quite welcome 🙂

Adrian Imanuel03:02:36

been looking for an answer since about 3 wks ago, now it comes to light. I'm so stupid

dpsutton03:02:31

it makes sense to accept repl input from the repl. its kind of a quirk that it works this way. and the input request is tiny and out of site

Adrian Imanuel03:02:32

couldn't be more agree than this

Adrian Imanuel05:02:11

@U11EL3P9U thank you so much for helping me. https://github.com/dharrigan/google-apis-example/tree/master/src/dharrigan it's because of i couldn't operate the emacs that well, but I got the concept of oauth2 because of you. still it's really simple, but I just found the answer today omg... lol :rolling_on_the_floor_laughing:.. again, thanks a lot!!

dharrigan07:02:17

You're most welcome 🙂

dharrigan07:02:41

Keep on 'learning! 🙂

dpsutton03:02:00

emacs is wanting you to type there to send the input rather than in the repl buffer

3
pinealan07:02:59

are there clojure libraries for hmac?

pinealan07:02:56

thanks! I’ll try them out

Ryan Boldi08:02:45

Hey guys! I just started trying to use incanter to draw some plots, but whenever I do:

(ns main
  (:use [incanter core charts stats datasets]))
clj-kondo yells at me for using :use. Is there a succinct way to achieve the same thing using :refer :all? (p.s. it also underlines all my incanter functions like histogram due to unresolved symbol even though the code works)

borkdude08:02:27

@ryan.boldi123 clj-kondo yells at you because it has no way of knowing where some of the symbols in your code are coming from and therefore it discourages :use and :refer :all for that matter.

borkdude08:02:25

As a human I often have the same problem as clj-kondo, that's why I also don't use :use myself, I find that the code becomes more confusing. Just use :require + :as or :refer

Ryan Boldi08:02:36

@borkdudeSo would I need to always use fully qualified names whenever I call incanter functions? Something like incanter.core/view ?

borkdude08:02:15

@ryan.boldi123 No: (ns main (:require [incanter.core :refer [view]]))

borkdude08:02:00

Or: (ns main (:require [incanter.core :as i])) and then write (i/view ...)

Ryan Boldi08:02:09

@borkdude So I would need to write 4 require lines, one for core, charts stats and datasets?

borkdude08:02:28

yeah, well you don't have to, you can use nested libspecs, but that's another story ;)

😅 3
Ryan Boldi08:02:57

@borkdude Thank you very much!

borkdude08:02:31

(ns main (:require [incanter [core :refer [view]] [charts :refer [foo]]]))
This works, but this syntax has gone a bit out of fashion in favor of just writing the namespace names in full

😮 3
Ryan Boldi08:02:43

This is very helpful. I don't mind sticking to doing 4 separate requires for the sake of readability.

dharrigan08:02:21

Oh, I just answered that also in discord

solf09:02:13

What discord? I tried googling and found a couple in years-old reddit comments, is there a "recommended" one?

dharrigan11:02:01

It's called Clojurians

dharrigan11:02:03

Discord doesn't make it easy to find out the server URL

dharrigan11:02:19

Try this one :

dharrigan11:02:25

It was on Invite Someone

dharrigan11:02:35

you're most welcome! 🙂

FiVo12:02:24

Does seq (and thereby keys and vals ) give some guarantee with respect to ordering for maps with identical keys ?

FiVo12:02:02

For example

(defn gen []
  (->> (for [i (range 1000)]
         [i (rand-int 1000)])
       (into {})))
does it always hold that
(= (keys (gen)) (keys (gen)))

ghadi13:02:11

no, it doesn't hold across different maps @finn.volkel

FiVo13:02:31

@ghadi so the guanrantee is not given, but the implementation always yields the same order or the implemenation does not always yield the same order?

andy.fingerhut13:02:03

If you add equal keys in same order to two maps the implementation today will have same order

andy.fingerhut13:02:12

If you add same keys in different orders to two maps, their order of seq, keys, and Vals can differ

FiVo13:02:54

thanks, that makes sense

adam-james13:02:25

Is there an appropriate way to 'pull in' functions from different namespaces into a namespace such that the symbols become accessible in that ns from other namespaces? That seems unclear... what I mean is to be able to do something like this:

(ns svg-clj.main
  (:require [clojure.string :as st]
            [svg-clj.utils :as utils]
            [svg-clj.specs :as specs]
            [svg-clj.transforms :as transforms :refer [translate rotate scale centroid bounds]]
            [svg-clj.path :as path]))

(some-kind-of-pull translate) ;; something to make the symbols accessible, incl. docstring and args
(some-kind-of-pull rotate) 
...
Then, a user would use svg-clj as follows:
(ns user.drawing
  (:require [svg-clj.main :refer [circle translate rotate]])) ;; user doesn't need to know about svg-clj.transforms

walterl14:02:00

My guess: (intern *ns* 'translate translate), etc.

adam-james15:02:53

Hmm... tried that and it almost works. I do have the symbols accessible when :requiring main, but I don't see the argslist show up in my editor (my minibuffer in emacs usually shows the args as I type a fn)

seancorfield18:02:56

@U01LR7M2B7A That's because the metadata is lost on that intern -- but you can get the metadata from the original var and add it to the new interned var. Something like this: https://github.com/clojure-expectations/clojure-test/blob/develop/src/expectations/clojure/test.cljc#L538-L546

seancorfield18:02:58

I'm using update to append the line about "Imported from..." but you could just do (insert *ns* 'translate (with-meta translate (meta #'translate))) I think. #' gets the var behind the function translate and you need that for the metadata.

adam-james18:02:40

I was just messing around with meta! Your linked code example gave me the hint I needed. I did not know about 'resolve' and was struggling to attach meta to the var as opposed to the symbol. Thanks for the help!

oly15:02:53

https://clojurescript.org/reference/repl-options where can I put these ? I want to set a static path to resources/public so when i jack in I can ajax files tried in build.edn but either thats wrong or I am doing something else wrong 😕

nozd18:02:28

is there a better way to write this?

(let [m {:foo "ab" :bar "cd"}
        bar (list (:bar m))
        foo (list (:foo m))]
    (concat bar foo))
=> ("cd" "ab")

nozd18:02:33

I basically want to take two keys from a map and make a list out of the values

sb18:02:32

If I understand good

seancorfield18:02:51

@UJ5N28CL8 Is there a reason not to just use [(:bar m) (:foo m)] rather than creating a singleton list for each item and then gluing them back together?

nozd18:02:21

(let [m {:foo "ab" :bar "cd"}
      {bar :bar foo :foo} m]
  (list bar foo))

seancorfield18:02:53

And as sb says, destructuring can make this cleaner:

(let [{:keys [bar foo]} {:foo "ab" :bar "cd"}]
  [bar foo])

👍 3
nozd18:02:37

cool, this is much more idiomatic, thanks

seancorfield18:02:21

This form of destructuring is rarely used, unless you want to rename the keys to something else: {bar :bar foo :foo}, i.e. {one :bar two :foo} -- so one is bound to (:bar m) and two is bound to (:foo m)

seancorfield18:02:59

(sometimes that is absolutely necessary, so it's good to know about, as well as the more common :keys destructuring)

nozd18:02:53

in my use case, :keys destructuring would work, there is no need to rename the keys

borkdude19:02:30

user=> ((juxt :bar :foo) {:foo "ab" :bar "cd"})
["cd" "ab"]

👀 3
seancorfield19:02:34

Another good use for juxt 🙂

kimim00:02:52

How about:

(-> {:foo "ab" :bar "cd"}
    vals
    reverse)

seancorfield00:02:48

Hash maps are inherently unordered. You can't rely on the ordering or the reverse ordering.

seancorfield01:02:18

And I think the assumption is that there are many other keys in there, but @UJ5N28CL8 only wants two of them.

kimim01:02:33

Yes. map is unordered. You are right.

nozd19:02:20

juxt is awesome, and yes the map contains more than 2 keys

borkdude19:02:20

Just for the record, juxt works with any (positive) amount of keywords (or other fns)