Fork me on GitHub
#beginners
<
2017-05-08
>
crvst11:05:34

Hello, how efficiently update the table-like atomic data like this?

(def table [["Letter" "Number"]
                 ["Aleph" 1]
                 ["Bet" 1]
                 ["Gimel" 2]
                 ["Dalet" 3]
                 ["He" 5]
                 ["Vav" 8]
                 ["Zayin" 13]
                 ["Het" 21]])

crvst11:05:54

Let’s say I’m editing a cell containing "Aleph", how to swap it a parent atom?

curlyfry12:05:58

@crvst Since the data is a vector of vectors you'd have to access the element by indices

curlyfry12:05:07

(assoc-in table [1 0] "No longer called Aleph")

curlyfry12:05:32

Or if the table is contained in an atom that you want to swap: (swap! table-atom (fn [table] (assoc-in table [1 0] "No longer called Aleph")))

crvst14:05:04

@curlyfry Thank you. What is the idiomatic way to keep meta-data like vector indices within React component? Or is there any way to get bounded data?

Rachel Westmacott14:05:37

you might even get away with (swap! table-atom assoc-in [1 0] "No longer called Aleph")

crvst14:05:05

Since I need to store somewhere the metadata, how should I get the index in for?

crvst14:05:53

(for [item (rest @table)]
          [cell i])

crvst14:05:07

cell here is a Reagent component

curlyfry14:05:01

@crvst I'm not sure if I know exactly what you want to do, but maybe map-indexed works?

crvst14:05:49

I want to implement primitive spreadsheet

crvst14:05:26

Great, I will take a look at map-indexed

crvst14:05:40

Yes, @curlyfry! It’s excactly what I looked for

noisesmith17:05:30

@vitruvia (phrase) calls phrase with no args, as if it were a function

noisesmith17:05:08

the two errors here are using a vector containing a string as if it were a string, and calling a vector as if it were a function

noisesmith17:05:13

@vitruvia if you are familiar with algol family languages like c/js/java/c# etc. calling (f) in clojure is like calling f() in one of those - it’s just moving the paren to the left

vitruvia17:05:58

I'm not =( Actually I've solved all the exercises on the koans, but now I'm trying to solve stuff on exercism and I found I've forgotten much of the syntax

noisesmith17:05:37

@vitruvia OK - just remember that (f) calls f - parens are not just for grouping, and in code that gets compiled, it needs a function

noisesmith17:05:43

(or a method etc.)

noisesmith17:05:26

you might see something like '(1 2 3) in examples, the ' prevents evaluation so returns a literal list of the form

vitruvia17:05:45

solved it =]

crvst17:05:07

Guys, how to swap nested collection? Something like this #(swap! atom-coll assoc-in [y x] value)

crvst17:05:11

But the vectors inside atom is in a lazy-seq, so before assoc-in I need to get the vector istelf

crvst17:05:14

So, the structure is something like #<Atom: ([0 [1 2]] [1 [3 4]])>, etc.

john17:05:10

lists and vectors are both associative via their index. So y above, I believe, would index first into your list. x would then index into one of the vectors.

crvst17:05:02

So, the assoc-in should work well for a lazy list too?

crvst17:05:41

Now I have the error for this: No protocol method IAssociative.-assoc defined for type cljs.core/LazySeq

crvst17:05:27

This is a Clojurescript environment

noisesmith17:05:52

assoc-in does not work with non-associative collections

noisesmith17:05:01

vectors are associative, lazy-seqs are not

john17:05:07

ah, I'm a liar.

john17:05:57

you can use an update and break it apart in the function.

crvst18:05:18

Got it, thank you!

Drew Verlee19:05:43

Any suggestions how how i can pass the cond condtionals in at run time?

(defn describe-number [n]
  (cond-> []
    (odd? n) (conj "odd")
    (even? n) (conj "even")
    (zero? n) (conj "zero")
    (pos? n) (conj "positive")))
to something like
(defn describe-number [n conditionals]
  (cond-> [] conditionals))

(describe-number 5 ...)
I want to be able to change them at run time. I feel like could use macros todo this, but i’m woundering if there isn’t a simpler way to achieve the sam functionality?

noisesmith19:05:50

sounds like something you could do with a reduce over a hash-map mapping conditional to data

noisesmith19:05:56

something like (reduce (fn [description [pred? s]] (if (pred? o) (conj description s) description)) [] {odd? "odd" …})

noisesmith19:05:08

where o is your n

john20:05:02

But cond-> is a macro, so no. The form you give it must adhere to the defined structure, at compile time, not runtime.

john20:05:28

Oh, I didn't see what you wrote below that. Yeah, you could probably create a macro that does that. Sounds hairy though.

Drew Verlee20:05:29

@john I was thinking this might be the case. I starting to wonder if its wiser to not go looking farther then reduce for many tasks. Macros seems to introduce a lot of the same complaints i have about other langauges in terms of their inflexability, or i’m thinking about this wrong?

Drew Verlee20:05:33

I suppose i should go look at the implementation of cond->

john20:05:12

Right, macros have compile time / runtime constraints common to complaints found in other languages. We're only spoiled about it though because almost everything can be passed around transparently in Clojure. And the downsides of macros are offset by the fact that they can produce entirely new syntaxes that aren't possible in some other languages.

john20:05:16

In my experience, macros are mostly for adding sugar to what already works. Build something that works first, then use macros to sugar over part of that, only when necessary. Often times you don't even need them.

mobileink20:05:40

otoh, the nice thing about sugar is the sweetness. describe-nbr-> could be a variant of cond-> . it's all about trade-offs - sometimes a macro can make code much more legible, even if strictly speaking you could get away without it.

mobileink20:05:32

for example cond-> . not to mention all the other threading macros. 100% sucrose.

noisesmith20:05:46

the form on line 5 is a no-op

noisesmith20:05:59

it can’t possibly do anything

noisesmith20:05:20

perhaps you want to test two conditions in one form? cond is good for that

vitruvia20:05:09

I just want to test if phrase ends with "?"

vitruvia20:05:16

but the condition worked on its own

noisesmith20:05:21

you test that, then return a value that nothing consumes

noisesmith20:05:34

“Sure” is returned and thrown away, the form might as well not exist

vitruvia20:05:44

how do I return it?

noisesmith20:05:53

by putting it in the last form in the function

noisesmith20:05:08

eg. with cond you can test multiple conditions, and have a separate return value for each one

vitruvia20:05:56

so the only way to make a function with multiple conditions is by using a switch case statement? (in this case cond)

mobileink20:05:06

@john common advice is to not use macros unless you cannot avoid it, or something like that. but i think better advice is, to paraphrase Samuel Beckett, "Never use a macro unless it is absolutely necessary or convenient to do so."

noisesmith20:05:15

@vitruvia right case works if you can dispatch on a single value, cond works if you have a different test for each result, and nested if technically works but that’s what cond does anyway so just use cond

vitruvia20:05:39

alright, thanks!

noisesmith20:05:26

also, in case you don’t know yet, you can find documentation for all these nice functions and macros in the repl

> (doc cond)
-------------------------
clojure.core/cond
([& clauses])
Macro
  Takes a set of test/expr pairs. It evaluates each test one at a
  time.  If a test returns logical true, cond evaluates and returns
  the value of the corresponding expr and doesn't evaluate any of the
  other tests or exprs. (cond) returns nil.
nil

john20:05:16

@mobileink agreed. sweetness in moderation. 🙂

mobileink20:05:32

the black arts are strong magic - very useful but very dangerous in the wrong hands. 😉

josh.freckleton22:05:19

lein test works, but lein test-refresh fails to find an import (that it doesn't need for tests)