Fork me on GitHub
#beginners
<
2016-09-17
>
josh_tackett01:09:04

How do you assoc a key at the end of a map?

snoonan01:09:18

maps don't have an order, so what end are you asking?

snoonan01:09:08

(assoc m key value)

akiva02:09:49

@snoonan is correct. If you want to do ordering or filtering of a map you can use sorted-map or keys.

plexus05:09:09

Note that sorted map will keep the entries sorted by key, it does not mean map that keeps the order entries were inserted. If you want to keep that kind of order just use a vector of pairs

eslachance12:09:40

:thinking_face: my repl was working fine yesterday but now it won't load, apparently because of SLF4J failing to load... I have no idea what that is. didn't add any new dependencies.

eslachance12:09:20

It was... code? something in my code was causing it to fail... commented out everything except static definitions and now it works. šŸ˜’

plexus12:09:20

sorry to hear... maybe try commenting out bit by bit so try to narrow it down

rodweb13:09:12

Hello guys! How do you usually mock an external API when unit testing?

plexus13:09:03

by external API do you mean a third party library, or a remote service?

rodweb13:09:20

a remote service

plexus13:09:46

goooood question. The answer, as always, it depends šŸ™‚

plexus13:09:14

if you're ok with just stubbing, i.e. replacing the call with a canned response, than with-bindings is probably enough. You probably have a wrapper function that does the actual API call, so redefine that in your test

plexus13:09:56

(deftest my-test
  (with-redefs [do-api-call (constantly {,,, some canned response ,,,})]
     (is (= ,,, ))
     ))

plexus13:09:00

if you really want mocking, i.e. being able to assert how many requests are made, with which args, etc, then something like memocks might help https://github.com/siilisolutions-pl/memocks

rodweb13:09:47

thanks! I think with-redefs will do it for now šŸ™‚

rodweb13:09:16

but Iā€™ll take a look at memocks anyway

vjunloc14:09:56

How do i read documentation in figwheel repl ?

vjunloc14:09:52

doing

(doc map)
throws error

vjunloc14:09:06

----  Compiler Warning on   <cljs form>   line:1  column:2  ----

  Use of undeclared Var cljs.user/doc

  1  (doc map)
      ^--- 

----  Compiler Warning  ----
#object[TypeError TypeError: Cannot read property 'call' of undefined]
nil

plexus15:09:58

these helpers are in the cljs.repl namespace

plexus15:09:08

(cljs.repl/doc map)

plexus15:09:55

the clojure repl includes these in the user namespace, I would expect ClojureScript repls to do the same for cljs.user, but apparently not

plexus15:09:21

or at least not for figwheel, seems to work fine in Planck

petterik15:09:04

