Fork me on GitHub
#beginners
<
2019-01-20
>
simesy00:01:03

not sure how to ask.Can i get stuff out of dotimes? simplistic example…

(defn something
    [count]
    (dotimes [n count]
      ; do something with a side effect
      (+ total-ran 1)
    ("Total: " total-ran)
so that
(something 5)
-> "Total: 5"

kingmob01:01:52

@simon223 If you look at the dotimes macro (https://github.com/clojure/clojure/blob/clojure-1.9.0/src/clj/clojure/core.clj#L3305), you can see the body of the loop is a when that always ends in a recur call, so it’ll always return nil when the iterations are done. dotimes is primarily for side effects. If you want to just return the number of iterations, you can do that from the count var, but that’s not very useful, assuming not every iteration has a side effect. What you might want is something like this:

(defn something
  [count]
  (loop [n count
         total-ran 0]
    (if (< n 0)
      (str "Total: " total-ran) ; return final result
      (if (even? n) ; some test to determine whether to do something
        (do
          (println "Did something with" n)
          (recur (dec n) (inc total-ran)))
        (recur (dec n) total-ran)))))

simesy02:01:40

@kingmob thankyou!

kingmob03:01:10

Happy to help. Feel free to reach out if you have any other questions

simesy04:01:42

is a binding basically a pointer/reference?

seancorfield04:01:52

A binding gives a name to a value. Each time you recur you give the same names to new values.

seancorfield04:01:12

A top-level name, bound with def (or defn) is more like a pointer/reference since a Var is created -- the name is bound to the Var and the Var "contains" the value. And you can alter what the Var contains (`alter-var-root`, for example, or just calling def again).

simesy06:01:05

thanks @U04V70XH6 and @kingmob i got what i needed with something like:

(defn do-stuff [total]
    (loop [results []]
      (if (= (count results) total)
        (results})
        (do
          (let [new-thing (do-something)]
            (recur (conj results new-thing))))...

seancorfield06:01:43

(take total (repeatedly #(do-something))) should be about the same.

N/A04:01:19

is there a type of prettier for clojurescript? where on save the file reformats automatically like this: https://github.com/prettier/prettier

soulflyer05:01:34

emacs with clojure-mode and aggressive-indent?

N/A06:01:01

Thank you!

Karol Wójcik13:01:03

How can I destructure extra_info keys from the map?

{
  :categories ["A"]
  :attributes {
      :tags ["tag1"] 
      :unit_price "1"
      :extra_info {
         :neutrient_elements ["elem1"]
      }
  }
}

I tried something like
[{:keys [categories] :as product
    {:keys [tags unit_price] :as attributes} :attributes
    {:keys [nutrient_elements] :as extra_info} [:attributes :extra_info]}]
and it seems to work for attributes but does not destructure the extra_info 😞

yuhan15:01:55

you'll have to destructure it inside your attributes map

yuhan15:01:18

[{:keys [categories] :as product
  {:keys [unit-price tags] :as attributes
   {:keys [nutrient-elements] :as extra-info} :extra-info} :attributes}]

yuhan15:01:03

but at this level of nesting it's probably more readable to use get-in than use destructuring

simesy15:01:28

if i have [{:type "cat" :age 5}, {:type "dog" :b 6}] how can i get a list like ("cat", "dog")?

simesy15:01:24

a little uncertain about my square/round brackets there, but my squigglies are definite 😅

eggsyntax17:01:46

Bit of feedback on the above, just for context: You can express it either as a [vector] or a '(list) (note the quote so that it doesn’t try to interpret (list) as a function). Either works equally well in this case; it seems to be more common to use vectors for literals. They have different performance characteristics, but those aren’t going to matter unless you’re dealing with a large number of elements. One way to think about it is that they’re both sequences (ie fulfill the sequence interface), and a ton of functions in Clojure operate on sequences, without caring what the concrete type is.

simesy17:01:14

@U077BEWNQ the “sequence interface” makes sense, I generally keep forgetting what’s what after i google it 😛

Karol Wójcik15:01:07

Thank you @qythium

yuhan15:01:42

(map :type <your list>)

simesy15:01:02

ah i was close with map.. thanks!

simesy16:01:20

map is clearly where I need to get my skates on

simesy16:01:02

maybe i mean transducers

Oliver Marshall16:01:28

@simon223 If you're just starting out you'll probably have a better time focusing on the classics like map, filter and friends before moving on to transducers

simesy17:01:24

Definitely starting out… sooo. i feel bad i couldn’t work this out, because it feels simple… but i’ve got beginners amnesty? Trying to turn:

{:First "foo", :Second "bar"}
into
{:First
  [:eq "foo"]
 :Second
  [:eq "bar"]}
My latest non-working example.
output ((fn [[k v]] [:eq v]) (into [] input))]
im just not quite getting how to process/transform items in a map 😕

simesy17:01:11

ok i think i’m … close

Oliver Marshall17:01:39

I PM'd you if you still need help btw 🙂

rakyi17:01:15

you can use map or for with into {} or reduce-kv

rakyi17:01:20

(into {} (for [[k v] {:First "foo", :Second "bar"}] [k [:eq v]]))

rakyi17:01:14

there are also utility libraries which implement map-vals for mapping over values in a map, which clojure doesn’t have built in

rakyi17:01:07

do you understand why your example doesn’t work?

simesy17:01:04

ah i got similar.. yeah i did mostly understand why my examples weren’t working from the errors.

simesy17:01:22

I got

output (into {} (for [[k v] input] [k [:eq v]]))]

yuhan17:01:29

have a look at update also (edit: oops, misread the question)

simesy17:01:29

looks same?

simesy17:01:10

that ended up as simple as i hoped 😄

tim19:01:59

you can also use reduce and be lazy: (reduce #(assoc %1 (first %2) [:eq (last %2)]) {} {:First "foo", :Second "bar"})

Lennart Buit19:01:31

(you can do code formatting with backticks (` ), how to escape backticks is beyond me for now)

tim19:01:29

k, thnx.. can u edit messages?

Lennart Buit19:01:04

yes, to the right is a menu with three dots

Lennart Buit19:01:29

OR, when it is the last message you wrote, you can simply press arrow up

tim19:01:02

ok, thnx

simesy20:01:28

@tim792 nice thanks