beginners

Getting started with Clojure/ClojureScript? Welcome! Also try: https://ask.clojure.org. Check out resources at https://gist.github.com/yogthos/be323be0361c589570a6da4ccc85f58f.
sova-soars-the-sora 2020-11-23T06:03:47.264600Z

👋:skin-tone-4:

🤘 1
Lyderic Dutillieux 2020-11-23T09:34:47.267400Z

Hey guys, I'm looking to send emails with Clojure. I'm new to the Java eco-system. I saw that there is this clojure lib (postal : https://github.com/drewr/postal), which wraps Jakarta Mail. Anyone have an opinion on Postal or Jakarta Mail ? Thanks 😉

dharrigan 2020-11-23T09:38:39.267800Z

Another one to evaluate is <https://github.com/toyokumo/tarayo> it’s pretty simple.

👀 1
dharrigan 2020-11-23T09:39:12.268400Z

However, for the moment, I’m mostly sending emails via Amazon SES. Works great (with the cognitect aws libraries)

dharrigan 2020-11-23T09:39:13.268600Z

.

0xclj 2020-11-23T13:40:07.269100Z

Given a collection like:

[{:lname "ln", :fname "First user", :email "<mailto:x.y+1@domain.com|x.y+1@domain.com>", :mobile "+1111111121", :secondarychannels [{:m "email", :mv "<mailto:x.y+first1@domain.com|x.y+first1@domain.com>"} {:m "email", :mv "<mailto:x.y+first2@domain.com|x.y+first2@domain.com>"} {:m "sms", :mv "+1111111111"}]} {:lname "ln", :fname "Second user", :email "<mailto:x.y+3@domain.com|x.y+3@domain.com>", :mobile "+1111111112", :secondarychannels [{:m "email", :mv "<mailto:x.y+second1@domain.com|x.y+second1@domain.com>"} {:m "email", :mv "<mailto:x.y+second4@domain.com|x.y+second4@domain.com>"} {:m "sms", :mv "+1111111131"}]}]
I want something like: {:emails [“<mailto:x.y+1@domain.com|x.y+1@domain.com>” “<mailto:x.y+first1@domain.com|x.y+first1@domain.com>” “<mailto:x.y+first2@domain.com|x.y+first2@domain.com>” “<mailto:x.y+3@domain.com|x.y+3@domain.com>” “<mailto:x.y+second1@domain.com|x.y+second1@domain.com>” “<mailto:x.y+second4@domain.com|x.y+second4@domain.com>”], :sms [“+1111111121” “+1111111111" “+1111111112” “+1111111131"]} There are multiple ways to do this and I have a working approach of first gathering all the emails and then gathering all the mobiles and merging them together. I’m looking for an alternate solution that reads like:
Pseudocode:

let x = {:emails [] :sms []}
for every element in collection-&gt;secondarychannels, if m == email, append mv to emails collection (in x), else append mv to sms collection (in x).
What is a good way to write the same in Clojure?

dgb23 2020-11-24T14:20:28.327Z

@mail.acharyarahul.now Disclaimer: I’m also just a beginner/intermediate Clojure programmer. But have a look here: https://clojuredocs.org/clojure.set My instinct is that you can define your collection as a set of maps (AKA kind of like tagged tuples in relational algebra). And then you want to use a combination of project select and index to achieve what you are doing. My assumption is that your code becomes a bit clearer, more declarative that way. To get the hang of it I suggest you open a REPL and just play around with these functions a bit and some example data (that’s what I would do).

uosl 2020-11-24T15:08:36.330100Z

I also happened to look into project, select and index on clojuredocs when I saw these comments. I wonder if there's a blog post/tutorial introducing these to people unfamiliar with SQL/relational algebra...

dgb23 2020-11-24T15:19:22.330300Z

@regen SQL is based on relational algebra. I learned it with the book Datenbanktheorie H.Buff (german). The basic operations and theory are rather simple. It’s based on set and tuple data structures. I’m not aware of an online resource, but I recommend learning the general first (relational algebra) and then apply it to SQL and/or Clojure’s sets.

uosl 2020-11-24T15:33:19.330800Z

Thanks for the info! I can't read german, but I'll try and find a book on relational algebra.

0xclj 2020-11-26T01:29:48.427700Z

@denis.baudinot, thanks a lot for pointing to the helpful resources. Will try out playing around with those commands. A few questions though: > AKA kind of like tagged tuples in relational algebra Not really aware of a concept of “tagged tuples” in relational algebra. Can you point to relevant examples?

dgb23 2020-11-26T10:05:56.436200Z

@mail.acharyarahul.now what I meant is just tuples. The tagging occurs by giving each position a key so to say. You can think of a map (or record, row etc.) as a tuple, but with names for each position. There must be a better word for it, but I don’t remember it, so I just said “tagged tuples”. Similarly, a vector (mathematics) has positional semantics like (23, 7, 42); but we sometimes say x, y, z to refer to each position in the vector. Again, probably there are better words for this as well :)

0xclj 2020-11-27T01:04:28.457300Z

@denis.baudinot, got it. Thanks!

Bob B 2020-11-23T14:09:14.269800Z

you could group secondarychannels by :m and then use the values I believe