@filipecabaco (into [] (remove #(rem? % step)) acc) instead of (doall (remove #(rem? % step) acc)) brings the time down another 50% for me

plexus15:09:04

interesting! how about (vec (remove ,,,))?

filipecabaco15:09:09

Interesting...

mfikes15:09:49

FWIW, Planckā€™s doc macro is referred into cljs.user iff you are starting a REPL by doing this at startup (require '[planck.repl :refer-macros [apropos dir find-doc doc source pst]])

plexus15:09:57

@mfikes but just running planck does that, right? at least works for me on Linux...

mfikes15:09:57

@plexus Yes. But, for example, if you ā€œrunā€ a cljs file using Planck (so that it essentially doesnā€™t go into interactive REPL ā€œmodeā€), this is skipped.

plexus15:09:27

ah right, makes sense. Thanks for clarifying.

plexus15:09:52

any idea why it's not working in Figwheel? seems odd... maybe it's a regression

mfikes15:09:03

@plexus Right. (doc map) works for me in Figwheel at the intitial cljs.user prompt

mfikes15:09:32

Looks like Iā€™m on Figwheel 0.5.4-7 based on what it just pulled from Clojars

plexus15:09:14

I'm using figwheel over nREPL, maybe that's the problem, let me compare with a regular lein figwheel

plexus15:09:00

hmmm nevermind, works just fine after a restart, both on a terminal and over nREPL. Not sure what I was doing before.

plexus15:09:17

@vjunloc as long as you're in the cljs.user namespace it should work. If it doesn't then something is wrong and you'll have to tell us some more about your setup

vjunloc15:09:44

Oh, i think i created a new namespace in the repl

vjunloc15:09:00

works fine after restart, thanks for looking into this @plexus

vjunloc15:09:31

Can you please tell me how to enable parens matching in figwheel ?

filipecabaco16:09:57

@petterik any idea why it improves performance so much?

plexus16:09:13

@vjunloc what do you mean by "parens matching"?

val_waeselynck16:09:30

@filipecabaco to understand the performance improvements, check out transients and transducers

val_waeselynck16:09:03

definitely advanced topics you needn't care about as a beginner šŸ™‚

filipecabaco16:09:15

Will check, get amazed and then go back to basics šŸ˜›

petterik16:09:11

@filipecabaco it might have to do with chunked sequences, but I'm not sure. If you look at (source filter) (which remove uses), you'll see that there's a special case for (chunked-seq? (seq coll)). The coll in your case is what's returned from take which is not a chunked seq: (chunked-seq? (seq (take 1 [1]))) => false In the sieve using (into [] (remove ...)), we're using the transducer api instead of the sequence api, avoiding seq's and chunked-seq's all together (for lack of a better explanation).

petterik16:09:16

@filipecabaco Also, this is just a guess. I leave it to you to find out if this is the case šŸ™‚

vjunloc16:09:50

@plexus I am not sure of the exact term, but basically as you type in the repl and you provide a closing parenthesis ")" the repl sort of matches it with it's corresponding opening parenthesis

plexus16:09:51

I don't think any terminal based repl will give you that. If you run it inside emacs you can use show-parens-mode (I think that's what it's called)

vjunloc16:09:21

but it works fine in my boot-cljs setup, wondering why it doesn't for figwheel

vjunloc16:09:22

And my boot-cljs setup is nothing fancy, i simply followed this guide - https://github.com/magomimmo/modern-cljs/blob/master/doc/second-edition/tutorial-01.md

filipecabaco16:09:07

@petterik thanks for the explanation and yep will check the way! That's half the fun :)

vjunloc17:09:50

I am trying to require clojure.set like this -

(require '[clojure.set :as cs]) 

vjunloc17:09:00

in my repl

vjunloc17:09:41

but running the union function throws an error -

(cs/union #{1 2}  #{3 4}) 

vjunloc17:09:06

error -

#object[TypeError TypeError: Cannot read property 'union' of undefined]

vjunloc17:09:23

so basically import is failing, not sure why

akiva17:09:09

Might want to just reboot your REPL.

willyfrog17:09:29

Iā€™ve tested both in lein repl, and planck, and seems to work ok

vjunloc17:09:26

Okay, works in figwheel repl, but not on boot-cljs

vjunloc17:09:50

even after restarts

vjunloc17:09:52

I wish figwheel had parens matching

surreal.analysis19:09:48

@vjunloc Iā€™d encourage you to set up https://github.com/bhauman/lein-figwheel/wiki/Using-the-Figwheel-REPL-within-NRepl, and use your editor of choice to interact with it. REPL Driven Development is great, and setting up your environment like this will definitely pay off in the end

pawel.kapala22:09:16

Iā€™m a bit confused with recurā€™s description at https://clojuredocs.org/clojure.core/recur, and I read, that clojure wonā€™t do proper tail call optimisation unless I explicitly use recur, is that correct? Does that mean, I have to use recur, to do arbitrary recursion (self function) calls in clojure?

pawel.kapala22:09:31

Naive, classic factorial example I came up with wonā€™t do TCO, right:

(defn factorial[n] (if (= n 0) 1 (* n (factorial (dec n)))))
as opposed to the example presented at recur docs:
(def factorial
  (fn [n]
    (loop [cnt n acc 1]
       (if (zero? cnt)
            acc
          (recur (dec cnt) (* acc cnt))
; in loop cnt will take the value (dec cnt)
; and acc will take the value (* acc cnt)
))))

pawel.kapala22:09:53

Yeah I shouldā€™ve followed this: http://clojure.org/reference/special_forms, thereā€™s more to it:

pawel.kapala22:09:09

"Note that recur is the only non-stack-consuming looping construct in Clojure. There is no tail-call optimization and the use of self-calls for looping of unknown bounds is discouraged. recur is functional and its use in tail-position is verified by the compiler.ā€œ

pawel.kapala22:09:17

I think this answers my question

seancorfield23:09:45

Correct, direct recursion does not use TCO. recur essentially replaces the call with a loop under the hood, rebinding the arguments.

seancorfield23:09:57

loop / recur is a similar construct.

seancorfield23:09:40

Note that Clojure only lets you use recur where it can convert it to a loop, i.e., only in a valid tail recursive position. That means that if recur is legal, you are guaranteed you get the optimization. This makes things much more predictable than languages that attempt to do automatic TCO because you can see from the code directly whether or not you have a recursive call or an optimized-to-loop call ā€” and you canā€™t "force" TCO where it isnā€™t possible.