Fork me on GitHub
#beginners
<
2021-03-26
>
pinealan07:03:59

anyone got experience with implementing https://en.wikipedia.org/wiki/Financial_Information_eXchange clients? are there resources in clj/java that can help one to get started?

Tim Robinson10:03:35

is there any documentation that describes what the various metadata flags do? I realise it's extensible but I can't find anywhere that lists the "built-in" ones. specifically ^:redef

noisesmith23:03:45

if the metadata controls the compiler, I'd expect it to show up in that file

bastilla11:03:04

Simple question here. I do this a lot: (if a a ...)

let [a (some-calc x y)
     a (if a a (some-alternative x y)]
But it dawns on me this is from my imperative mindset and not very lispy/functional. How do you deal with this?

delaguardo11:03:56

(or a (some-alternative x y))

delaguardo11:03:34

event better (or (some-calc x y) (some-alternative x y))

๐Ÿ™Œ 6
bastilla11:03:04

This community rocks!! @U04V4KLKC

simongray11:03:19

what @U04V4KLKC wrote. Using or is idiomatic.

delaguardo11:03:25

or is a macro so it is safe to even have some sideeffects in some-alternative function

bastilla11:03:01

Thanks a lot !! (and @U4P4NREBY @U04V4KLKC )

simongray11:03:52

both and and or just return the last value (when true) since everything apart from nil and false is considered true in Clojure, so you will see a lot of succinct code that combines logic tests and nil punning in Clojure code.

๐Ÿ™Œ 3
aratare13:03:00

Hi there. What is the de facto way in Clojure to check if a string is an email address? Is regex matching my best option here?

manutter5113:03:00

There are a lot of resources that will tell you the best you can do is to determine if a string probably is an email address, and not necessarily a valid one.

manutter5113:03:36

You can google for some really hairy regexes that are intended to be a comprehensive match for any valid email address, but YMMV.

manutter5113:03:53

The site I'm working on now just has a simple regex that checks for "_@_._", and if it doesn't match, it just puts up a caption that says "Please be sure you are using a valid email address."

aratare13:03:02

yeah I forgot how hairy email validation can become with regex

manutter5113:03:45

The only reliable way to check for valid email addresses is to send it an email with a link that has an embedded one-time token, and then see if they click the link.

โ˜๏ธ 9
manutter5113:03:45

Alternately, there are online services that do mass-mailing that will offer you email validation services, which might be marginally better than a regex, if you don't mind paying.

manutter5113:03:30

I'm thinking like MailGun or MailChimp or something, but I don't remember which of them (if any) offers that service. I have seen it though.

aratare13:03:30

This is for a personal project so Iโ€™ll just do some simply regex matching. Thanks a lot ๐Ÿ™‚

ghadi13:03:03

@rextruong first 8-9 minutes ofhttps://www.youtube.com/watch?v=9Q--oX5muxw covers email parsing with regexes

๐Ÿ‘ 9
ghadi13:03:37

tl;dw "good luck" ๐Ÿ™‚

manutter5113:03:36

The phrase "exponentially diminishing returns" does come to mind ๐Ÿ™‚

Elliot Stern13:03:26

Thereโ€™s some java libraries like https://javaee.github.io/javamail/, but the simplest regex + sending an email is really best

Azzurite16:03:37

I feel very stupid right now because this must be so basic and I can't figure it out... I want to create a function that wraps hiccup content

(defn wrap [content] ; content is a list of hiccup elements
  [:div {:id "Test"}
   ; insert content here, but not in a list, just all the individual elements
   [:div {:id "footer"} ...]
  ])
how do I do that? Or is that just the wrong approach?

manutter5116:03:23

You could use into effectively here.

dpsutton16:03:14

you have a vector and a collection and want to return a vector of the concatenation. (into [:div {:id "footer"}] your-collection) is the most straightforward approach

dpsutton16:03:48

I phrased it like this to point that the smallest reproduction of your issue doesn't have hiccup or divs or a function called wrap involved. often all these details mask the simple problem: (into [:a] [:b :c :d]) -> [:a :b :c :d]

Azzurite16:03:18

hm ok I was hoping to be able to do something like in js where you can do

let arr1 = [1, 2, 3];
let arr2 = [...arr1, 4, 5, 6];
where arr2 would be [1, 2, 3, 4, 5, 6] then

dpsutton16:03:54

there's no equivalent of the spread operator in clojure

Azzurite16:03:08

okay thanks!

Azzurite16:03:39

kind of interesting, I'd think that'd be a pretty cool thing to have

Azzurite16:03:49

makes everything more succinct

dpsutton16:03:43

you can post on http://ask.clojure.org . It's possible it's been brought up before. Possibly declined, possibly still open to it. Or perhaps no one has taken the time to ask about it

Alex Miller (Clojure team)17:03:40

Donโ€™t recall anyone asking for it

Alex Miller (Clojure team)17:03:10

I mean, thereโ€™s concat, and cat transducer if you want vector

Azzurite16:03:57

so my function would look like this:

(defn wrap [content] ; content is a list of hiccup elements
  (let [wrapper [:div {:id "test"}]
        footer  [
		          ; some more elements here
				]]
  (into (into wrapper content) footer)
it does what I want... idk it's just looking wrong somehow, like it could be much easier...

Azzurite16:03:40

in JS I would've done

let wrap = (content) => [
   :div, {:id "test"},
   ...content,
   // footer elements
];
(I'm not comparing/complaining, I would've just hoped it was easier and hope there's a better way than what I do)

dpsutton16:03:01

(reduce into wrapper [content footer])

dpsutton16:03:42

or (into wrapper (concat content footer)) should work

seancorfield16:03:02

(-> wrapper
    (into content)
    (into footer))
@azzurite This makes the flow more obvious, perhaps?

Azzurite17:03:35

honestly idk why this wasn't obvious to any of us ๐Ÿ˜„

(concat wrapper content footer)

dpsutton17:03:00

it needs to be a vector for hiccup

dpsutton17:03:25

so you'd have to do (into [] (concat ...)) which is what i put above (into wrapper (concat content footer))

noisesmith23:03:35

this is a great place to use cat - (into [] cat [...])

dpsutton23:03:58

i always forget about cat

Azzurite17:03:02

I see, yeah

Azzurite17:03:04

thanks everyone

Azzurite17:03:42

for some reason I like (vec (concat wrapper content footer)) best, just gets my intent across I feel

noisesmith23:03:24

there's also (into [] cat [wrapper content footer])

noisesmith23:03:44

does the same thing to the data, with less intermediate steps / lazy seqs

Azzurite10:03:05

I still don't understand transducers and haven't found a good explanation... the official reference seems to assume too much of my intelligence ๐Ÿ˜„

noisesmith17:03:31

my tl;dr is that they offer the same transformation steps as lazy seq operations, without needing a seq for input or output

noisesmith17:03:07

this wouldn't matter if clojure was a "clever" compiler, but clojure is intentionally not one

manutter5117:03:22

That works too.

sova-soars-the-sora18:03:05

So let's say i've got a series of posts on a social-ish thing...

sova-soars-the-sora18:03:51

and I want to have notifications for users... like if someone "reacts" to your post.

sova-soars-the-sora18:03:02

i'm thinking: keep a "last-seen-notification" timestamp for each user, and then check it against the stored reactions... but i also want a way for users to mark certain notifications as seen... well i don't know if i want to go that fine-grain... but in general a way to see notifications for reactions. does it make sense to...

sova-soars-the-sora18:03:52

mark notifications as "seen" ... or try and simply rely on latest-seen timestamp to do that difference?

sova-soars-the-sora18:03:22

kinda a nebulous design-level question... but i'm a little unclear on doing the notifications bit so any words of help would be appreciated ๐Ÿ˜„

hiredman18:03:02

most notification systems are really bad, because when they were initially written the idea was "little ephemeral messages"

hiredman18:03:33

but no one actually wants that, what they want is basically "lightweight email"

hiredman18:03:50

meaning an inbox, where notifications persist, and you can mark them as read, and read old ones, etc

hiredman19:03:40

so I would try to ignore that you are implementing notifications, and instead look at imap, and the extensions to imap for push, for inspiration

sova-soars-the-sora19:03:11

that makes sense, "lightweight email." I am trying to keep a very reduced interface but a historical view on notifications is likely necessary.

sova-soars-the-sora19:03:47

Do you reckon "mark as read/seen" and "Mark all as read/seen" would be sufficient with a boolean on each notif?

sova-soars-the-sora19:03:10

hard-pressed to think of other use-cases.

Franco Gasperino23:03:07

if this is evaluated lazily, shouldn't i receive a false instead of an NPE?

(first (remove #(% nil) [int? zero?]))

Michael Gardner00:03:00

to verify that chunkiness is the problem:

(defn dechunk [s]
  (lazy-seq
   (when-let [[x] (seq s)]
     (cons x (dechunk (rest s))))))

(first (remove #(% nil) (dechunk [int? zero?])))

Michael Gardner00:03:40

I prefer creamy sequences over chunky, myself

Franco Gasperino00:03:00

i like the crunch of the chunk

Michael Gardner00:03:22

you can also use transducers to avoid laziness if you prefer

Michael Gardner00:03:41

personally I think laziness-by-default was a design mistake in Clojure

Franco Gasperino00:03:46

i have a user-supplied value that i need to apply a series of value checks to, defined in an external schema

Franco Gasperino00:03:14

schema as a vector that will provide a bottoms-up series of truthy tests to the value

Franco Gasperino00:03:31

was curious how to handle a nil

Michael Gardner00:03:32

transducer version:

(into [] (comp (remove #(% nil)) (take 1)) [int? zero?])

Michael Gardner00:03:52

you could also just use reduce

๐Ÿ‘† 3
Franco Gasperino00:03:28

reduce will still need to be in transducer form, correct?

Franco Gasperino00:03:00

(reduce #(%2 1) [int? pos?]) => true
(reduce #(%2 1) [int? even?]) => false
(reduce #(%2 nil) [int? even?]) => NPE

Franco Gasperino00:03:10

or more appropriate non-transducer version:

(reduce #(conj %1 (%2 1)) [] [even? int?]) => [false true]

Michael Gardner00:03:00

seems like you want short-circuiting, in which case you'd use and in the reduce to produce a single bool

Franco Gasperino00:03:54

yea. i think thats why i picked remove as the primary form. the first eval (int? even?) that returns false, i can take 1 and short circuit

Franco Gasperino00:03:16

but first calls seq, which is where your link on chunking comes into play

Darin Douglass00:03:51

you can use reduced to short-circuit a reduce call: https://clojuredocs.org/clojure.core/reduced

Franco Gasperino00:03:32

thanks, darin. will check that out

Franco Gasperino00:03:03

in the case of transducers, do all of the comp params need to be transducable, too?

Franco Gasperino00:03:22

e.g. in the case of your example, you use (take 1) in it's transducer form

Franco Gasperino00:03:41

outside of a transducer context, i could use first. but it doesn't seem to want to apply here..

Michael Gardner00:03:01

they all need to be transducers, yes. first doesn't have a transducer arity, I guess because take can do that already

noisesmith23:03:03

calling first on (remove pred? coll) will realize every item in coll until one is truthy, so the error should be expected

noisesmith23:03:19

you can replace zero? with (fnil zero? -1) (-1 was an arbitrary choice, plug in any non-zero)

noisesmith23:03:49

or #(and (number? %) (zero? %))

Franco Gasperino23:03:18

(int? nil) => false
  (zero? nil) => NPE