✔️ 1
2020-11-23T14:15:03.270Z

There’s a library called meander that was written for this sort of thing. If you’re new to Clojure it may or may not be a good fit, but you might be interested anyway. https://github.com/noprompt/meander

✔️ 1
uosl 2020-11-23T14:15:39.270300Z

Your pseudocode seems to easily translate to a reduce

✔️ 1
tskardal 2020-11-23T14:53:29.270500Z

I played around a bit for fun and ended up with with this:

(-&gt;&gt; stuff
     (mapcat :secondarychannels)
     (reduce (fn [agg {k :m v :mv}]
               (update agg (keyword k) conj v)) {}))
where stuff is your original structure

simongray 2020-11-23T15:09:02.271Z

Unless you specifically need the ordering, sets seem like a better semantic fit for your two resulting collections.

dgb23 2020-11-23T18:14:57.272100Z

I agree with @simongray on that the set would be the right data structure for these kinds of operations. There are std functions for sets, like select, join and so on, which seem to be the right fit for the transformations you want to do.

alexmiller 2020-11-23T18:49:41.272600Z

I mean, what you're building here IS an index and this IS a relational database

2020-11-23T20:56:18.277100Z

Anyone familiar with clojure.java-time? I’m having trouble finding the right function in the docs to convert a string timestamp to a more readable date-time format. Given a timestamp in ISO-8601 "2020-11-22T19:00:01.000939-06:00", how would I be able to convert it to something like “Nov. 22, 2020 07:00 PM” or even “2020-11-22 7:00 PM”?

2020-11-23T21:00:22.277700Z

the "format" and "formatter" from this ns are imported into the primary ns, and are made for this sort of thing https://github.com/dm3/clojure.java-time/blob/master/src/java_time/format.clj

2020-11-23T21:01:58.278600Z

I have a hunch this library makes more sense if you are familiar with the underlying classes it wraps

2020-11-23T21:02:16.278900Z

(which kind of begs the question regarding using the library...)

2020-11-23T21:03:23.279400Z

there is a simple looking example in the README though

(format "MM/dd" (zoned-date-time 2015 9 28))
=&gt; "09/28"

2020-11-23T21:16:26.280400Z

Thank you. I’ll try out format

jstaab 2020-11-23T23:23:45.282800Z

Hi everyone, I'm trying to get started with compojure (after a few years' hiatus), and I'm having a hard time getting route/resources to work. I'm not even able to get <http://clojure.java.io|clojure.java.io>.resource to work:

mkdir resources
echo 'hi' &gt; resources/x
clojure -e "(require '<http://clojure.java.io|clojure.java.io>) (prn (<http://clojure.java.io/resource|clojure.java.io/resource> \"x\"))"
nil

jstaab 2020-11-23T23:24:22.283Z

clojure 1.10.1 for reference

dgb23 2020-11-23T23:37:26.287100Z

have you tried using the a name.extension convention? https://docs.oracle.com/javase/8/docs/technotes/guides/lang/resources.html#res_name_context

jstaab 2020-11-23T23:40:38.287300Z

Yep, if I use the filename hello.txt as in the clojuredocs example (https://clojuredocs.org/clojure.java.io/resource) I still get nil

jstaab 2020-11-23T23:49:57.287600Z

I think I got it, I wanted route/files instead of routes/resource. I'm not sure why, I guess I don't really understand resources

seancorfield 2020-11-23T23:53:49.287800Z

If you use route/files, you'll find your app won't work when you build an uberjar and run it (via java -jar).

jstaab 2020-11-23T23:54:51.288Z

I see, so that's more for accessing files on a target system then? So how do I get resource to work?

seancorfield 2020-11-23T23:54:55.288200Z

You need resources on your classpath to be able to pick up files from it. That's why running clojure like that isn't seeing it.

jstaab 2020-11-23T23:55:40.288400Z

Ok, I'm just using tools.deps, not lein, so I assume that's something lein-ring handles for you? So it's probably just a flag I pass to clojure when I run my program

seancorfield 2020-11-23T23:57:14.288600Z

(! 729)-&gt; mkdir jstaab
(! 730)-&gt; cd jstaab/
(! 731)-&gt; mkdir resources
(! 732)-&gt; echo 'hi' &gt; resources/x
(! 733)-&gt; clojure -e "(require '<http://clojure.java.io|clojure.java.io>) (prn (<http://clojure.java.io/resource|clojure.java.io/resource> \"x\"))"
WARNING: When invoking clojure.main, use -M
nil
(! 734)-&gt; clojure -Sdeps '{:paths ["resources"]}' -e "(require '<http://clojure.java.io|clojure.java.io>) (prn (<http://clojure.java.io/resource|clojure.java.io/resource> \"x\"))"
WARNING: When invoking clojure.main, use -M
#object[java.net.URL 0x34a1d21f "file:/Users/sean/clojure/jstaab/resources/x"]
^ like so

seancorfield 2020-11-23T23:57:42.288800Z

Or put a deps.edn file in that directory that has :paths ["resources" "src"] (assuming you also have a src folder)

jstaab 2020-11-23T23:57:51.289Z

neat, I'll try that

jstaab 2020-11-23T23:59:36.289200Z

That did the trick! Thanks Sean, you remain the best.