Fork me on GitHub
#clojure
<
2018-09-14
>
mv04:09:19

Hey everyone. If I were building a new web app in clojure, with a frontend in cljs, what libraries should I look at? I'd like to be backed by Datomic. Last time I asked, transit/vase was recommended to me, but I haven't seen much activity on the vase project

seancorfield04:09:04

(I'd certainly be interested to hear responses to that question! My inclination would probably still be Reagent and/or re-frame and either Sente or a simple REST back end with Ring/Compojure or maybe compojure-api...)

mv04:09:24

Thanks @seancorfield! Re-agent, reframe and sente all look great. I was more thinking about the backend. I really like the idea of vase, but don't want to build on something abandoned

dangercoder04:09:03

@mv http://www.luminusweb.net/ can be interesting for you

👍 8
seancorfield05:09:59

@jarvinenemil That site seems to start out with recommending LightTable as an editor and using Docker... I thought LightTable was pretty much abandonware at this point and starting out with Docker is not exactly a friendly low bar to get started...

seancorfield05:09:16

It just feels way too framework-y and "magical" to me... I've seen beginners start down that path and it's great if it works but they're hopelessly lost as soon as anything goes wrong 😞

manuel05:09:46

I started with Luminus back in first Clojure days

manuel05:09:12

it was a fine experience, but I did learn way much more by setting up an application from scratch by myself

domparry07:09:13

Hi all. I really feel like I’m just not finding something in core that does this:

domparry07:09:16

(defn contains-subvals? [subvals vals]
  (->> vals
       (partition (count subvals) 1)
       (some #(= subvals %))))

domparry07:09:42

(Order is important, so using sets isn’t going to work)

domparry07:09:13

want to know if sub vector [1 3] exists in [3 4 1 3 6] for example

awb9907:09:30

can someone help me with a what I think is a siple issue?

awb9907:09:57

I have a vector with statistics, then I filter the statistics so I only get the statistics for a month.

awb9907:09:13

when I then want to get a key element then I get nil.

schmee08:09:38

I suggest printing % in your filter fn to make sure that the input is what you expect

awb9908:09:34

@smee would I do this via (do println (%) ...) ?

awb9908:09:28

I just found the error. Filter returns a list, so I have to take FIRST of the list that filter gets.

schmee09:09:25

just remember that first will return nil on an empty list!

deliciousowl10:09:56

this is quite the gotcha when you're manipulating strings, because it will print the function name instead

pyr09:09:53

As I was saying in #remote-jobs:

pyr09:09:55

Hi Clojurians!We're opening a new Clojure heavy position at Exoscale where we build programmable cloud infrastructure. We're now completely remote-compliant even though we favor European candidates: https://www.exoscale.com/jobs/#senior-software-engineer-backend-mailto

deliciousowl10:09:19

I'll gladly assist you with my several weeks of Clojure experience 😄

awb9910:09:53

I want to concatenate lists, this works: (concat [1 2] [3 4] [5 6] [7 8])

awb9910:09:07

what I am trying to do is concatenate an array of arrays

awb9910:09:21

(concat [ [1 2] [3 4] [5 6] [7 8] ])

awb9910:09:27

so this works not.

awb9910:09:41

I want to get back [ 1 2 3 4 5 6 7 8]

awb9910:09:51

but I only have a list of lists.

awb9910:09:58

I am sure there must be some sort of parameter.

awb9910:09:02

I tried mapping,

awb9910:09:07

but this didnt work.

roti10:09:10

you can use apply

roti10:09:24

(apply concat ...)

awb9910:09:09

(apply concat [ [1 2] [3 4] [5 6] [7 8] ] )

awb9910:09:16

this works

awb9910:09:25

I knew there must be some kind of trick...

awb9910:09:46

thanks roti

awb9910:09:49

clojure is really quite powerful.

roti10:09:52

it's not a trick 🙂

awb9910:09:55

I did read two books,

awb9910:09:18

but still have a hard time in coming up with the right functions to use.

awb9910:09:31

it is quite different to c# where I am familiar with....

roti10:09:20

there's also http://clojuredocs.org/clojure.core/flatten , which is more general

roti10:09:45

I know what you mean. I think there are basically two humps you need to get over to be comfortable with Clojure: thinking in a functional way and getting used to immutable data

awb9910:09:06

I have been using ramda in javascript for quite a while,

awb9910:09:14

which is a functional library,

awb9910:09:23

and I also have experience with Linq on c#

awb9910:09:37

so I do a lot of stuff in a functional way,

awb9910:09:57

but in clojure you seem not to have this last 5 or 10% of imperative wrapper,

awb9910:09:17

so normally I at some point when I dont find a functional approach, then I end up having some for loops or whatever

awb9910:09:27

and in clojure, I sort of miss that.

awb9910:09:59

the other thing that sort of confuses me,

awb9910:09:04

is that the code I write is so compact.

awb9910:09:12

I think I now have 500 lines of clojure

awb9910:09:21

and in c# this would easily be 10,000 lines.

awb9910:09:31

so in c# you basically do typing all the time,

awb9910:09:39

you dont take lots of time to think about stuff,

awb9910:09:41

you just write,

awb9910:09:58

and when you have written enough, then your brain is already at a stage where you have thought about the problem.

orestis11:09:12

Thanks for this phrasing, I’ve been thinking similar thoughts recently and this is very very apt.

awb9910:09:04

in clojure I thikn it is the other way around.

awb9910:09:09

you need to think about the problem,

awb9910:09:13

and then the writing is really fast.

awb9910:09:16

Is there a way to combine (range 2005 2019) with (range 1 13) so I get a vector of vectors, so I have a combination of year/months ?

awb9910:09:27

is a map the best way to solve that?

awb9910:09:52

or is there some kind of vector cross-product that I can take?

roti10:09:50

(for [year (range 2005 2019)
        month (range 1 13)]
[year month])

awb9910:09:23

cool. two approaches.

roti11:09:18

and this one looks quite imperative 🙂

awb9911:09:40

it is imperative, or not?

deliciousowl11:09:21

the one I linked is a lazy function

awb9911:09:20

yes, yours @coinedtalk is very functional

awb9911:09:25

I talk of the for loop

deliciousowl11:09:32

thats a list comprehension too

deliciousowl11:09:38

I don't think it's imperative

roti11:09:52

no, it's not imperative. If you macroexpand the for you see it's actually based on loop which is a functional looping construct

deliciousowl11:09:27

if you want side effects you'd need to add (doall) or something?

deliciousowl11:09:41

trying to use for more often rather than dotimes

roti11:09:55

or use doseq

awb9911:09:29

(def year-month-vector (for [year (range 2015 2019) month (range 1 13)] [year month])) (doall year-month-vector)

awb9911:09:34

what I dont get,

awb9911:09:37

I work in the repl,

awb9911:09:51

and then when I want to quickly inspect a variable,

awb9911:09:55

then it doesnt work.

awb9911:09:04

for now I am putting doall in front,

awb9911:09:06

and then it works.

awb9911:09:12

but perhaps this is a bad idea?

deliciousowl11:09:15

it doesn't execute until you do that

deliciousowl11:09:25

it's a lazy function (?)

awb9911:09:40

so the doall just triggers the evaluation,

awb9911:09:06

so how I do it is ok then I guess.

awb9911:09:37

how do you guys organize your projects?

deliciousowl11:09:42

(println (do year-month-vector))

awb9911:09:56

I find that when I develop, I have to write tons of tests,

awb9911:09:06

to see if the functions do what they are supposed to do.

awb9911:09:18

I am unsure if I want to remove the tests, after I know it works,

awb9911:09:25

or if I woudl move the "tests" to a test folder,

awb9911:09:50

because when I later do modify my functions, I very easily fuck them up completely.

roti11:09:59

what do you mean by inspect a variable?

awb9911:09:01

until I sort of figure out how to make the modification work also.

roti11:09:19

when you print something it automatically triggers evaluation, so you don't need doall

awb9911:09:19

well, in this case I wanted to know if the month/year vector is how it shoudl be.

deliciousowl11:09:24

posted in the other channel, might be relevant for debugging: https://blog.michielborkent.nl/2017/05/25/inline-def-debugging/

deliciousowl11:09:20

Andy, maybe use clojure.spec and :pre :post conditions

roti11:09:23

that's why you can have infinite sequences, but not print them 🙂

awb9911:09:25

thanks so much!

deliciousowl11:09:40

might have to test a lot less later that way

awb9911:09:40

hopefully.

awb9911:09:44

THANK YOU SO MUCH GUYS!

awb9911:09:56

Without you I would go crazy!!

schmee11:09:14

@hoertlehner I think you hit the nail on the head with the comparison to C# above with regards to having time to think about the problem while writing the mountains of code required

schmee11:09:42

just stick at it the way you seem to be doing and you will have Clojure figured out in no time! 💪

orestis11:09:06

@hoertlehner re code organisation, are you talking about writing actual tests with deftest or just REPL experiments?

orestis11:09:01

One approach that seems to be very common is to keep either a comment block at the end of your file where you keep your REPL experiments there so you can just re-evaluate them later, or move to their own namespace and turn them into proper tests once the API stabilises.

orestis11:09:27

But if you create small functions, then usually you don’t need to change them that much after making them do what you want, in my (limited) experience.

awb9912:09:32

I was talking about Repl experiments.

awb9912:09:09

The comment block is a good idea.. Thanks!

roti15:09:21

@schmee @hoertlehner I never saw the verbosity of languages like C# or Java as an obstacle in thinking about the problem, though I did mind greatly the readability of such code (by which I mean how easy one can find out what the code does, which in C# and Java suffers because of the code which is there but not part of the problem). In Clojure however, until now I do feel that readability suffers as well, but for another reason: the lack of type declarations, and (to some degree) the lack of verbosity.

awb9915:09:48

To me the big issue I have with c# is that small Repl style experiments are really pain in the ass. I have written my own c# Repl... And even I ultimately gave up because typically one has to instanciate very complex object structures. What is also missing in c# is like a JSON format that allows to setup data structures easily.

awb9915:09:49

I as to reading code.. I still understand the verbose c# code better.. In clojure I have problems seeing the structure of the code.. If I have 5 levels of data hierarchy.. Then I get lost on which level I am doing what. And then if I move one bracket then I am on a completely different data layer.

awb9915:09:48

Javascript for example is very similar to clojure insofar as one can program very functional in it.. AND Javascript allows to define data structures in code..

awb9915:09:52

What does make c# code hard to understand is if you work with multiple services (like database) that have to be initialized somehow. Then most of the code is setting uo the connections, and perhaps managing the dependencies.. I find that very hard to simulate. So the functional part and the infrastructure gets convoluted.

schmee15:09:43

could you elaborate on how the lack of type declarations is problematic?

roti15:09:56

when reading clojure code, you always spend some time guessing the type of values (party to find out what values are accepted, but also to find out their semantic), and it's largely deductive process. it is therefore harder. this is mitigated with comments and names, of course, like any other dynamic language.

roti15:09:55

for dynamic languages in general, the connection between the source code and the runtime is weaker, so you can find out less just by looking at the code than you would in a static language

henrik07:09:06

I tend to document the types of input and output, where spec is not used. It's not as straightforward to explain in text though when working with complex data structures.

roti15:09:51

it's just something I miss because of many years working with static languages

schmee15:09:02

interesting, my feeling is the opposite. for me, when working in statically typed languages with no REPL it’s hard to understand what’s going on cause you have these large, opaque objects, often deeply nested, and there is no generic API to work with them

schmee15:09:27

in Clojure, I go into the REPL, print the thing and “oh, it’s a map” and then I have the usual tools at my disposal. in Java, for instance, I print something and “oh, it’s a HTTPServletExecutionContext” and I have no idea how to use it since it’s a completely custom thing with it’s own API

schmee15:09:33

multiply that with however many classes you have in your project (often several hundred or even thousand) and things get out of hand. in clojure, you pretty much have maps, vectors and seqs, and that’s it. and since most projects stick to that, I can immediately jump into any project and make sense of it

awb9915:09:55

I now have a little data mining / data exploration project written in clojure. Mostly I use print-table and proto Repl charts. Now I want to do something more interactive and don't know which libraries I should use. Is reagent / re-frame a good choice for that?

futuro15:09:20

I’ve heard lots of good things about re-frame, so if that’s caught your attention I’d just run with it.

futuro15:09:38

There’s a handful of choices for cljs UI frameworks, and the best deciding factor is to pick whichever grabs your attention while reading the readme.

roti15:09:03

the efficiency of the REPL as claimed by many, is half true in my opinion. In a static language you use the debugger of course, there's no alternative. the REPL is useful during development, but becomes less efficient in maintenance, simply because it does not allow you to easily inspect some state. you can use println of course, but often the debugger is flat out better. and all this is not related to the number of classes in a project, in my oppinion. I think the way logic is spread out in classes is rather the problem.

roti15:09:55

I have developed over time a hatred towards inheritance, and only because I did a lot of maintenance 🙂

awb9915:09:51

I am not yet at the stage, where I have huge clojure project, so I am just speculating. I found some snippets to allow remote-repl to a running application. So I think with a remote repl, one should be able to debug most problems of a running app, I guess better than with an IDE / Debugger, because one can setup all kind of scenarios quicker.

roti15:09:51

@hoertlehner you want to add a ui to your project?

awb9915:09:25

Yes I need a UI. And preferred a web based ui.

awb9915:09:32

In python I would use jupyter notebooks; there you have a few controls (like sliders, comboboxes, and numerical up/down boxes, that then allow me do explore the effect of parameter changes to the model.

futuro15:09:06

I don't think any cljs ui framework has ui elements out of the box, but check out https://material-ui.com/ in tandem with whatever you pick.

roti15:09:46

for web based UIs you can check out the react wrappers in clojurescript, they are definitely popular: https://clojurescript.org/community/libraries, om and reagent are probably the most popular. I tried using quiescent, because I liked the philosophy behind it, but ran into problems, and it also looks abandoned. I also played around with hoplon, and liked it.

futuro15:09:51

(or some other component library from the JS world)

ghiden20:09:23

Yes. I'm using an old version 0.7.0 due to some dependencies restrictions. This doesn't seem to work. But I just tried 0.8.1 and it works.

roti15:09:05

reagent is arguably the simplest in terms of API, you probably don't event need to learn React

roti15:09:13

indeed, the react wrappers don't offer ui elements, but all of them allow using react components

Lutz16:09:19

Hi everybody! I have a question about Onyx.

Lutz16:09:17

I have a job where I want to use watermark triggering to use windows of segments. It works in a toy example, and time-based triggering works in the real application. However, watermark triggering does not work in the real application. What can be the cause and how can I verify and fix that?

debamitro17:09:20

Hi, I am a beginner in Clojure but not a beginner in programming. I would like to study the codebase of a large, and preferably computation-intensive, Clojure program. I come from a C/C++ background and I want to see how large programs can be written differently

jsa-aerial17:09:50

depending on what you are fishing for here are a couple serious things: https://github.com/uncomplicate/bayadera <-- very serious and https://github.com/aria42/flare <-- sits on top of Neanderthal https://github.com/uncomplicate/neanderthal

jsa-aerial17:09:13

OTOH, might be best to just start with some straight ahead Clojure data xform work. Also, check out #beginners and probably useful to add #data-science

debamitro17:09:59

Hey @U06C63VL4 thanks a ton

✔️ 4
seancorfield18:09:33

Also, feel free to ask any beginner-Clojure questions in the #beginners channel as that's where other folk have opted it to help with as much detail (and patience) as you need or want.

seancorfield18:09:52

(for "beginner(s) in programming", we have #programming-beginners -- just FYI)

debamitro01:09:39

Thanks @seancorfield I will do that

timgilbert18:09:11

Hey all, I'm sure I'm missing some basic core function that can be used to make this function more concise, anyone want to assist with simplifying it? I'm just running a list of data through a pre-determined list of transform functions.

(defn apply-transforms [data]
  (map (fn [xform] (xform data))
       [xform-fn-1 xfrom-fn-2 ...]))

Nolan18:09:59

looks like juxt could help

enforser18:09:10

yeah, good call on juxt
((juxt xform-fn1 xfrom-fn-2 ...) data)

wizard 4
timgilbert19:09:53

juxt! It's like Clojure's magic secret sauce

timgilbert18:09:09

Er, that is, I'm running a single data item through all of those, as in a threading form

cryan19:09:07

like, the threading macro? ->?

lilactown19:09:10

is there a spec for datomic's datalog query language?

nwjsmith19:09:31

Not sure if that’s useful, but it should be complete (might be out-of-date WRT the latest clojure.spec)

arrdem23:09:00

Does anyone have an example of :default-deps lying around? I’ve got a hacked up copy of the clojure script which lets me -Dmore-deps.edn and I’ve confirmed that works, so I’m trying to clojure -Dmore-deps.edn -R:my-defaults to inject resolver :default-deps so I can have {:deps {org.clojure/clojure nil}} in my actual deps.edn and “inherit” the Clojure version from the :default-deps of the :my-defaults profile in the other file.

Alex Miller (Clojure team)23:09:28

default-deps is not terribly useful at the moment

Alex Miller (Clojure team)23:09:11

not sure exactly what you mean by “inject resolver”

arrdem23:09:12

clojure.tools.deps.test-alpha> (deps/resolve-deps {:deps {'org.clojure/clojure nil}}
                                                  {:default-deps
                                                   {'org.clojure/clojure {:fkn/version "1.10.0"}}})
ExceptionInfo Coordinate type  not loaded for library org.clojure/clojure in coordinate nil  clojure.core/ex-info (core.clj:4739)
I was expecting that would work based on the docs 😕

Alex Miller (Clojure team)23:09:04

well it’s failing to understand the nil coordinate in :deps

Alex Miller (Clojure team)23:09:12

that’s the fall-through of a multimethod

arrdem23:09:44

diff --git a/src/main/clojure/clojure/tools/deps/alpha.clj b/src/main/clojure/clojure/tools/deps/alpha.clj
index 6293734..f4e06c1 100644
--- a/src/main/clojure/clojure/tools/deps/alpha.clj
+++ b/src/main/clojure/clojure/tools/deps/alpha.clj
@@ -178,7 +178,7 @@
             coord-id (ext/dep-id lib use-coord config)]
         (when verbose (println "Expanding" lib coord-id))
         (if-let [action (include-coord? version-map lib use-coord coord-id parents exclusions verbose)]
-          (let [{manifest-type :deps/manifest :as manifest-info} (ext/manifest-type lib coord config)
+          (let [{manifest-type :deps/manifest :as manifest-info} (ext/manifest-type lib coord-id config)
                 use-coord (merge use-coord manifest-info)
                 children (canonicalize-deps (ext/coord-deps lib use-coord manifest-type config) config)
                 use-path (conj parents lib)
Variable naming bug 😕 As currently written deps.alpha keeps the original dependency coordinate even after figuring out what coordinate it wants to use by consulting the override and else mapping, so if the original mapping wasn’t to a valid coordinate as here even if a valid coordinate is discovered in the defaults resolution will blow up.