Fork me on GitHub
#beginners
<
2015-12-08
>
dbstandsfor03:12:20

Hmm. Anyone here? I am mystified by this 4clojure problem. After several attempts I googled it (probably not best practice, I know), but I cannot understand why it works. And then I tried the code in the REPL at home, and it doesn't seem to work the same way there.

andrut03:12:40

hey, try posting the problem simple_smile

dbstandsfor03:12:04

Before I googled for an answer, I assumed I needed some kind of test to see what sort of collection it was, to reverse it, and then to re-cast it as the original collection type. I was surprised that it seemed to work without doing that. But then on my REPL at home it isn't working the same way, it always gives me a list like I was expecting.

dbstandsfor03:12:13

I just realized... a vector and a list with the same contents are equal.

dbstandsfor03:12:16

Is that all it is?

dbstandsfor03:12:54

now I think I remember that last time I asked a question on here, it was just that I was missing a parenthesis, and you answered that time too! Clearly I need to pause a bit longer before posting my questions.

codonnell03:12:43

That is, indeed, all it is. The rubby ducky treatment is always surprisingly effective.

dbstandsfor03:12:38

rubber ducky?

codonnell03:12:30

Talking out your problem to a friendly rubber ducky. They may not respond, but talking it out is often enough for you to understand your problem.

dbstandsfor03:12:48

ah. yes. I definitely need to do that.

kyle_schmidt03:12:45

or quite literally duck typing in this case

kyle_schmidt03:12:40

?? I have a list (or seq?) of urls like: (["http://example.com"] ["http://gmail.com"] ["http://oajve.com"]) I would like to perform a get request on each but I don't know what to do to "get into" this data structure and perform some sort of seq operation

codonnell03:12:13

If you just want to get a particular element, you can use first, second, or nth. But probably you want to execute some function on each element of your list, in which case you're probably looking for map or doseq.

codonnell03:12:44

You can also use get like nth.

kyle_schmidt03:12:59

