Fork me on GitHub
#beginners
<
2020-03-14
>
acecraft9901:03:05

(defn eval-not

  [input]

 (cond

(and (seq? (second input)) (= 'and (first (second input)))) ;(do x here which -> (or (not x) (not y))
))
If the user types in: (eval-not '(not (and x y))), is there a way to return (or (not x) (not y)) Without using macros and without changing the style of code I have already written above. I asked this question before, but I was not very specific as to what I was asking. I hope this question is better written.

smith.adriane01:03:27

is there any particular reason the style of the code can’t be changed?

jason35801:03:57

@ yes there is: it's a homework assignment πŸ™‚

acecraft9903:03:36

Well. I created the homework assignment and I did any other functions in the same format. Would appreciate any advice :)

dpsutton03:03:47

(defn demorgan
  [form]
  (cond
    (atom? form)
    form

    (and (= 'not (first form))
         (sequential? (second form))
         (= 'and (first (second form))))
    (let [[_ [_ & terms]] form]
      (list* 'or (map (comp #(list 'not %) demorgan) terms)))

    :else
    form))

dpsutton03:03:08

(demorgan '(not (and x y)))
(demorgan '(not (and (not (and x y)) z)))

jr0cket16:03:06

I am sure there is a function to convert the following collection of albums to be grouped by artists instead, or is this in need of a reducing function?

(def music-collection
  [{:album-name "Tubular Bells" :artist "Mike Oldfield"}
   {:album-name "Smells like teen spirit" :artist "Nirvana"}
   {:album-name "Vision Thing" :artist "Sisters of Mercy"}
   {:album-name "Here comes the war" :artist "New Model Army"}
   {:album-name "Thunder & Consolation" :artist "New Model Army"}])
So the results would look like
{"Mike Oldfield"    ["Tubular Bells"]
 "Nirvana"          ["Smells like teen spirit"]
 "Sisters of Mercy" ["Vision Thing"]
 "New Model Army"   ["Here comes the war" "Thunder & Consolation"]}

jr0cket16:03:06

I am sure there is a function to convert the following collection of albums to be grouped by artists instead, or is this in need of a reducing function?

(def music-collection
  [{:album-name "Tubular Bells" :artist "Mike Oldfield"}
   {:album-name "Smells like teen spirit" :artist "Nirvana"}
   {:album-name "Vision Thing" :artist "Sisters of Mercy"}
   {:album-name "Here comes the war" :artist "New Model Army"}
   {:album-name "Thunder & Consolation" :artist "New Model Army"}])
So the results would look like
{"Mike Oldfield"    ["Tubular Bells"]
 "Nirvana"          ["Smells like teen spirit"]
 "Sisters of Mercy" ["Vision Thing"]
 "New Model Army"   ["Here comes the war" "Thunder & Consolation"]}

mark54016:03:05

I suggest trying a group-by followed by a map to convert the values to a vector.

jr0cket16:03:25

I tried group-by after I partitioned it and made a mess πŸ™‚ group-by :artist music-collection on its own does a better job, although its not quite the right shape and artist details repeated. An anonymous function with group-by should fix it I think

jr0cket16:03:50

This loop-recur does what I was looking for, but its so much code πŸ™‚

(loop [albums    music-collection
       by-artist {}]
  (let [album (first albums)]
    (if (empty? albums)
      by-artist
      (recur (rest albums)
             (update by-artist
                     (keyword (:artist album))
                     conj (:album-name album))))))

jr0cket17:03:00

hmm, loop-recur is the only approach that works so far 😞

bredov17:03:45

As mentioned above you could try something like that

(reduce-kv (fn [m k v] (assoc m k (map :album-name v)))
           {}
           (group-by :artist music-collection))

eagonmeng18:03:30

The above works great, also if you wanted to do it using purely sequence function (and for example if you don't remember reduce-kv's syntax off the top of your head)

(defn artist->albums
  [coll]
  (->> coll
       (group-by :artist)
       (map (fn [[k v]]
              [k (mapv :album-name v)]))
       (into {})))

mark54018:03:18

^^ is good and here's the same thing using a transducer instead of ->>.

(into {}
    (map (fn [[k v]]
           [k (mapv :album-name v)]))
    (group-by :artist music-collection))

luis.cairampoma11916:03:12

Any form to express it more short and intuitive?

luis.cairampoma11916:03:05

maybe without necessity to use the function int-or-nothing

lockdown-17:03:50

That if-let global is bad

luis.cairampoma11917:03:57

Is just an example

luis.cairampoma11917:03:12

if-let is in a function

bfabry17:03:33

probably cond-> by the looks

bfabry17:03:11

wait you only have a single condition there

luis.cairampoma11917:03:09

yes, I just want to corroborate if this difference is greater than 0, and asign this value to a variable

bfabry17:03:10

(let [diff (- ...)]
  (when (> diff 0)
    (str diff)))

bfabry17:03:11

btw it's generally considered bad-form to use if-let and if without else branches. if you have no else branch use when and when-let

luis.cairampoma11917:03:43

Thank you for that!

bfabry17:03:50

no worries

mark54018:03:22

@ if you don't mind, please post text instead of images, much easier to read for me anyway. To get syntax coloring you can post a snippet with Ctrl-Shift-Enter and select Clojure for the Type.

nate_clojurians20:03:43

I might make that a ms-until function, so like (ms-until unix-time) where returning nil means it's in the past