Fork me on GitHub
#beginners
<
2020-02-07
>
hindol.adhya03:02:17

Expanding on Alex's idea, this would be the way to un-interleave,

(defn distribute
  [n coll]
  (apply map vector (partition n coll)))

(distribute 3 [1 2 3 4 5 6 7 8 9]) ; => ([1 4 7] [2 5 8] [3 6 9])
@bfabry

bfabry03:02:03

Distribute is a great name. Also now I think about it, "deal", like dealing cards

hindol.adhya03:02:04

Yes, it is exactly like dealing cards, 🙂. You have given a nice little mental exercise. With the apply map trick, I am killing the lazyness. Now I am wondering what would be the way to distribute while preserving the potential lazyness of the incoming collection. EDIT: Andy's solution with map and take-nth is lazy. Perhaps there is a solution with partition as well.

heefoo04:02:05

I strugle to create a class with gen-class and i have problem to override the toString method

heefoo04:02:14

(ns example
 (:gen-class
   :name         test.override
   :methods      [ ^{Override {}} [toString [] String]]
   :state        state
   :init         init
   :constructors {[String] []}))
(defn -init
  [name_]
  [[] (atom name_)])
(defn -toString [this]
  (deref (.state this)))

heefoo04:02:42

gives

Caused by: java.lang.ClassFormatError: Duplicate method name "toString" with signature "()Ljava.lang.String;" in class file test/override

heefoo04:02:57

any incites why this happens ?

seancorfield05:02:18

:methods [[ ^{Override {}} toString [] String ]]

heefoo06:02:23

@seancorfield indeed, but this was after experimentation

heefoo06:02:30

i moved it to

:methods      [[^{Override {}}  toString [] String]]   

heefoo06:02:03

I created another ns with content

(ns override-test.simpleClass
   (:gen-class
     :name         simpleClass
     :methods      [[^{Override {}}  toString [] String]]
     :state        state
     :init         init
     :constructors {[String] []}))

(defn -init
  [name_]
  [[] (atom name_)])


(defn -toString [this]
  (deref (.state this)))



#_(simpleClass. "test")

heefoo06:02:32

and evaluating (simpleClass "test") gives the same error

heefoo12:02:51

@seancorfield it seems that the problem was that toString seems to be already implemented by virtue of the automatic subclassing mechanism of gen-class. Probably Ljava.lang. String is treated as a (?) superclass and toString is added automatically, so i just had to remove it from :methods.

seancorfield17:02:12

Saw your updates on S.O. -- I read that in the docs and sort of assumed you'd tried that first before adding the Override annotation. Sorry, I should have asked that question first.

heefoo06:02:48

and the problem  persists

heefoo06:02:32

I don't write java but it seems that it should have worked even without the annotation. Could it be a bug ?

isaacballone06:02:10

When someone gets a chance, I was wondering if I did this correctly:

(def input
  [{:name :isaac :value ["pencil", "pen"]}
   {:name :brian :value ["eraser", "cat"]}])

(reduce
  #(assoc %1 (:name %2) (:value %2)) {} input)

; Output
; {:isaac ["pencil" "pen"], :brian ["eraser" "cat"]}
So the input and the output are exactly what I want, the thing I'm not sure about was how I did it. Am I right to use reduce? Also since maps are immutable, is it inefficient to have a new one made every time? Also theoretically, would it be bad to have large map used to keep track of a state that is constantly changing?

seancorfield06:02:43

@isaacballone Clojure's data structures are designed for that usage and are very efficient.

seancorfield06:02:27

That transform looks like a very reasonable way to get from your input to your output.

seancorfield06:02:51

Just bear in mind that if you have two hash maps in your input that have the same :name then the later one will overwrite the earlier one(s).

isaacballone06:02:48

Okay. I originally used let to make a variable and had a for loop doing assoc on it, but I was probably doomed from the start from that approach, right? Since it's immutable anyway, it's not a reference I can write to, and it returns a new one with assoc

seancorfield06:02:51

The vectors for the :value keys will be shared between the input and the output.

seancorfield06:02:49

Here's an alternative for you to ponder: (into {} (map (juxt :name :value) input))

isaacballone06:02:49

Oh okay, that makes sense too. I hadn't thought about that

isaacballone06:02:16

Oh boy slapping some black magic at me. I'll have to read the docs on those functions lol

hindol.adhya10:02:52

😁 (juxt f g) returns a function that, when executed, will return [(f %) (g %)]. Very very handy. We know keywords are functions. So, (:key {:key "value"}) => "value" . So, ((juxt :name :value) arg) is actually [(:name arg) (:value arg)].

hindol.adhya11:02:09

If you are curious about into, I think it is exactly same as reducing over a collection and supplying an init collection, the way you did it. Choose whatever looks better.

isaacballone06:02:50

Thanks for your help! I really appreciate it

christian.paling11:02:55

Hi guys, it is not possible to do with-redef inside a test on something from Java, is it?

christian.paling11:02:59

In one of my tests I’m testing erroneous environment variables for the configuration of the application

christian.paling11:02:52

So inside the test I’m trying to do: with-redefs [System/getenv something-else] …

christian.paling11:02:27

However, I always get Unable to resolve var: System/getenv in this context

jysandy12:02:20

with-redefs only operates on vars. A heavily simplified explanation of a var is basically anything defined using def or defn. This means that with-redefs will not work on Java methods such as System/getenv. You'll have to resort to other means of stubbing environment variables.

jysandy12:02:49

One possible solution is to wrap System/getenv in a Clojure function, which can then be swapped out using with-redefs.

christian.paling13:02:22

@ Thank you! Yes, that’s what I did for now, I just wrapped it using a clojure function

kamuela12:02:19

Does leiningen manage its own JDK?

finn.volkel12:02:38

Probably a better question for #leiningen. I don't know about the jdk, but clojure dependencies are completely seperated from your own project, except maybe if you use a leiningen plugin.

delaguardo12:02:02

No, leiningen uses JDK configured for shell session export JAVA_CMD="${JAVA_CMD:-"java"}" taken from lein bin script

kevin.van.rooijen13:02:34

Is there a way to define the existence of a function in a namespace? e.g. I have a defn that refers a 2nd defn, but the 2nd defn hasn't been defined yet.

didibus18:02:16

Try to minimize your use of declare. And instead move your defns in their dependency order. Defns that use another must appear after in the namespace.

kevin.van.rooijen17:02:37

The problem is that I have a tree-like structure, with banches and nodes that can have new branches. So it's inheritedly recursive. I can't really think of a way to solve this differently at the moment.

didibus17:02:38

Mutually recursive things is normally the good use case for declare.

didibus17:02:59

But in a data-structure, have you considered using keywords instead of symbols?

kevin.van.rooijen13:02:38

declare is what I'm looking for, nevermind