Fork me on GitHub
#beginners
<
2018-08-14
>
stardiviner10:08:38

How can I check out all namespaces (which is not required yet) from a library dependency just like function (apropos #"regexp match") ?

stardiviner10:08:16

I know CIDER can get those completions, so there are must a way to get those namespaces.

stardiviner10:08:23

Don't know how it is implemented.

stardiviner12:08:14

Is there someone using Clojure GitHub API library tentacles? How to know that my authentication is verified? (I don't know what auth for my personal access token, OAuth or OAuth2?)

zlrth12:08:17

I'm brainfarting over this. I have some duplicate hashmaps that i'd like to remove by id, so I'd like to produce a list of ids:

(->> '({:id 123 :val "val"}{:id 124 :val "val"} {:id 125 :val "otherval"})
                        (group-by :val)
                        (vals)
                        #_(map (fn [lm] (reduce (comp =  #(apply  dissoc % :id)) {} lm))))
;; want to return: '(124), because the removing the map that has :id 124 will make a list of unique maps.

zlrth12:08:44

oh and in the problem i'm facing, there are potentially other kvs in the map, and i only want to return the map if the hashmaps = each other

mfikes12:08:47

distinct-by is a common function used outside of core

mfikes12:08:24

That might be a bit of the opposite of what you want @mfm but it would work like this

cljs.user=> (distinct-by :val '({:id 123 :val "val"}{:id 124 :val "val"} {:id 125 :val "otherval"}))
({:id 123, :val "val"} {:id 125, :val "otherval"})

zlrth12:08:42

thanks so far @mfikes! i'll see if i can modify distinct-by or use a tricky argument...

mfikes12:08:26

I think distinct-by is probaby my 2nd most desired fn that is not in core. (With the 1st being a function or functions to map over maps, like mapping over the values to increment them.)

zlrth12:08:37

i think this is doing more of what i want:

(distinct-by (comp set #(dissoc % :id)) '({:id 123 :val "val"}{:id 124 :val "val"} {:id 125 :val "otherval"}))
=> ({:id 123, :val "val"} {:id 125, :val "otherval"})
where i now can: ignore the thing that'll always be unique (the :id), and compare against all other values in the set

zlrth12:08:12

and to get the list of ids (the original desideratum), i do something like clojure.set/difference

zlrth12:08:35

on the :id's produced by the above function application

zlrth12:08:45

thanks! distinct-by is great.

👍 4
cjmurphy16:08:01

If a function has this signature: [url & {:keys [a b c]}], then doesn't that mean it can be called with one or more arguments? Just has to be at least one.

cjmurphy16:08:21

Actually I think it would have to be an odd number, but probably that would only be worked out at runtime??

schmee16:08:26

those are optional keyword args, so you can call it like this: (foo some-url :a some-value :c some-other-value)

cjmurphy16:08:44

Trouble is I'm getting an error message saying 3 args being passed is no good. In fact only one args means no error messages.

schmee16:08:16

how are you calling it?

cjmurphy16:08:37

(wn/make-websocket-networking "/chsk" :push-handler (fn [m] (when @app (push-received @app m))))

cjmurphy16:08:07

That is 3 arguments, s/be correct.

cjmurphy16:08:39

Wrong number of args (3) passed to fulcro.websockets/make-websocket-networking

cjmurphy16:08:50

I'm just checking my sanity here.

cjmurphy16:08:10

Surprising error message to me.

cjmurphy16:08:47

I get the same error message with 2 args, but it passes with one arg.

schmee16:08:12

it’s keyword args all the way

cjmurphy17:08:06

That would be the latest source. Cursive is showing me old source. And shadow-cljs using what is really being used which would be the latest I imagine. Actually I'm confused.

cjmurphy17:08:48

Either way its a wrong error message isn't it?

noisesmith17:08:54

your project manager can show you the version you are using; lein deps :tree for example

noisesmith17:08:44

if all args are keyword args, any odd argument count is invalid, you'd get "no value supplied for key"

noisesmith17:08:11

I wouldn't expect shadow-cljs to pin you to the latest version of a dep

cjmurphy17:08:49

Fulcro is pretty much the latest, verified using lein deps :tree :- "2.6.0-RC5"

cjmurphy17:08:13

So I'll change to RC6...

noisesmith17:08:37

also, if you use lein cp you can see the actual resource being used to load the code, and look at the source - but cursive definitely automates that

thheller17:08:34

@cjmurphy that fn only takes one argument? a map?

schmee17:08:10

dang, you’re right, no & in sight

schmee17:08:22

sorry for missing that

cjmurphy17:08:59

Not in the source that Cursive is showing me.

noisesmith17:08:47

cursive should be using your classpath, so I'd find it unlikely it would get the source wrong

noisesmith17:08:04

(of course bugs will be bugs, but that would be a very weird one)

cjmurphy17:08:52

Well I can see 'url' there (first arg, before the &), so the unlikely seems to be happening no??

noisesmith17:08:15

perhaps your deps changed since cursive started and it has a stale view of your deps?

cjmurphy17:08:19

Time to clean the cache perhaps...

noisesmith17:08:32

or cursive and your process are using different classpaths...

cjmurphy17:08:31

I'm doing an "Invalidate caches and restart".

thheller17:08:24

@cjmurphy you can conrol+click the function call. check which file it takes you to.

cjmurphy17:08:47

That is what I do to look at the source thru Cursive I think. I go control-B.

cjmurphy17:08:00

So that fixed Cursive. The call is now underlined as red and tells me about incorrect arity, just as shadow does. Thanks all.

placeboza17:08:53

FYI regarding the mount vs component discussion yesterday, here's Dan Boykis' insight into why mount is better: http://danboykis.com/?p=2263

placeboza17:08:19

In short - it's his opinion on what is beautiful and structurally correct in Clojure

hiredman17:08:19

the idea that mutable globals that cannot be composed together in anyway is beautiful and structurally correct is laughable

hiredman17:08:29

the whole thing is basically dynamic scoping vs static scoping, which was a whole argument back in the day, and dynamic scoping can be nice for some stuff, but static scoping is the correct default

placeboza18:08:30

Agree with what you say about mutable globals and lack of composition. Was just pasting it here, as somebody mentioned that they couldn't understand what the attraction was (for mount)

Nick Cabral18:08:04

Does deref'ing a promise tie up an OS thread, or is the calling thread parked, similar to taking from a core.async channel?

noisesmith18:08:20

promises have nothing to do with threading machinery, your thread blocks until some other thread delivers

Nick Cabral19:08:33

Yeah perhaps I didn't phrase that very well with respect to threading. But it sounds like the answer is "yes, dereferencing a promise does block and tie up CPU resources, unlike clojure's channels, in which the calling thread is parked (making those compute resources available for other work) until a value is delivered"?

noisesmith19:08:06

it blocks a thread, but it doesn't busy wait or tie up CPU

Nick Cabral19:08:04

Perfect, that's what I wanted to find out. Thanks! After looking at the java API again, I think my question could have been better written as "When a promise is dereferenced, is the calling thread state set to 'wait' or 'park'?" Thoughts?

noisesmith19:08:48

That works. There is no "park" state for a thread, you need some abstraction over threads to provide that (aka a coroutine, green-thread, callback-chaining... it's called by various names)

noisesmith19:08:57

the advantage is that you can switch a green-thread context without an actual thread context switch, which means you have more control and you don't pay the price of OS level thread machinery

Nick Cabral19:08:16

Awesome, thanks again.

noisesmith18:08:38

that said, on most operating systems threads are relatively cheap

noisesmith18:08:24

(promises have no more to do with threading machinery than anything else that blocks a thread that is)

wekempf19:08:00

@jasonpepas There's a project named MAL (Make a LISP) on github (https://github.com/kanaka/mal) that's implemented a Clojure Inspired LISP interpreter in 73 different languages. One of them is Swift. There's a link in the readme to another project, MALC, that provides an LLVM compiler for MAL. Between the two, you'd have a good starting point for creating a ClojureSwift.

👍 4
blance20:08:59

If I have a function that takes a map as argument, then how do I make sure I don't accidentally retrieve the wrong key when using such map? say the function is supposed to be passed in a {:a 1}, and I somehow think it wants a {:b 1}, then I proceed to use :b in the body of the function, and also when writing test for the function. I won't discover it until I deploy the service to qa environment and do a end to end integration test.

justinlee20:08:42

@blance I think that’s just a general question of program correctness (?) Theres nothing unique to using a map. Same issue with passing a string to a function that expects a number, for instance.

blance20:08:30

so not really testable with dynamic typed language i guess?

johnj20:08:05

you can use spec

johnj20:08:54

or do the validation yourself

johnj20:08:09

ex: check for the correct key

blance20:08:56

spec won't work in compile time though, and the function is not pure (upload file to s3), so I would need to write bunch of mock in order to exercise the path:thinking_face:

blance20:08:24

i guess this is probably not clojure specific problem..

dpsutton20:08:43

have you ever worked in python or javascript?

johnj20:08:49

checking for such concrete stuff might not be a good idea anyway

justinlee20:08:42

it’s a big topic. I’d say that there are moments where may need to program defensively by doing run-time validation. Another thing you’ll hear people say is that if you need to mock in order to test, you’re doing it wrong 🙂

justinlee20:08:20

I find that advice not that useful when what you are doing is primarily i/o, though, but it is a good thing to keep in mind

blance20:08:39

only played with python and javascript, no serious work.

blance20:08:59

i was hoping to test this with integration test to verify the whole system work

blance20:08:13

but my teammate ask me to mock and write unit tests..

justinlee20:08:28

there isn’t anything wrong with integration testing

blance20:08:54

which I feel not really a good idea, but can't think of a valid argument.. as I guess i'm suppose to always write unit test for any code?

blance20:08:16

he's reasoning is to fail fast and catch error earlier:thinking_face:

justinlee20:08:01

well the unit test should make sure that your function works as expected for all expected inputs. so the unit test just need to make sure that your function that accepts a map does the right thing. the unit test can’t possibly test whether other functions call that function properly

blance20:08:06

thanks! i'll see if i can convince him using that argument 🙂

noisesmith21:08:55

another approach here is to spec the function and exercise the function and the caller, if they use the spec, the only thing left is to make sure the spec is correct

blance21:08:05

I could gave typo in spec as well :( and I would need to exercise all path calling that function which would require lots of mocking I guess

noisesmith21:08:53

"exercise" has a specific meaning with spec- inputs are generated that match the spec, and your code is executed with each one

noisesmith21:08:07

the idea is that instead of having to verify that all your functions are doing the right thing, you make them use the same spec, you verify the specs carefully, and the spec is used to ensure each one behaves as expected (this means you don't have to write your own tests for conformance - the inputs are generated for you)

noisesmith21:08:26

this isn't the only way to do things, but it's how we do things at my day job and it does work

blance21:08:57

spec can't be used to verify side effects can it?

blance21:08:24

i really like the idea of generative testing, but most of our code are doing side effects 😞

noisesmith21:08:20

yeah, to be really effective, it requires code that isolates side effects from data transformations (which is often a good thing btw, and clojure offers multiple tools to facilitate that pattern)

noisesmith21:08:03

but if you just have a bunch of state updating functions, by definition you can only use integration tests, generative tests and unit tests aren't helpful

blance21:08:45

thanks for the suggestion, that makes a lot of sense. I'll try to convince my teammate:)

markomafs22:08:15

Guys i'm having some warnings on eastwood lint on that fn

(defn count-merchant-transactions
  "Count Merchant Last Transactions for a Merchant"
  [^Transaction transaction, lastTransactions]
  (let
    [
     merchants (filter (fn [x] use transaction (= (:merchant x) (:merchant transaction))) lastTransactions)
     ]
    (count merchants)
    ))

Eastwood warnings:
core.clj:40:32: unused-ret-vals: Var value is discarded: use
core.clj:40:36: unused-ret-vals: Local value is discarded: transaction
Am I doing it wrong? how can I improve this fn or the entirely function?

hiredman22:08:01

use transaction

hiredman22:08:13

that isn't doing anything

hiredman22:08:36

which is what eastwood is complaining about

markomafs22:08:58

(:merchant transaction) i'm not using it?

hiredman22:08:08

in the function

hiredman22:08:18

before (= (:merchant x) ...)

hiredman22:08:04

you have use and transaction, just sitting there, they aren't part of the return value of the function and they aren't used in an expression that might have side effects

markomafs22:08:05

if i remove use transaction, is it still works?

markomafs22:08:01

dafuq not even tried. it works, sorry my OO mindset

hiredman22:08:20

it isn't clear what the use transaction is intended to accomplish, but as is it definitely isn't doing anything, which is why eastwood complained about it

markomafs22:08:03

i was thinking on pass transaction value throw (fn) , but it already are in the context

sundarj23:08:37

@UC7MQBH6H yeah, you never need to use names from outer scopes in Clojure, like you do in PHP. you just reference them