Fork me on GitHub
#beginners
<
2017-05-26
>
vitruvia03:05:43

can anyone help me out?

john04:05:05

Would (remove nil?work? Perhaps drop the recursion into a loop further down the function, rather than recurring back to the top level.

john04:05:30

Or use an accumulator that only collects the non-nil values.

tap04:05:55

You snippet is broken. You maybe want to replace line 6 with (list (select (first a-seq)))? One solution to your problem is to not cons nil to the result sequence

(defn my-filter [pred? a-seq]
  (let [select (fn [x] (if (pred? x)
                         x
                         ))]
    (if (<= (count a-seq) 1)
      (list (select (first a-seq)))
      (if-let [e (select (first a-seq))]
        (cons e (my-filter pred? (rest a-seq)))
        (my-filter pred? (rest a-seq))))))

joshkh11:05:50

how might i go about getting more detailed information from an exception? for example, the following isn't very helpful:

(post "" 
      {:form-params {:query "<query model=genomic view=Gene.organism.name></query>"}})
ExceptionInfo clj-http: status 400  slingshot.support/stack-trace (support.clj:201)

joshkh11:05:01

i know the server is sending back a reason why it failed which i can see in my browser but not in the repl

agile_geek12:05:47

@joshkh have you tried evaling *e in the repl immediately after the exception (the repl connected to the server)

agile_geek12:05:33

@psalaberria002 personally, I wouldn't try and do the condition in the threading macro. I would put the intermediate result in a var in the let.

vitruvia12:05:57

@john Thanks, but I can't use acc or remove. I mean I could but I think this is meant to be solved with a recursion using cons

vitruvia12:05:18

@tap thanks I'll try that.

dpsutton13:05:34

vitruvia: if the current element satisfies the predicate, you want to return the element cons to the rest of the filter output, otherwise you just want to return the rest of the filter output

dpsutton13:05:21

and you only want to continue when you have a seq'able sequence

dpsutton13:05:30

does that help?

vitruvia13:05:46

@dpsutton Sort of... I do get the idea, I just don't know how to make it into clojure code using only cons and conditionals.

dpsutton13:05:12

(defun my-filter [pred? l]
  (when (seq l)
     (let [e (first l)]
        (if (pred? e)
          (cons e (my-filter pred? (rest l)))
          (my-filter pred? (rest l))))))

dpsutton13:05:15

try something like that

dpsutton13:05:20

and let's look at it

dpsutton13:05:05

"when there's more elements of the list, if the predicate applies, return this element and whatever else the function decides, or else just return the rest of the function

vitruvia13:05:25

hmmm I think I can do something like that using map

vitruvia13:05:29

just realized map is allowed

dpsutton13:05:58

i'm interested to see your idea

dpsutton13:05:09

but if you check out the source,

([pred coll]
   (lazy-seq
    (when-let [s (seq coll)]
      (if (chunked-seq? s)
        (let [c (chunk-first s)
              size (count c)
              b (chunk-buffer size)]
          (dotimes [i size]
              (let [v (.nth c i)]
                (when (pred v)
                  (chunk-append b v))))
          (chunk-cons (chunk b) (filter pred (chunk-rest s))))
        (let [f (first s) r (rest s)]
          (if (pred f)
            (cons f (filter pred r))
            (filter pred r))))))))

dpsutton13:05:42

ignore the then block of the if (chunked-seq? s) and you'll see that they have done exactly what we did except with a lazy sequence

dpsutton13:05:35

(when-let [s (seq col)]
   (let [f (first s) r (rest s)]
     (if (pred f)
       (cons f (filter pred r))
       (filter pred r)))))

dpsutton13:05:09

but play with map. you can probably (definitely) make this with reduce as well

vitruvia13:05:10

but why doesn't the source code return an error when the seq is a singleton or empty? in this case you would call pred? on nil and it could return an error. For example even? nil returns an error

dpsutton13:05:25

i'm not sure i understand

dpsutton13:05:46

