Fork me on GitHub
#beginners
<
2019-08-09
>
zhuxun200:08:47

Hey guys, if I were to write a wrapper function (g) for another function (f), so that (g x y z) is (f "hello" x y z), how should I write it?

zhuxun200:08:48

Currently, I'm doing (defn g [& args] (apply f (concat ["hello"] args)))

Toby Clemson00:08:46

apply has many signatures such that there's no need to (concat ["hello"] args)

Toby Clemson00:08:10

Instead you can just say (apply f "hello" args)

Toby Clemson00:08:48

Separately, it might be cleaner to do something like: (def g (partial f "hello")

👍 8
zhuxun200:08:00

Is that the idiomatic way?

zhuxun200:08:21

To be clear, I want g to always insert a constant "hello" at the first position of the f call, regardless of the number of arguments.

sova-soars-the-sora00:08:48

Can I get an opinion? Making a magazine site. There's subscriptions. You gotta pay $5 to read some of the locked material. With locked material, I have a cljs app basically say "hey it's locked" and if you have credentials or session data, it makes an ajax request for the article. Any tips of how to make this robust?

noisesmith17:08:05

The robustness is in the ability to differentiate a customer that has paid for a resource from one that hasn't. A small jwt id in a cookie or token is one way to do this (simple data, plus verification you set this data, which at least prevents js based hacks)

noisesmith17:08:39

let them use jwt to prove who they are, then use that id to verify with your db which resources they have access to, etc.

bfabry01:08:36

(def g #(apply f "hello" %&)) is how I’d write that @zhuxun2

👍 8
Anik Chowhdury03:08:17

I have used future for multhreading in core-async. Here is the screenshot of my code and error message. I got null pointer exception for using future. If i use just

(async/thread-call (process-data-chan))
instead of
(future (async/thread-call (process-data-chan)))
i dont get any null pointer exception. Can anyone explain me and give me solution about this? I am newbie in clojure and specially in multi threading.

Crispin04:08:53

I would write it as (async/thread (process-data-chan))

Crispin04:08:15

is process-data-chan nil? does it return nil?

Crispin04:08:00

thread-call expects a function as its arg. does (process-data-chan) return a function?

Crispin04:08:31

maybe you mean (async/thread-call process-data-chan)?

Crispin04:08:47

so you get the exception with future? and not with the bare call? are you sure it's not the other way around (the exception is with the bare call?)

Crispin04:08:10

future captures all internal exceptions. They will be raised when you deref the future.

Anik Chowhdury04:08:58

@U1QQJJK89 thanks a lot. I have to write

(async/thread-call process-data-chan)
instead i write wrong one. Actually i want to use go block of core async to do that operation of multi threading which i did with future. But I really find go block hard to understand!

Crispin04:08:39

go is the parking form of thread

👍 4
Crispin04:08:26

watch hickeys core.async intro talk. Helped me understand it when I was starting out: https://www.infoq.com/presentations/clojure-core-async/

❤️ 16
zhuxun208:08:03

I'm trying out Reagent. One thing bugs me as someone who came from working with React JSX is that the prevailing formatting convention supported by tooling is very line copy-paste unfriendly:

zhuxun208:08:08

for example, if I were to append a [:li "c"] after [:li "b"], in the following code

[:ul
 [:li "a"]
 [:li "b"]]

zhuxun208:08:39

I can't just line copy-paste the last line. Instead, I need to do some minor editing...

zhuxun208:08:36

Do you guys format Hiccup-like forms with closing brackets in newlines?

zhuxun208:08:16

[:ul
 [:li "a"]
 [:li "b"]
]

👎 12
👍 4
zane16:08:10

I'd say that this rule from the style guide applies here: https://guide.clojure.style/#gather-trailing-parens

zane16:08:41

@U051BLM8F, maybe we should change it to say "delimiters" rather than "parens"?

Chris08:08:37

Personally I’m using Parinfer (https://shaunlebron.github.io/parinfer/), it helps a lot for these cases

👍 8
schmee09:08:04

☝️ this, parinfer makes these problems go away!

danielneal09:08:02

In emacs (and probably in other editors), you wouldn’t copy the last line in this case, you’d forward select the next expression (which would select [:li "b"] and then copy the selection

Crispin10:08:33

you could also in emacs use c-k to kill the last line, which would retain the final bracket and not delete it

Crispin10:08:44

or you can use expand-region

Crispin10:08:40

c-= inside the form to select it, then copy and paste as usual

Crispin10:08:09

(I use paredit in emacs)

David Pham12:08:19

I would like to generate a range of distinct days with Clojure.spec, anyone could help me with it?

Mno13:08:32

I tried asking in #yada but it seems to be rather empty during my normal hours. But I'd appreciate if someone has a resource on getting oauth2 (with google preferably) to work with yada.oauth that they point me at it.

Noah Bogart13:08:10

if i want to conj a bunch of objects onto a vector in a map atom, and i have them in a list, is it better to write a (doseq [obj objects] (swap! v update :key conj obj) or something like (swap! v update :key #(apply conj % objects))?

Noah Bogart13:08:59

that's a cumbersome way of saying: is it "better"/more idiomatic to do a bunch of swap!s or a single swap! with apply?

Alex Miller (Clojure team)13:08:41

the former is N separate transactions (and someone else could be doing the same thing, interleaving the results)

👍 4
Alex Miller (Clojure team)13:08:09

but really you'd probably be better off with (swap! v update :key into objects)

Alex Miller (Clojure team)13:08:36

but be careful with the nil case - into uses a list in that case

Alex Miller (Clojure team)13:08:08

I guess conj has the same problem (since into uses conj)

Alex Miller (Clojure team)13:08:41

into will also automatically use transients if it can (like with vectors)

Noah Bogart13:08:20

oh that's clever, yeah. i'll experiment with into, see if that handles my usecases

petterik17:08:30

I usually guard against the nil case with fnil like so: (swap! v update :key (fnil into []) objects), to make the type of the collection explicit. Can easily swap out the vector in (fnil into []) for a #{} or {} depending on the type one wants.

bartuka17:08:57

I'm reading a XLSX file with this java library (https://github.com/monitorjbl/excel-streaming-reader) and transforming the HSSFRow objects into a lazy-seq by converting an Iterable interface using iterator-seq

bartuka17:08:12

however I get EOF while reading errors from some files

bartuka17:08:35

I could not notice any difference in the content of the files that throws this excp.

noisesmith17:08:55

any chance the lazy-seq escapes the body of the with-open that keeps the resource open?

bartuka17:08:37

yes, this is happening

bartuka17:08:55

but I should get errors from all the files I process this way, right?

noisesmith17:08:39

only the ones that aren't realized up to the entries you try to use

noisesmith17:08:54

iterator-seq chunks, the chunking can hide this error with smaller inputs

noisesmith17:08:23

(I'm a big non-fan of chunking iterator-seq btw since iterators often imply some kind of side effect even if just extra IO...)

noisesmith17:08:59

somewhere I have a snippet for non-chunking iterator-seq, but it's not hard to write regardless

bartuka17:08:20

I'm connecting some dots here (while running my code, I did a quick re-write to check if this was the problem)

bartuka17:08:56

I send each processed row to rabbitmq and I was watching the patterns of the messages received and I noticed some chunks

bartuka18:08:07

so itertaror-seq is the one creating them?

noisesmith18:08:29

yes, it will consume N items at a time, even if you ask for 1 at a time

bartuka18:08:56

interesting, is it possible to control this parameter?

noisesmith18:08:05

nope, it's built into the code

noisesmith18:08:22

but as I mentioned, rewriting iterator-seq to not chunk is only a few lines of code

dpsutton18:08:18

(defn iterator-seq [iter] (clojure.lang.RT/chunkIteratorSeq iter)) you aren't kidding

😄 4
dpsutton18:08:33

doc string and metadata elided

noisesmith18:08:07

lost my version, but this one is identical https://gist.github.com/raek/2601906

noisesmith18:08:22

(defn iterator-seq [it]
  (lazy-seq
   (when (.hasNext it)
     (cons (.next it)
           (iterator-seq it)))))

noisesmith18:08:44

I'd never put an arg list on the same line as a function name, otherwise to the character my version

dpsutton18:08:48

i'm extremely inconsistent on that. do you have a motivating reason or just your aesthetics?

noisesmith18:08:11

the doc-string goes between the name and args

👍 4
Alex Miller (Clojure team)18:08:18

If you care about external resource control, you shouldn’t use seqs in the first place

noisesmith18:08:27

the args on line with function-name thing makes sense in cl, with their doc-string placement

Alex Miller (Clojure team)18:08:28

Use loop or education or something else

Alex Miller (Clojure team)18:08:22

My general of thumb is - if you care exactly how many things get realized and when, then don’t use lazy seqs

💯 4
Alex Miller (Clojure team)18:08:33

As they make no guarantees

bartuka18:08:09

that's pretty reasonable

noisesmith18:08:15

yeah, I like that as a principled approach, but that's in conflict with every professional codebase I've inherited or collaborated on

Alex Miller (Clojure team)18:08:34

Sounds like you’re the common factor ;)

noisesmith18:08:35

it's like some things in core.async - the design principles work but the way most people seem to adopt them fall into very predictable misuses

Roger Amorin Vieira20:08:39

Hey clojurians, when I start to learn clojure this year I built some basics tests/algorithms, and today I look that repository and think about create a library to be like a group of nice algorithms, that could be useful. So if you want to help me to build this library access the link and lets code: https://github.com/rogervieiraa/clojure.algorithm (This repository is noob friendly, so the code sometime isnt the in the best way, if you found some code that can be upgraded, open an issue explaing that, this it's a nice way to help each other to write better code)