hm tried map already using: (map #(client/get [%]) urls)

kyle_schmidt03:12:23

and (map #(client/get %) urls)

codonnell03:12:23

map returns a lazy sequence, so unless you're doing something to realize those urls, nothing will happen

codonnell03:12:49

I believe mapv is not lazy; you could give that a try.

kyle_schmidt03:12:17

The fact that the list is nested with vectors is problematic

kyle_schmidt03:12:02

PersistentVector cannot be cast to java.lang.string

codonnell03:12:36

If I gave you [""] how would you get the string out?

codonnell03:12:34

Cool, I've been looking for an opportunity to try that. 😄

kyle_schmidt03:12:02

is that the best solution or can we do better?

dbstandsfor03:12:04

how about flatten ? turn the list of vectors of strings into just a list of strings

codonnell03:12:48

That also works. I like that.

andrut04:12:58

hey, you can also use mapcat, it'll call map and concat the results

roelof06:12:03

good morning everyone

roelof06:12:11

anyone a tip how to solve this one : http://www.4clojure.com/problem/166

roelof07:12:01

how can I check if a entry is a function or not ?

rantingbob07:12:12

What do people think of Intrduction to Functional Programming with Clojure from Lispcast, and there accompanying web dev course?

rantingbob07:12:26

I'm thinking I might do it after I cover clojure for the brave and true

trancehime07:12:57

I've got a question

cjmurphy07:12:38

@roelof: It is simpler than it sounds. You are given the function that you need to use to return one of three keywords.

trancehime07:12:45

I want to use filter to create n separate sequences from a much bigger sequence based on n keys, so I can compare them. How do I go about persisting the sequences returned from filter?

cjmurphy07:12:59

You have a sequence of size n and need to get another sequence of size n?

trancehime07:12:38

For example: [{:data data :identifier 1} {:data data :identifier 2} {:data data :identifier 3}], I want to use filter so I can get 3 individual sequences based on :identifier so I can check if :data in each of the maps are the same

trancehime07:12:12

My purpose is that I have a giant set of data from a database submitted by various users and I want to check if the data from the users are exactly the same

trancehime07:12:30

well, "giant" is an exaggeration

roelof07:12:08

@cjmurphy: I know. but the first one is (< 5 2 ) , oke, then < is the function

cjmurphy07:12:14

Can you use apply? That would do something to each of the hash-maps.

roelof07:12:39

@cjmurphy: when I have as argument (fn [x y] (< (count x) (count y))). How can I execute only the count functions then?

cjmurphy07:12:46

Consider what you want to do to one of the hash-maps then use apply to get that function you have created to each of them.

roelof07:12:47

that part I do not see

cjmurphy07:12:17

Last two comments to @trancehime

cjmurphy07:12:58

@roelof: I think you've got it now? (I'm assuming)

roelof07:12:12

oke, so I have to use apply

cjmurphy07:12:36

No not you.

cjmurphy07:12:57

You have to use if simple_smile - much simpler

roelof07:12:15

I thought a cond

cjmurphy07:12:43

Yes prolly even better - I just like if

roelof07:12:14

hmm, when I do this

(defn my-eq
  [operator st1 st2]
  (println operator)

(my-eq (fn [x y] (< (count x) (count y)))) 

roelof07:12:25

I see a wrong arity error message

trancehime07:12:26

youre only passing 1 argument to my-eq which is (fn [x y] ...)

cjmurphy07:12:47

You promised you would use cond, but you have not!

roelof07:12:10

@cjmurphy: yep , I try to find out why I see the error message

cjmurphy07:12:44

But @trancehime has just told you why.

roelof07:12:07

moment, I will scroll back to find that part

trancehime07:12:16

your my-eq function is asking for operator, st1, st2

roelof07:12:01

yes., because the first test looks like this : ( < 5 1))

roelof07:12:13

and that looks to me 3 seperate parameters

roelof07:12:35

So one paraemeter

trancehime07:12:17

usually an anonymous function like what you showed in your example just now is treated as 1 argument

roelof07:12:41

hmm, then I have to destruct it to find out what both counts are returning. When I do the whole function the answer would be false and I cannot say if it's then gt or eq

cjmurphy07:12:39

How do you find out if 5 and 1 are equal when you have a 'less than' function that gives the right answer?

roelof07:12:17

I have to do the same function with both arguments to see which one is true ??

roelof07:12:18

so ( < 5 2 ) false ( = 5 2 ) false ( > 5 2 ) true , so the return value will be :gt

cjmurphy07:12:40

< tells you that first number is less than second number.

cjmurphy07:12:18

But you have to divide and conquer.

cjmurphy07:12:43

5 is greater than 2 so your function should use the < operator to return true.

roelof07:12:00

yep, that is what I also try to say

cjmurphy07:12:16

Of course inside the function you don't know what the numbers are, you only know x and y.

roelof07:12:52

@cjmurphy: correct but x and y are the numbers

roelof07:12:22

in this one (< 5 2) x and y are 5 and 2 ?

roelof07:12:25

oke, then we mean the same

cjmurphy07:12:43

(when (op x y) :lt)

cjmurphy07:12:46

Because op means 'less than'. Better to call it lt-op.

cjmurphy07:12:23

I gotta work now...

roelof07:12:42

oke, have a nice workday

roelof07:12:46

I think I have to write op myself , I cannot find anything on this

trancehime07:12:14

I figured out group-by has the behavior I'm looking for regarding my initial question.

trancehime07:12:21

Now I'm faced with a different conundrum

trancehime07:12:33

Though perhaps I might have to use apply anyway at some point

roelof07:12:08

Cannot help you, im facing my own problem which I find very confusing

trancehime07:12:27

I'll see if I can figure it out myself first

trancehime07:12:35

Just thinking out aloud mostly

roelof07:12:12

I think I have to look for more "beginners" problem. The last "easy" problems are very hard for a beginner like me

roelof08:12:41

hmm : this looks promosing (when (function arg1 arg2) :gt) but if it's false how can I check for the other two

trancehime08:12:08

you should use cond.

trancehime08:12:43

when should only be used if when the expression returns false you don't want to do anything

roelof08:12:47

and then three times the `(function arg1 arg2) part

roelof08:12:39

pfff, somehow I think I have to change function to get this working

agile_geek08:12:09

@roelof: I haven't followed the whole thread but take a look at condp as it might be useful.

roelof08:12:28

@agile_geek: maybe you are right. The 5th example of this page : http://conj.io/store/v1/org.clojure/clojure/1.7.0/clj/clojure.core/condp looks almost on the challenge

trancehime08:12:22

condp probably works better yeah.

roelof08:12:08

the only thing I have to figure out how I can change a function from (< 5 2) to ( = 5 2) or (> 5 2)

roelof08:12:41

or this one (fn [x y] (< (count x) (count y)) where I have or change < or that the function does not use it and I can compare the both counts parts

trancehime08:12:40

If you see the documentation on condp you should notice that it should go through the clauses until a match is made.

trancehime08:12:14

So it's a matter of providing the right predicate, expression and clauses.

roelof08:12:38

oke, but this function is given

trancehime08:12:28

the function is actually just (< (number of characters in x) (number of characters in y))

roelof08:12:31

correct, I know that

roelof08:12:12

but if the numbers of characters are the same in x and in y the output schould be :eq not :lt

trancehime08:12:03

the idea of the challenge is that you can output any of the equalities when all you have is <

trancehime08:12:16

(= :eq (__ (fn [x y] (< (count x) (count y))) "pear" "plum"))

trancehime08:12:51

the function should be such that you can output :gt or :eq or :lt when your comparator is any less-than function

roelof08:12:09

I know , im looking to this one a long time

roelof08:12:05

with these inputs the outcome of the anymous function will be false I think

roelof08:12:33

So I know it need to be :eq or :gt

roelof08:12:13

I do not see how I can see how I can check which one it will be

roelof08:12:23

I take a break

nando08:12:47

@rantingbob: I really like LispCast’s tutorials

nando08:12:13

They are well-paced for someone trying to learn, one concept at a time.

cjmurphy09:12:33

@roelof: (when (op y x) :gt)

trancehime09:12:19

Given a a content-type as image/png and I want to get just the png part, what's a better way than what I have now which is: (first (rest (clojure.string/split mime #"\/")))

trancehime09:12:31

where mime is image/png

trancehime09:12:59

I'm running into java.lang.NullPointerException problems

trancehime09:12:15

even though the same code does not produce the same error in other places

trancehime09:12:32

so (second (clojure.string/split mime #"\/"))?

cjmurphy09:12:13

Well not exactly tackling the problem head on...

trancehime09:12:49

I mean I'm just really confused. I'm using this particular code in order to write save an icon's file extension to a record in a database

trancehime09:12:21

There's one incredibly specific case where I get a java.lang.NullPointerException when I am uploading 3 icons at once

trancehime09:12:29

and it only occurs on one specific form input

cjmurphy09:12:39

You are splitting an actual image file into two based on where the \ character is??

cjmurphy09:12:06

Just the name of a file?

trancehime09:12:12

The image upload part is fine, the file is saved into the filesystem no problem

trancehime09:12:19

or rather, files

trancehime09:12:34

Now, the file object when passing it to the server has a :content-type key

cjmurphy09:12:37

on some protocol String?

trancehime09:12:58

the :content-type key's value is MIME type so it has the image/png or what have you

cjmurphy09:12:24

So maybe the String coming in doesn't have a second \

cjmurphy09:12:02

Only do the split if you know there are two \ chars in the String...

trancehime09:12:16

I'm confused

trancehime09:12:41

I just want to split after /

trancehime09:12:15

This piece of particular code works with literally every single other form input I have that behaves the same way except this one and only if I am uploading 3 icons at once even if they are all exactly the same just with different filename

trancehime09:12:41

The stack trace includes java.util.regex.matcher.gettextlength which lead me to believe it has something to do with my splitting function

cjmurphy09:12:17

Maybe null text coming in

nando09:12:23

How is the mine type determined when the file is uploaded?

trancehime09:12:08

@cjmurphy: I have logged the object entering the server to see if anything appears weird. For cehcking, I uploaded 3 .png files. All 3 of them had :content-type values of image/png

nando09:12:20

Is the file itself inspected, or is it simply from the filed name extention?

trancehime09:12:45

I believe it's from the file itself

trancehime09:12:14

What confuses me is if I am just uploading 1 or 2 images using this form there's no issues. But 3? No, it breaks

nando09:12:00

Any 3 files and it always breaks?

cjmurphy09:12:12

Concurrency issues?

cjmurphy09:12:18

Try a sleep!

trancehime09:12:02

I AM SUPER DUMB

trancehime09:12:16

never mind, I got the issue

trancehime09:12:41

should be :tournamentIconLargeObj and :tournamentIconHugeObj

trancehime09:12:57

What was going in was indeed null, since the form object does not have a :tournamentIconLarge key but a :tournamentIconLargeObj key which contains the file informations

cjmurphy09:12:51

You could fix your null problems forever with a Maybe monad thing.

cjmurphy09:12:34

If you could be bothered using it all the time - like Scala and Haskell people are forced to.

trancehime09:12:36

(the code is actually not so elegant, but I'm quite new at Clojure and they're making me do an awful lot on my own in just a month... I'll probably focus on reworking it once I'm allotted time to do so)

cjmurphy09:12:30

(more a theoretical comment)

trancehime09:12:48

Nah I'm just admitting that how I'm going about the whole thing isn't exactly great xD

cjmurphy09:12:05

okay good luck

escherize13:12:51

whats the best way to arbitrarily sort a seq of maps on a couple keywords? let's say i want all the :b's then all the :a's then all the :c's. So in:

[{:k :c} {:k :a} {:k :b} {:k :a}]
I'm looking for f s.t.
(f [{:k :c} {:k :a} {:k :b} {:k :a}]) 
;=> [{:k :b} {:k :a} {:k :a} {:k :c}]

escherize13:12:43

(let [x [{:k :c} {:k :a} {:k :b} {:k :a}]
      o (->> [:b :a :c]
             (map-indexed (fn [idx itm] [itm idx]))
             (into {}))]
  (sort (fn [{a :k} {b :k}]
          (< (o a) (o b)))
        x))

roelof13:12:09

someone who can help me this 4clojure problem : http://www.4clojure.com/problem/166

roelof13:12:45

I do not see how I can return :gt on the first test

roelof13:12:56

(< 5 2 ) itself is false

cjmurphy14:12:28

Did you look at the two whens I put here?

roelof14:12:06

Two when ?

cjmurphy14:12:13

They give you two thirds of the answer if you can combine them together.

roelof14:12:20

I only saw only this one : (when (op y x) :gt)(

roelof14:12:27

and that is only one when ?

escherize14:12:47

Anyway, incase anyone's interested i have a bunch of "packages" that have "statuses" and I wanted to show them in the order I thread through to become o.:

(defn order-packages [packages]
  (let [o (->> [ "BLOCKED" "PLACED" "PROCESSING" "PROCESSED" "SENT" "PAID" "CANCELLED"]
               (map-indexed (fn [idx itm] [itm idx]))
               (into {}))]
    (sort (fn [{a :status} {b :status}] (< (o a) (o b)))
          packages)))

cjmurphy14:12:57

The other will be this then: (when (op x y) :lt)

roelof14:12:25

oke, now I see it

cjmurphy14:12:31

I put your name at the front to draw your attention (to the second one)

roelof14:12:49

and when nothing is true , it will be :eq

roelof14:12:34

I think I know the answer now

roelof14:12:42

Time to play more on the repl

cjmurphy14:12:24

@escherize: sorting is surprisingly hard I found.

escherize14:12:41

Yeah, that is actually tricky, maybe I'll write a general one someday

cjmurphy14:12:54

I got a general function from the Internet that uses recursion. I'll get it now...

escherize14:12:11

(defn sort-with [coll key-fn val-seq] ,,,)

escherize14:12:39

actually i kind of wrote it...

escherize14:12:40

(defn sort-with [key-fn val-seq coll]
  (let [o (->> val-seq
               (map-indexed (fn [idx itm] [itm idx]))
               (into {}))]
    (sort (fn [a b] (< (-> a key-fn o)
                       (-> b key-fn o)))
          coll)))

(sort-with :k [:c :b :a] [{:k :c} {:k :a} {:k :b} {:k :a}])

;=> ({:k :c} {:k :b} {:k :a} {:k :a})

cjmurphy14:12:20

The tricky bit is sorting from one column, then the next, then the next, which I think is what you are trying to do..??

escherize14:12:40

no, I'm just sorting on one column. And that does sound difficult.

escherize14:12:07

i just wanted to define a sequence to sort by

cjmurphy14:12:19

sort-with for one column??

escherize14:12:20

here [:c :b :a]

escherize14:12:41

yeah, here we sort coll with column :k

escherize14:12:06

I defined sort-with above

cjmurphy14:12:14

Oh looks good.

escherize14:12:46

You've got me interested in the multi-column version now, though.

roelof14:12:42

@cjmurphy: thanks, problem solved

cjmurphy14:12:15

Okay great. @escherize - I'll have to get back to you later on that one (and I prolly will!). An interesting kind of thing to examine here...

cjmurphy14:12:46

Okay found it. This is the reference where everyone has a go:

escherize14:12:25

Oh nice! I know the author and he's awesome! 😄

cjmurphy14:12:37

(defn compare-by [[k comp & more] x y]
  (let [result (comp (k x) (k y))]
    (if (and (zero? result) (seq more))
      (recur more x y)
      result)))

escherize14:12:41

I used to work with him a while back

cjmurphy14:12:07

And above is the function I chose to use.

escherize14:12:32

awesome, thanks cjmurphy!

cjmurphy14:12:20

Can you tell me how to format as code? You can see what I tried.

escherize14:12:46

totally, just do three `'s then three more, all in the same message

escherize14:12:27

wow, that is a really elegant solution.

cjmurphy14:12:52

I just used it at the time. Prolly better able to understand it now...

roelof15:12:59

Another question : I do now the 3rd chapter of web development with clojure and use the librerator plugin

roelof15:12:18

but what do I have to put into the main function

roelof15:12:47

I use cursive instead of lighttable and I cannot see the pages

roelof15:12:02

and I do not see the port I have to use

roelof15:12:23

It is wise to do the exercises of the brave book and also do the 4clojure challenges

cjmurphy15:12:10

I actually read most of the Brave book but didn't do the exercises. A good combination of theory and exercises might be to hold off on doing the exercises on one of them.

roelof15:12:49

oke, I ask this because im stil struggeling to get the fp clojure way of doing things

roelof15:12:16

Later on I would like to use clojure to make web apps but now that is more then i can chew now

cjmurphy15:12:32

You might want to be reading a few books then. Perhaps leave the exercises for a while, give them a rest and come back later 'refreshed' after having read a few of the books out there.

roelof15:12:37

I can do that but my problem is Always if I read it , I think I understand it but then I have to do in in real

roelof15:12:10

that why I choose to do a lot of exercises / challenges to get really a feeling for it

cjmurphy15:12:58

The whole 'how to do web applications' is going to be changing with Om-Next, which eschews talking through to REST services. So I would delay that part of the learning - that's certainly my strategy.

cjmurphy15:12:25

I might be wrong - just feeling my way.

roelof15:12:04

oke, I have seen a lot of Om. Looks good but I wonder if you could use it when you do not anything about react

roelof15:12:22

No problem. I ask here for oponions

roelof15:12:15

I will focus on 4clojure and the brave book

roelof15:12:35

I think that this will me busy for some months

cab18:12:31

If I have a function with an arity of 0, whats the idiomatic way to call that function 10 times and put it into an array? Right now I have (map (fn [_] arity-zero-fn) (range 10))

cab18:12:09

ha, perfect! thanks

cab18:12:11

awesome :) (take 10 (repeatedly arity-zero-fn))