it will never do that: (when-let [s (seq col)] ...

dpsutton13:05:52

it returns nil if there are no values

vitruvia13:05:15

I haven't learned when yet =(

dpsutton13:05:16

and (first [a]) is well behaved

dpsutton13:05:27

it's an if without a else clause

dpsutton13:05:46

(if predicate then-block) == (when predicate then-block)

vitruvia13:05:27

let me see what I can do

dpsutton16:05:27

why is select a function?

dpsutton16:05:47

select calls pred again, after you've already called it

dpsutton16:05:06

why not just cons the element e onto (my-filter pred? (rest a-seq))

vitruvia16:05:02

What do you mean? the element e is only bound to the first element of the seq, I still need to check whether it fulfills pred?. That is what select is for.

dpsutton16:05:28

you do that in the (if (pred? e)) so why check it again the the select function

dpsutton16:05:34

you only need to check it once

dpsutton16:05:11

and in fact you really should only do it once, both since its extra work for no gain and someone could give you a function with side-effects even though you might specify they should give only pure functions

vitruvia16:05:40

oh you are right

vitruvia16:05:20

great, thanks for the help

dpsutton16:05:25

does it work correctly?

john16:05:38

That's some good looking code 😉

dpsutton16:05:54

in fact, it looks very, very similar to production code in clojure 🙂

vitruvia16:05:00

Thanks guys. Clojure is beautiful 😄

noisesmith17:05:35

(but I didn’t use ->> here because it didn’t actually apply to this code)

nimblerabit17:05:53

I'm sure this is a silly question, but I'm having trouble figuring it out. I have two sequences of data, like this:

(55.9 55.0 54.4 53.8 53.6 53.5 53.0 52.9)
(3459 27554 8433 4177 22351 13752 3228 26071)
The data is related, so in this example the first item in the first sequence is a :rate and the first item in the second sequence is a :count. I'm trying to combine these into a sequence of maps, like this:
({:rate 55.9 :count 3459} {:rate 55.0 :count 27554} etc etc)

nimblerabit17:05:15

For some reason I'm blanking on how to do it, can anyone point me in the right direction?

noisesmith17:05:34

(map #(hash-map :rate %1 :count %2) rates counts)

nimblerabit17:05:27

My brain must be fried, so simple. Thanks a bunch!

grzm18:05:16

I have a sequence that I'd like to put onto a core.async channel, one element at a time. I'm sure there's an idiomatic way to do this, but I haven't been able to figure one out. I've tried onto-chan, but if the sequence contains more than 1024 elements (the number of puts that can be cached), I get an error due to exceeding the put cache size. Any ideas or pointers to references most welcome!

donaldball18:05:45

Maybe you want a channel with a buffer large enough to contain your seq?

grzm18:05:04

I suppose I could partition the sequence into chunks, and put the chunks on using onto-chan

donaldball18:05:12

Or you want a go-loop that will park its puts instead of barfing when the channel buffer is full

grzm18:05:57

@donaldball yeah, I've thought using a buffered channel: I haven't used them much (or, at all, actually) so far. I've been trying to stay within the limits of what I currently know.

grzm18:05:29

My go-loop attempts haven't been working so far. I'll try to create a test case.

grzm18:05:02

@donaldball thanks for confirming that I've likely been thinking in right way, just not getting the implementation right

donaldball18:05:33

to-chan might also be more what you’re looking for

grzm18:05:01

came across that one, too. I've got an existing channel I'm working with, otherwise I think that would be a similarly good fit

donaldball18:05:14

Maybe you need to start your reader before you start your writer?

ssansovich18:05:38

Why does (map key {:a 1 :b 2}) => (:a :b) but (key {:a 1}) throws a ClassCastException? Interestingly, (apply key {:a 1}) => :a

noisesmith18:05:52

apply key works in that case because it turns your hash-map into a list of hash-entries

noisesmith18:05:06

and key works on a hash-entry and luckily in that example there’s only one so key works

dpsutton18:05:42

user> (source key)
(defn key
  "Returns the key of the map entry."
  {:added "1.0"
   :static true}
  [^java.util.Map$Entry e]
    (. e (getKey)))
nil

noisesmith18:05:42

@ssansovich when you map on a hash-map, your function gets called on each hash-entry individually

ssansovich18:05:33

Thanks @noisesmith but why does (key {:a 1}) throw an exception? That’s what I’m missing. Maybe I’m being dense

dpsutton18:05:42

(key {:a 1})
ClassCastException clojure.lang.PersistentArrayMap cannot be cast to java.util.Map$Entry  clojure.core/key (core.clj:1518)

noisesmith18:05:03

@ssansovich a hash-map is not a hash-entry

noisesmith18:05:08

it’s a collection of hash-entries

dpsutton18:05:08

the error explains it. it's a persistent array map. the type hint in key dictates it must be a MapEntry

ssansovich18:05:54

thanks @noisesmith and @dpsutton I’ll read up on the difference

noisesmith18:05:43

@ssansovich remember that a hash-map can have 0 or more keys in it - it doesn’t make sense to ask what the key of {} is, or what they key of {:a 0 :b 1 :c 2} is

dpsutton18:05:49

the map is a collection of map entries. Just like [1 2 3] is a collection of integers. Key works on the entry, not the collection of the entries the same way + works on numbers not the collection of them. however you can map + over a collection and apply it to a collection

ssansovich19:05:39

makes sense. thanks very much!

jlutteringer21:05:23

I have quick question: what is the idiomatic way to map a function across two uneven sequences? I found some references to calling map with more than one collection as in (map + [1 2] [3 4]) => (4 6), but it looks like it halts processing based on the shortest input

jlutteringer21:05:53

never mind! in the process of typing up my question I must have stumbled on the correct wording to please google and found this stack overflow post: https://stackoverflow.com/questions/18940629/using-map-with-different-sized-collections-in-clojure

gmercer23:05:14

in core.async is there a way to subscribe to everything (e.g. a stats gatherer) or do I need mult the publications channel ?

noisesmith03:05:10

gmercer: yeah, a mult on the same channel that you make the pub from is the simple way to do it

gmercer03:05:04

@noisesmith cheers - the stats gathering should pretty lightweight and is very unlikely to be the slowest consumer

gmercer03:05:36

I have another slightly related question .. I intend to have the stats running a go block and updating atoms does it seem reasonable to return a function that closes over those atoms for answering questions about the stats ?

noisesmith03:05:58

why atoms if the data is closed over?

noisesmith03:05:24

(that is, as opposed to updating the values as args to recur)

noisesmith03:05:18

I ask because a have a pretty good idea of when I would close over values (they are only relevant in a specific scope and it makes sense to update them via recursion) and I have a good idea of when to use a global atom (multiple threads need to access the values and they don't "belong" to a specific process), but stuff that is in between seems like it's just cargo culting OO usually

gmercer04:05:10

maybe if i dumped some sketched out code ?

noisesmith04:05:53

minor thing, there's a bunch of extra parens that will lead to "long can't be cast to IFn" errors at runtime

noisesmith04:05:19

see, the thing is you are simulating an object via closures, and we have actual objects if you want to do OO

noisesmith04:05:16

the idiomatic thing would be to have functions that calculate the stats you want, based on the raw values, and put all the values in a single hash map that gets updated with a single swap per iteration

noisesmith04:05:24

and return the atom

gmercer04:05:36

extra parens (sorry - just tried to jam idea in)

noisesmith04:05:51

yeah, just wanted to make sure you were aware

noisesmith04:05:37

so the normal way to do it would involve (atom {:size 0 :start (System/currentTimeMillis) :freq 0}) and swap! to update the :size and :freq keys each iteration

noisesmith04:05:53

and instead of closing over the functions, just make them normal defs that a client can use

noisesmith04:05:38

don't use hand-made message passing - I don't think this calls for OO, but if you need it we have defprotocol, deftype, defrecord etc. for making actual objects that have methods

gmercer04:05:11

I know it looks like I am attempting to hide the raw values ala OO

gmercer04:05:07

but I thought it was more of a basis for using https://github.com/ztellman/potemkin#def-derived-map

gmercer04:05:22

where I could offer some kixi.stats analysis without the user having to learn kixi

gmercer05:05:02

thanks for the feedback - I am thinking the def-derived-map might get closer to what you were recommending (just return a map!) while letting me pop in some extra features - I can see the function option is pretty dodgy (kw -> any)

noisesmith05:05:07

it's much more normal to hand the user data and a function - if you want extra features you don't need def-derived-map, defrecord suffices

noisesmith05:05:18

but I don't think you even need the extra features