Fork me on GitHub
#beginners
<
2017-05-10
>
noisesmith01:05:30

the cond needs to be inside the () of the let form

noisesmith01:05:33

right now it isn't

noisesmith01:05:42

so it doesn't see the x that let binds

noisesmith01:05:21

it's seeing the old x (if it can find one at all)

vitruvia01:05:37

I don't understand why it needs to be inside the let if it doesn't modify what I assign x to

vitruvia01:05:49

the assign to x is just the filter part

noisesmith01:05:01

nothing can see x if it isn't inside the parens of the let

noisesmith01:05:11

that's why let exists, to create a local scope

john01:05:29

And you should probably indent the (:require form hanging off that ns form. With the atom editor I'm using, for instance, it would automagically drop the :require to the top level and wrap a closing parens around (ns bob.

john01:05:23

Though some might call that a deficiency of my editor.

vitruvia01:05:49

thanks for the heads up

noisesmith01:05:58

@john there was a tweedle-dee / tweedle-dum situation on my team where one person would indent things totally wrong, and the other used an editor that auto-indented, and end up automatically re-parenthesizing in ways that broke the code

noisesmith01:05:13

like working in a madhouse I swear

john01:05:47

it's a broken "feature" of the parinfer version in the ide I'm using, for sure. Linting my code is one thing. Changing how it works is another.

john01:05:38

speaking of work, is there a room in here specifically for job postings and requests? or do people ask around in random rooms?

john01:05:53

nevermind. #jobs it is

gonewest81802:05:06

@matan @ghadi if you use weavejester/environ you can in fact put your configuration in a map, either in your project.clj or in profiles.clj and the loading and parsing of that map is handled for you. If you keep profiles.clj in your .gitignore then you can avoid accidentally checking in the maps, and in deployment use environment variables to configure instead. This is a plus if you’re a “12 Factor App” shop. I think environ is well worth a look. In addition, I wrote a library on top of environ called “defcon” which adds a few more conveniences that I happen to prefer, like ability to cast the values to a type (i.e. integer, float, bool), the ability to supply default values, and the ability to declare mandatory config variables that must be set.

felipe-campos13:05:44

tried

(deref (future (Thread/sleep 1000) 0) 990 5)
on the REPL and got 0. could anyone explain me why?

Drew Verlee13:05:47

This might seem like an odd question but when is it appropriate to use a multimethod over a conditional branch like if/else? It seems possible you could always dispatch to a type. The big trade offs seem to be: if/else branch conditions can be changed at run time. Multimethods are organize the code in a better mental model.

ghadi14:05:27

@felipe-campos timing precisions are not guaranteed

ghadi14:05:04

in this case you're getting the result of the future rather than the timeout value.

ghadi14:05:29

In core.async (not relevant here) the timer granularity is explicitly coalesced to 10ms intervals

vitruvia15:05:18

Why does using (doc replace) throw an error in my IDE?

vitruvia15:05:35

The compiler says it is unable to resolve the symbol

curlyfry15:05:19

@vitruvia You need to require clojure.repl to use doc

Alex Miller (Clojure team)15:05:27

Most repls automatically refer it in the user namespace

Alex Miller (Clojure team)15:05:41

But if you switch to something else, it's not available

ejemba16:05:25

what exactly is a .edn file ?

ghadi16:05:08

@ejemba kind of a limited subset of clojure oriented towards data https://github.com/edn-format/edn

ejemba16:05:30

@ghadi « the json of clojure world »?

ghadi16:05:45

sort of yeah

ejemba16:05:11

thank you ghadi

ghadi16:05:54

if you want a data interchange format that has EDN's semantics but JSON's reach, look at Transit. Also designed by Rich Hickey..

ghadi16:05:25

Transit has readers and writers for most languages

ghadi16:05:54

It's a lot faster than EDN (and not limited to clojure at all)

vitruvia16:05:55

How can I use replace to change a character on a string for different characters? Like if I want to replace t in "test" by a but the e by i and get "aisa"?

verma16:05:28

what is everyone using to write clojurescript tests? .. something akin to the figwheel experience would be great.

manutter5117:05:32

@vitruvia You might want to take advantage of clojure’s list-processing tools for that instead, for example (defn tr [s] (apply str (map #(condp = % \t \a, \e \i %) s)))

vitruvia17:05:56

I don't quite understand what your solution does though

manutter5117:05:00

“For each character in the string, if it’s a t replace it with a, if it’s an e replace it with i, otherwise use the original character.”

manutter5117:05:18

As a one liner it’s less readable, just a sec

manutter5117:05:03

When you use map on a string, it iterates through each character in the string, and passing it to the function. The function in this case is a condp, which is like a case statement in other languages.

manutter5117:05:46

so it’s basically matching the current character against the first character of each pair, and if they’re equal, it returns the second character of each pair. If none of them match, it returns the original character

manutter5117:05:17

(tr "test") ; ==> “aisa”

ghadi17:05:31

@vitruvia there is clojure.core/replace and clojure.string/replace . The first one is generic and can take a map of replacements, the latter is specific to strings.

ghadi17:05:02

I find condp harder to read

tbaldridge17:05:55

and almost anytime you see condp = you could replace it with a hashmap

tbaldridge17:05:17

in this case: (get {\t \a \e \i} % %)

tbaldridge17:05:45

but yeah, use regex instead

ghadi17:05:54

or (apply str (replace {\t \a \e \i} input))

vitruvia17:05:26

thanks guys!

vitruvia17:05:58

just one extra question, why do you need to use apply str?

vitruvia17:05:19

if all of my elements are str shouldn't it return a str anyways?

noisesmith17:05:41

no, sequence functions return sequences

noisesmith17:05:55

and the elements of a string are characters

noisesmith17:05:03

so you get a sequence of characters back

noisesmith18:05:30

=> (replace {\e \a \l \p} "hello")
(\h \a \p \p \o)

noisesmith18:05:50

=> (apply str (replace {\e \a \l \p} "hello"))
"happo"

vitruvia18:05:50

but if I do it with Regex?

vitruvia18:05:58

by the way what command is that?

noisesmith18:05:05

with regexes you stay strings, and everything will be ~100x faster

noisesmith18:05:18

the bot is /clj - but as you have seen it’s a bit buggy

vitruvia18:05:28

great, I'm using regex and to be honest I think it is more readable

vitruvia18:05:36

cool, thanks

lepistane18:05:40

ello guys i need help 1. have backend done in spring and i wanted cljs on frontend i am extreme beginner so i want to ajax-cljs that backend and use reagent to show that response i managed to make a button that sends ajax to the backend and it write to console.log can someone help me write something in browser? Like data.name or something? how do i do that?

lepistane18:05:10

why cant i just do this (first @response) when i put ajax-cljs response to atom to get first element of that response which is

verma18:05:44

what’s the type of the result @lepistane is it a JS array or is a ClojureScript vector/seq?

verma18:05:19

you can do a (first ...) on a clojurescript sequential types.

lepistane18:05:22

i have no clue when i use (type GET url) i get object

verma18:05:02

print it using (js/console.log ...)

lepistane18:05:02

i cant even (seq @response) same error

lepistane18:05:27

u mean print response? there it is in picture i posted looks like json

verma18:05:18

yeah, print it using (js/console.log ...) .. this will help make it clear if its a JS object or a Clojurescipt one.

lepistane18:05:17

@verma this is what i got printed function (meta,cnt,shift,root,tail,hash){ this.meta = meta; this.cnt = cnt; this.shift = shift; this.root = root; this.tail = tail; this.hash = hash; this.cljs$lang$protocol_mask$partition0$ = 167668511; this.cljs$lang$protocol_mask$partition1$ = 8196; }

mss18:05:30

beginner question about clojure concurrency constructs and jvm concurrency: what’s the general kind of concurrency construct I want to reach for if I need to puts 100s of long running blocking operations in flight?

verma18:05:32

ok, that means its clojurey

lepistane18:05:33

(.log js/console (str (type response))))

verma18:05:33

just (js/console.log response) would have sufficed

lepistane18:05:56

cljs.core.PersistentVector {meta: null, cnt: 4, shift: 5, root: c…s.c…e.VectorNode, tail: Array(4)…}

verma18:05:12

ok so it is a vector .. can you show me some of the code which is throwing the error?

verma18:05:21

(first response) should have worked

verma18:05:57

@lepistane feels like you should be doing (reset! resp ..) in your handler function .. and not right after GET since it may be async?

verma18:05:05

most likely is async

verma18:05:38

also I am assuming the atom here is reagent.core/atom

verma18:05:09

move the (reset! resp (js->clj response)) into the handler and see what happens.

verma18:05:45

you are most likely setting response to what (GET ...) returns (some JS representation of async operation)

verma18:05:57

and then trying to (first ...) on it, which won’t work

lepistane18:05:45

i dont have error anymore

lepistane18:05:55

so basically this handler function is like a callback in jquery?

lepistane18:05:16

would you be kind to help me with one more thing?

lepistane18:05:53

so i got vector now in atom (and yes that's reagent atom)

lepistane18:05:02

(defn prikazi [] [:div.prikaz (:name (first @resp))])

lepistane18:05:17

should in my mind print the name of first map that's in that vector

lepistane18:05:38

(defn handler [response] (reset! resp (js->clj response :keywordize-keys true)))

verma18:05:17

erm, I wouldn’t think so

lepistane18:05:17

but when i click on my button nothing happens

verma18:05:31

your keys in the map are not keywords, they are strings

verma18:05:43

so do (get (first @response) "name")

verma18:05:09

when you do (clj->js …)

lepistane18:05:55

it does work with get omgggggg i've been trying to do this for 2 whole days XDDD

verma18:05:03

:thumbsup:

lepistane18:05:05

thank you!!!

verma18:05:13

you can transform maps with keys, so you won’t have to deal with strings 🙂

lepistane18:05:33

didnt i do that with new handler? (defn handler [response] (reset! resp (js->clj response :keywordize-keys true)))

verma18:05:58

yeah, that should work

lepistane18:05:03

it does work. finally!! AHHAHA i am so happy thank you!! btw how did u learn all that where how when any resources that you could recommend?

mobileink18:05:35

keyboard, google, unlimited coffee, n days. simple_smile

matan18:05:47

(-> input-mapping :headers-mapping :gold-tags) is that a nice way to destructure a nested map? do you typically do it differently?

matan18:05:28

kind of follows the structure of the map in a linear order, compared to nested extraction

verma19:05:03

@matan I mostly try to do that, with some-> so I bail out in case something returns nil, I think this is supposed to be pretty fast as well compared to (get-in...)

matan19:05:12

oh, how cool! thanks @verma

matan19:05:08

can't wait for clojure.spec/clojure 1.9's validators, to make validation and extraction more tightly integrated

mkeathley19:05:47

I am trying to read in a file line by line and apply a transducer to each line of the file. Here is my code:

(defn file-contents [fpath]
  (line-seq (jio/reader fpath)))

(def clean
  (comp
    (filter #(= (first %) "*"))
    (drop 6)))

(defn apply-transducer [f r v]
  (if (empty? r)
    (conj v (clean (char-array f)))
    (recur (first r) (rest r) v)))

mkeathley19:05:26

So I am using the http://java.io/reader function to read in the file and converting that of a sequence of each line

mkeathley19:05:41

If I print each item in the seq, it works fine

mkeathley19:05:51

However, if I call apply-transducer on the seq using the clean transducer, I get this: [#object[clojure.core$filter$fn__4808$fn__4809 0x2e5bde32 "clojure.core$filter$fn__4808$fn__4809@2e5bde32"]]

mkeathley19:05:05

Am I missing something here?

verma19:05:30

calling a transducer like a function will return a reduction function .. so not really a cleaned output

verma19:05:57

you can use sequence function to do this: https://clojuredocs.org/clojure.core/sequence

verma19:05:35

(sequence (comp (remove #(str/starts-with? % "*"))) (line-seq file)) .. something like this?

noisesmith19:05:49

verma: that should work, but the comp is a noop

noisesmith19:05:15

and really, it makes more sense to just use remove directly, sequence isn’t helping here

verma19:05:43

yeah, agree, sorry I was just building off the transducer from the example 🙂

verma19:05:59

may not work, I just typed it here 🙂

mkeathley19:05:12

Let me try it

mobileink19:05:18

@matan: have you looked at "literal" destructuring with :keys? see https://gist.github.com/john2x/e1dca953548bfdfb9844

mkeathley19:05:29

@verma I am getting an empty sequence now, so that's a start 🙂

mkeathley19:05:53

So I am still getting empty seqs

verma19:05:00

(sequence (remove #(clojure.string/starts-with? % “*”)) [“hello” “*world” “this” “*is” “test”])

tbaldridge19:05:31

use the fully qualified name or perhaps require it first

dpsutton19:05:41

it has some issues with strings as well

rmuslimov19:05:59

any way I can adapt get works with lazy-seq? (get '(1 1) 0) => nil ?

rmuslimov19:05:28

however (get [1 1] 0) => 1

mkeathley19:05:33

@verma That isn't quite what I am looking for. I am starting with a lazy seq, and I had my comp in the wrong order

mkeathley19:05:55

What I first want to do is drop 6 from each line

mkeathley19:05:08

Then filter out everything that starts with *

verma19:05:18

so drop 6 characters from each line?

verma19:05:24

or drop the first 6 lines?

rmuslimov19:05:36

dpsutton: yea, but it can not be composable like (get-in val [:foo :bar 0])

dpsutton19:05:10

if you've got more complicated navigation i would look at spectre

dpsutton19:05:48

so what is your use case? You want the third element of the fifth element of the first element of a list?

rmuslimov19:05:49

I have crazy long structure, and using get-in for pulling values from it. I met persistenlist in it, and my get-in got broken

rmuslimov19:05:08

if I replace them with vector, all works well. But I don’t want to

rmuslimov19:05:16

I’ll checkout specter

dpsutton19:05:39

no problem. what's the structure? a lazy list?

dpsutton19:05:56

and you know which elements of it you would like?

rmuslimov19:05:54

`{:POS {:source ({:ISOCurrency "USD", :requestorID nil})},
    :altLangID "?",
    :availRequestSegments
    {:availRequestSegment
     ({:hotelSearchCriteria
       {:criterion
        ({:hotelRef
          ({:chainCode nil,
            :chainName nil,
            :hotelCode "123",
            :hotelName nil}
           {:chainCode nil,
            :chainName nil,
            :hotelCode "345",
            :hotelName nil}),
          :position nil,
          :radius nil,
          :refPoint (),
          :stayDateRange nil})},
       :roomStayCandidates
       {:roomStayCandidate
        ({:guestCounts
          {:guestCount ({:ageQualifyingCode nil, :count 1})},
          :roomAmenity ()})},
       :stayDateRange {:end "2017-08-17", :start "2017-08-15"}})},
    :echoToken "?",
    :primaryLangID "?",
    :version 1M})

rmuslimov19:05:00

an example from tests

dpsutton19:05:23

ahh. yeah i'll bet specter is right up your alley

dpsutton19:05:33

i think he has a filter to watch the word but i misspelled it

rmuslimov19:05:09

yep, will try it. thanks!

mkeathley19:05:31

drop 6 characters

verma19:05:50

ah, you can just (map #(subs % 6))

verma19:05:17

that is true for transducers though, comp order is reversed 🙂

mkeathley19:05:00

So first goes last

verma19:05:08

I mean, you don’t really need transducers here, but if you want them in there, you can have (comp (map #(subs % 6)) (remove #(str/starts-with? % "*")))

verma19:05:26

no, first goes first 🙂 .. first goes last is the natural comp order 🙂

mkeathley19:05:16

Oh yeah that's what I thought

mkeathley20:05:17

Got it working @verma! Thanks!

vitruvia21:05:20

does clojure have a builtin function for counting ocurrences of an element in a string or sequence or do I need to build my own?

Drew Verlee21:05:52

@vitruvia (frequencies "122333")

john22:05:22

or a filter