roelof18:12:47

im stuck at exercise 3 of the brave book

roelof18:12:53

my code looks like this

roelof18:12:14

(defn matching-part
  [part replacement]
  {:name (clojure.string/replace (:name part) #"^left-" replacement)
   :size (:size part)})

(defn symmetrize-body-parts
  "Expects a seq of maps that have a :name and :size"
  [asym-body-parts]
  (reduce  (fn [final-body-parts part]
            (into final-body-parts (set [part (matching-part part "right1-") (matching-part part "right2-")   ])))
          []
          asym-body-parts))

roelof18:12:32

but when I run it I see a null pointer exception

roelof18:12:50

anyone who can give me a tip where the error is

cab18:12:50

what does the compiler say?

roelof18:12:47

@cab: when i fire up a repl in cursive. I see this message ;

roelof18:12:54

#error {
 :cause nil
 :via
 [{:type clojure.lang.Compiler$CompilerException
   :message java.lang.NullPointerException, compiling:(do_things/core.clj:62:1)
   :at [clojure.lang.Compiler load Compiler.java 7239]}
  {:type java.lang.NullPointerException
   :message nil
   :at [clojure.string$replace invoke string.clj 99]}]

roelof18:12:40

and line 62 is this one ; (symmetrize-body-parts {:name "left-ear" :size 1} )

cab18:12:03

notice "Expects a seq of maps that have a :name and :size”

cab18:12:15

so you need to do (symmetrize-body-parts [{:name "left-ear" :size 1} ])

roelof18:12:20

oke, now it works. I think I need a break one more time

roelof18:12:05

tomorrow I will work on the last one of that chapter

roelof18:12:05

I have to change the code so it works on all numbers not just a fixed number

rantingbob18:12:27

On a random note, I totally don't get errors like that in my Clojure repl

rantingbob18:12:44

are you using a beta version or has there been an update?

cab18:12:47

in EDN, you mean?

roelof18:12:55

@rantingbob: moment i have to find out how I can check which version I use

roelof18:12:04

I thought the latest

roelof18:12:06

Found it, I use 0.1.172-15 @rantingbob

rantingbob18:12:25

I'll check what version I'm on once I get home

roelof18:12:18

oke, I will be away for some time. Sporting to do till 21:30. and it's now 19:41

roelof20:12:15

@cab : what do you mean with EDN ?

cab20:12:13

that error’s data format (and clojure is a superset of edn)

roelof20:12:11

oke, no idea. I have not learned edn with 4clojure and/or the brave book

cab20:12:35

its roughly json : javascript :: edn : clojure

roelof20:12:14

oke, json I have worked a some time when I tried node.js

roelof20:12:26

I think I will learn edn on my learning journey of clojure

roelof20:12:43

and otherwise I do not learn it

roelof20:12:27

First priority : doing the easy challenges of 4clojure and doing all the exercises of the brave book

roelof20:12:40

and maybe later learn Om or react

Tim21:12:04

I think edn is pretty easy to learn if familiar with clojure maps

drewverlee23:12:43

can someone explain what a logic list is? From http://insideclojure.org/2015/01/02/sequences/ (and probably 2 other places I have seen). What is the underlying data structure?

cab23:12:26

i think they mean it isn’t a concrete implementation

noonian23:12:49

well, you don’t have to care what the concrete implementation is

drewverlee23:12:54

so it I can expect it to behave a certain way and it doesn't help me to understand how it does that? (at least at a novice level). errr, meaning at this point, when im just learning the language, its sufficient to know the behavior .

noonian23:12:02

Any sequence will behave the same way for the sequence api functions. There are other functions that take seqs but do different things depending on the implementaton, like conj. In cases where you care you will often “dump" a sequence into a concrete implementation like a vector: (into [] (map inc [1 2 3]))

noonian23:12:47

and there are versions of map and filter that always return a vector ‘mapv’ and ‘filterv'

noonian23:12:22

so in that article, first, rest, next, and cons don’t care about concrete implementation

drewverlee23:12:11

@noonian: thanks, that helps a lot.

noonian23:12:29

@drewverlee: np, glad I could help!