Fork me on GitHub
#beginners
<
2018-04-12
>
Logan Powell00:04:07

Just saying thanks again! Worked like a charm! http://exercism.io/submissions/02b1e7c37b99433189c25365de9bd81b Going to look deeper into some->> 👋

seancorfield00:04:55

@funyako.funyao156 Would this work for you?

boot.user=> (s/def ::fmn (s/cat :a string? :b string? :c string? :kws (s/* keyword?)))
:boot.user/fmn
boot.user=> (s/conform ::fmn ["a" "b" "c"])
{:a "a", :b "b", :c "c"}
boot.user=> (s/conform ::fmn ["a" "b" "c" :d :e :f])
{:a "a", :b "b", :c "c", :kws [:d :e :f]}
boot.user=> (s/conform ::fmn ["d" "e" "f" 1 2 3])
:clojure.spec.alpha/invalid
boot.user=> (s/explain ::fmn ["d" "e" "f" 1 2 3])
In: [3] val: 1 fails spec: :boot.user/fmn at: [:kws] predicate: keyword?
nil
boot.user=> 

seancorfield00:04:22

@loganpowell Cool! You could use (assert ...) in str-2-seq instead of the if to perhaps simplify things there (now that you're catching assertions):

(defn str-2-seq [str]
  (let [chars (filter #(not= \- %) (seq str))]
    (assert (= 10 (count chars))
    (split-at 9 chars)))

seancorfield00:04:58

Since (split-at 9 chars) produces [digits checkr] as its result.

seancorfield00:04:48

Then another little trick you can do in isbn? is to further destructure checkr since you know it should be a sequence of one element

(defn isbn? [isbn]
  (try
    (let [[digits [checkr]] (str-2-seq isbn)
          nine (first-9 digits)
          chkr (hdl-check checkr) ; checkr is a Character now -- no need for apply
          sum (+ nine chkr)]
      (and (= (mod sum 11) 0)
           (> 100000 sum)))
    (catch Throwable _ false)))

❤️ 4
fmn00:04:53

@seancorfield Thanks! Worked like a charm. I need to understand spec better especially about the whole "regex" thing since I'm expecting :kws would be just another vector, not flattened out.

seancorfield00:04:37

The conformed :kws is a vector but s/* matches zero or more entries in a sequence.

seancorfield00:04:51

The regex vs collection stuff takes a bit of getting used to...

andy.fingerhut15:04:57

@grierson Depending on how much compute time is required by tf/parse, you might want to consider first calculating the result of tf/parse and putting the results under a new key in the maps to be sorted. Then you comparison function would just become t/after?. You can postprocess to remove the just-added key if you do not need it for anything else later. This is a general pattern called "decorate - sort - undecorate" that can be useful if keys are expensive to compute.

andy.fingerhut15:04:32

That is just an efficiency consideration, though. As far as correctness goes, what you wrote looks reasonable.

3Jane15:04:59

Hey, qq. -> and ->> provide a pipe of sorts. Is there a way to tee things out of the pipe temporarily and then merge it back to the pipe?

3Jane15:04:33

Very simple example: I have a list as an input. I want to count values of the list, create a range of 0..n, then map over this range and original list to create pairs of [i, value], then perform further operations on the list of pairs.

Alex Miller (Clojure team)15:04:15

but you can kind of do what you’re describing using as->

andy.fingerhut15:04:04

The specific steps you describe sound similar to the built-in function map-indexed. Might be worth looking at to see if it does what you want.

3Jane15:04:54

@alexmiller TIL, thank you 🙂 this is relevant to my interests @andy.fingerhut it’s just an example - I needed something that would be short to describe and simple to understand (thank you though, it would have been a good solution if this was the problem)

Alex Miller (Clojure team)15:04:27

(as-> [1 2 3] c (map vector (range (count c)) c))

Will16:04:56

I have a map called my-map which equals {:a 1 :b 2} and I want to store all the map keys into a symbol. I tried this (def my-keys (keys my-map)) but I’m getting this error

IllegalStateException Attempting to call unbound fn: #'user/keys  clojure.lang.Var$Unbound.throwArity (Var.java:45)

eval202016:04:45

Does (clojure.core/keys my-map) work?

sundarj16:04:59

have you done a (def keys) somewhere?

Will16:04:30

That was the problem, I did (def keys (keys my-map)) Not realizing that was a method until after. Thanks!!

8
Logan Powell17:04:43

@noisesmith that some->> idea was pretty clever 😉

noisesmith17:04:23

In my experience it leads to simpler code that survives refactors. Breaking try/catch based logic when editing code is common in my experience.

Will17:04:15

Is there a way to reverse desctructure? For example, instead of a b & rest then rest & a b?

noisesmith17:04:08

no

👍 4
🙂 4
❤️ 4
😉 4
✈️ 4
🎯 4
🐈 4
Nikos17:04:05

What are some good up-to-date beginner tutorials/guides on Clojurescript apart from the Getting Started guide on the CLJS site?

grierson18:04:34

@nikoszp The re-frame documentation is very good. https://github.com/Day8/re-frame

👍 8
Will20:04:29

I have a symbol rest that is equal to a sequence (3 2 1). When running (rseq rest) I’m getting this error

ClassCastException clojure.lang.APersistentVector$RSeq cannot be cast to clojure.lang.Reversible  clojure.core/rseq (core.clj:1573)
I’m not sure what that means? rseq worked on a sequence of strings

noisesmith21:04:07

rseq works on specific collection types, it doesn't work on any of the collections that print with ()

noisesmith21:04:16

in this case, you generated something using rseq, and rseq cannot operate on its own output

noisesmith21:04:54

you can use reverse though

mfikes23:04:50

I think the set of collections that rseq can be applied to are exactly those which satisfy the reversible? predicate.

mfikes23:04:11

A couple of reversible collections that the rseq docstring doesn't mention are sorted sets and map entries.

noisesmith23:04:22

yeah - pretty much user=> (filter reversible? ["" [] #{} {} () nil]) -> ([])

Will23:04:44

and reverse works on everything?

noisesmith23:04:32

everything seqable? returns true for

noisesmith23:04:04

which is a lot of things user=> (filter seqable? ["" [] #{} {} () nil]) => ("" [] #{} {} () nil)

noisesmith23:04:11

rseq performs better though

Will23:04:55

So I’d better off converting my sequences to vectors and using rseq? or is reverse fine for everything else

seancorfield23:04:58

So, (if (reversible? s) (rseq s) (reverse s)) ?

mfikes23:04:03

@seancorfield Hah! The definition of reverse in ClojureScript has that built in.

noisesmith23:04:04

if perf is the main concern, I assume using reverse directly will still be faster than vec followed by rseq

mfikes23:04:26

(if (reversible? coll)
    (or (rseq coll) ())
    (reduce conj () coll))

mfikes23:04:28

^ ClojureScript's definition of reverse

mfikes23:04:25

The or bit is to handle the nil that results if you apply rseq to an empty reversible collection

Will23:04:47

Thanks guys that clears it up :thumbsup: