Fork me on GitHub
#beginners
<
2022-12-12
>
Vernon05:12:33

For people totally new to functional programing and Clojure, I found the following book to be quite helpful. • Functional Thinking: Paradigm Over Syntax, by Neal Ford

popeye15:12:02

When I tried to write the file in csv

(csv/write-csv writer  ["Edward Cullen 12" "Edward Cullen 10" "Jacob Black 3" "Carlisle Cullen 6"])))

Why does it writing in below way
E,d,w,a,r,d, ,C,u,l,l,e,n, ,1,2
E,d,w,a,r,d, ,C,u,l,l,e,n, ,1,0
J,a,c,o,b, ,B,l,a,c,k, ,3
C,a,r,l,i,s,l,e, ,C,u,l,l,e,n, ,6

ghadi15:12:01

write-csv needs a collection of collections, and you are providing a single coll

respatialized15:12:49

the default CSV writer assumes each element of the vector you're trying to write is a sequence of cell values. Because strings can be treated sequentially, it writes each character to its own cell. If you want to write a single-column CSV, you should put each row in its own vector like:

[["Edward Cullen 12"] ["Edward Cullen 10"] ["Jacob Black 3"] ["Carlisle Cullen 6"]]

respatialized15:12:48

but I'm guessing you want two columns, which would be more like:

[["Edward Cullen" "12"] ["Edward Cullen" "10"] ["Jacob Black" "3"] ["Carlisle Cullen" "6"]]

popeye15:12:17

got it, Thanks

popeye15:12:09

It is printing with double quote

"Edward Cullen,12"
"Edward Cullen,10"
"Jacob Black,3"
"Carlisle Cullen,6"

Brian Marco16:12:29

If you put the comma inside the string it will print as you've described because a comma inside the string puts the comma inside the cell

(csv/write-csv writer 
 [["Edward Cullen, 12"] 
  ["Edward Cullen, 10"] 
  ["Jacob Black, 3"] 
  ["Carlisle Cullen, 6"]])
Instead, you can put a comma between strings (each new string is a cell)
(csv/write-csv writer 
 [["Edward Cullen", "12"]
  ["Edward Cullen", "10"]
  ["Jacob Black", "3"]
  ["Carlisle Cullen", "6"]])
but the commas are optional and treated as whitespace by the clojure interpreter so this also works
(csv/write-csv writer 
 [["Edward Cullen" "12"]
  ["Edward Cullen" "10"]
  ["Jacob Black" "3"]
  ["Carlisle Cullen" "6"]])

👀 1
🙌 1
Brian Marco16:12:41

The most clojuresque way of doing it would also leave the numbers without quotes since the csv writer will serialize numbers automatically

(csv/write-csv writer 
 [["Edward Cullen"  12]
  ["Edward Cullen"  10]
  ["Jacob Black"     3]
  ["Carlisle Cullen" 6]])

1
George16:12:27

I'm trying to track down why some html isn't updating on page reload, but it's a little complicated for me so would appreciate some help. I have a Compojure route "/" that calls index, which calls a hiccup (page/html5 ...)-- in that is a div,

[:div#result
                (if (get-in request [:session :identity])
                  (str (get-in request [:session :identity]))
                  "Not authorized")]
I have a login and a logout route which assoc's and dissoc's the :identity key into the :session map. That all seems to work, since I have a println at the top of index that shows me the :session map. The logout handler is
(defn logout [request]
  (-> (redirect "/")
      (assoc :session (dissoc (request :session) :identity))))
When that's called it does remove :identity from the :session map, but the result div on the index page doesn't update to "Not authorized" until I manually refresh the page. The redirect does trigger a new GET request which I see in the browser dev tools. Is this a hiccup thing where the html is compiled or something until I manually refresh?

George16:12:42

the funny thing is I see that :identity is gone from the :session map when the redirect runs, but the result div stays the same.

Brian Marco17:12:35

seems like it might be a caching issue. Try using a minimal set of middleware to reproduce the problem

George23:12:38

thanks, yeah there is some stale cache. I don't have much middleware atm,

(def app
  (-> #'app-routes
      (wrap-authentication backend)
      (wrap-defaults site-defaults)))

George23:12:55

the really odd thing is that if I view source on the page, the div element has the correct string in it

George23:12:02

but the rendered page is stale

George23:12:23

and if I look in the dev tools response, it shows the correct string as rendered html...just not in the FIrefox page

George23:12:50

the response that is of the GET request when I hit the logout button

skylize17:12:16

How do I check if a value is in a collection, including if that value is false or nil?

(let [m [:foo nil :bar]
      x nil]
   (pred m x))
; => true

(let [m [:foo :bar]
      x nil]
   (pred m x))
; => false

popeye17:12:12

(some nil? [4 5 nil 6])

popeye17:12:50

(some false? [ 4 5 false 7])

skylize17:12:24

That works. Thx

skylize17:12:21

Pretty annoying though to still need to check each of nil and false separately from the rest of all possible values.

popeye17:12:12

are you looking for something like (some (or nil? false?) [ 4 5 nil 6])

Alex Shulgin17:12:46

something with :not-found as sentinel?

Alex Shulgin17:12:28

e.g. (if-not (= :not-found (get m k :not-found)) ...)

skylize17:12:41

I'm building very generic test generators. nil and false are possible values (probable values due to the way generators "grow") that I should expect to deal with, whether or not the consuming test chooses to take advantage of that.

(let [m [:foo nil :bar]
        x some-value-which-could-be-nil-false
   (pred m x))

Alex Shulgin17:12:53

it's more tricky with (some #{nil} [0 nil 1]) , because that gives you nil either way 🙂

skylize17:12:07

yeah exactly. 😄

skylize17:12:43

And actually I think #{nil} set will fail as a function call.

Alex Shulgin17:12:46

the collection is completely generic sequence?

Alex Shulgin17:12:15

#{nil} is totally fine

skylize18:12:41

I'm making generators to generate functions. User gives a generator to make input value(s), a generator to make output value(s), (depending one or the other of those might depend on the generated results of the other), and in this variation a generator for how many input-output pairs to match each other. Super generic. I'm trying to use the input value(s) as a key to the corresponding return value for the generated function.

skylize18:12:31

I need to know for sure if the input value exists regardless if it is nullable.

Alex Shulgin18:12:05

if it doesn't have to be super-efficient, you can just walk the sequence linearly until you find the element that is = to the one you're looking for?

👍 1
skylize18:12:33

Yeah. That's a reasonable enough option.

pavlosmelissinos18:12:07

(let [m [:foo nil :bar false]
      x nil]
    (some #(= x %) m))
I think this should work but I'm pretty sure it's O(n) edit: Wrap it with boolean to get a boolean result

Alex Shulgin18:12:10

if you don't know the collection's type it's gonna be O(n) either way

👍 1
skylize18:12:18

Yeah. I think that's what I was looking for. The collection will be a seq or vector, which will be zipmapped as keys to another seq/vec of values. Then the search is done on the original key seq. So I don't think I'm likely to outperform that without going SuperNerd on the problem.

Chris G21:12:55

would some-fn help in this regard?

Chris G22:12:41

((some-fn false? nil?) coll)

Chris G22:12:40

oh hmm i dont think it would

Miķelis Vindavs06:12:23

with sets, you can use contains? to avoid the falsy problem (contains? #{nil} nil) will be true and be faster than linear iteration (i.e some) for large sets

👍 2
Alex Shulgin08:12:21

for a generic seqable collection this is the way to go: (some #(= x %) coll)

👍 1
George23:12:49

I have a weird issue here I haven't seen before -- what does it mean if the html rendered on a web browser page has a dynamically rendered string, call it "foo", but if you view source, and view the response part of the GET in browser dev tools, both of those show "bar". In this case "bar" is correct.

phill00:12:23

I don't know. But the cache-control header (served by your web server) can declare circumstances under which the browser can use an outdated, cached version of the page (which says "foo") while it is busy fetching a new version of the page (which says "bar"). Perhaps that's what you are seeing?

George00:12:10

yeah I was wondering the same thing...in this case though cache-control of the request is Cache-Control: no-cache

George00:12:25

I wonder if I need to set that in the response header?

George01:12:01

unfortunately that doesn't work

George01:12:43

ohh...I bet this is because the get request is done by js/fetch -- not sure of the solution yet though

George02:12:22

I'll just punt on this for now and change the div with JS after the fetch runs

George23:12:23

When I manually refresh the page again, the rendered html shows "bar"