Fork me on GitHub
#beginners
<
2019-07-24
>
sova-soars-the-sora00:07:53

how can i get lein to reload things? i'm using the reload middleware with ring but i edit the clj file and no change..

noisesmith00:07:41

the reload middleware only acts when new requests come in, you can use (require 'some.ns :reload) in a repl (this works with clojure alone, not a lein feature)

noisesmith00:07:02

there's also :reload-all to recursively reload

sova-soars-the-sora00:07:44

it's working, with reload/wrap-reload

sova-soars-the-sora00:07:58

thanks many for your help.

sova-soars-the-sora01:07:19

I'm getting a weird message on my serverbox

sova-soars-the-sora01:07:28

v@n1:~/cushion/resources$ lein run Could not transfer artifact org.clojure:core.unify:pom:0.5.7 from/to central (https://repo1.maven.org/maven2/): Received fatal alert: protocol_version This could be due to a typo i

sova-soars-the-sora01:07:42

can there please be a neural net trained on working PROJECT.CLJ? lol

sova-soars-the-sora01:07:15

unmatched delimiter ) and there is only one open paren and one close paren in the whole damn file

hiredman01:07:36

It isn't a typo

hiredman01:07:27

Lein is guessing that if it has an error fetching a dependency it is because you mistyped the dependency

hiredman01:07:20

But in this case the error is due to using an old jvm that defaults to a version of tls that most servers have stopped acceptting

hiredman01:07:42

You can Google the error message and read all about it

sova-soars-the-sora01:07:55

thanks, i did not have much luck googling it.

seancorfield01:07:41

Those were the first two search results for me from Could not transfer artifact maven: Received fatal alert: protocol_version using Bing.

sova-soars-the-sora01:07:49

@hiredman @seancorfield thanks, updating java worked even though it seemed to not work.

4
sova-soars-the-sora02:07:33

Now i'm getting a "Exception in thread "main" Syntax error compiling at (compojure/response.clj:64:9)."

sova-soars-the-sora02:07:47

"Caused by: java.lang.RuntimeException: No such var: response/url-response"

sova-soars-the-sora02:07:54

okay I just had to make sure every dep was up to date

sova-soars-the-sora02:07:58

thanks, lesson learned / noted

Ashley Smith11:07:24

Hey everyone, this sounds a little vague but.. I have a trivial hello world backend and a reagent cljs front end. How do I actually go about connecting them? For something as simple as retrieving the string 'hello world' from the backend and then showing it in my front end app? Is there some sort of package I need to use? I'm using Vagrant and ansible, so the backend is running on a vm that I need to connect to through my front end. Can somepone point me in the right direction - is 'Luminus' what I'm looking for?

Mno11:07:01

if you're asking about how to get data from your backend: There's many ways (most commonly http requests). If you're asking how to see your frontend in your browser: Then it could be through an entry-point from your backend (so basically an endpoint that gives back the html with the javascript (reagent-frontend) and css. or hosting that entrypoint somewhere else, or opening it locally.

Crispin11:07:35

if you start a new project with something like lein new luminus my-proj +reagent +postgres (or +mysql) and then have a look at how the project is laid out that should give you a good starting point

Ashley Smith11:07:48

Oh no, I can see my front end easily, but it's just seperate from my backend

Ashley Smith11:07:26

just trying to make the hello-world of an app with a backend

Mno11:07:53

I don't really understand then, maybe follow crispin's advice?

Crispin11:07:23

that should give you a project with backend and frontend and database

Crispin11:07:38

it has a dev mode with hotloading

Crispin12:07:03

and when you lein uberjar it will build a release version, minified, that is all bundled into a single jar for deployment

Crispin12:07:27

any problems you can ask in the #luminus channel on this slack

Crispin12:07:26

http://www.luminusweb.net/docs/profiles.html has more options for the starting template

Ashley Smith12:07:08

Thank you! I'm thinking about using re-frame as that looks like it handles some of that stuff anyway

jaihindhreddy15:07:47

An alternative to luminus is Juxt's edge. Based on stuff like yada, integrant, tools.deps. And an (arguably simpler) alternative to reframe is fulcro. You can also look at pedestal's interceptor (which yada also uses) for a more expressive abstraction than middleware (ring). Just pointing out some stuff that expanded my mind when learning Clojure.

Ashley Smith15:07:38

Thank you! I'm going for reframe, ring and compojure 🙂

🍻 4
Ashley Smith14:07:55

would people recommend working with clj-http or ring?

fdserr14:07:04

what are you trying to achieve?

jumar14:07:43

they are different - you use ring for building an http server (more or less) and clj-http for communicating with servers/APIs from a client (perhaps calling other backend services from your server code)

Ashley Smith21:07:01

oops sorry I'm still a little new to slack I didn't realise I had this thread! I found ring and compojure (I think that's how you spell it)

Ashley Smith21:07:13

now I'm trying to get it all working in a vm with vagrant and ansible

jumar09:07:50

Vagrant and Ansible are really unrelated to this question I believe 🙂

manutter5114:07:59

I’d vote for ring, it’s widely used and has been around for a long time. Very stable.

Ashley Smith14:07:40

it does seem like it. Okay, so ring will be sitting on the server, do I need another package for the client to talk to it?

manutter5114:07:22

You’ll want something on the server side to manage your routes for you, probably compojure would be a good start.

manutter5114:07:32

The compojure lib will set up the server side so it knows how to respond to requests. Then you’ll use something (probably re-frame-http-fx) on the browser side to send requests to the server, and handle the responses when they come back.

Ashley Smith14:07:07

thank you!

👍 4
walterl14:07:37

i'm having trouble figuring out how to use lists/vectors. i understand the implementation differences between them (linked list vs array list) and what that implies, and i've read a few different "should i use lists or vectors?" blog posts/SO questions. i guess the part that's confusing me is why they have different semantics when used with seq functions (conj, cons, etc). isn't that counter to clojure's "code to abstractions" principle?

xi14:07:54

[12:22] <Raynes>    When would you want to use a list over a vector?
[12:22] <rhickey>   when generating code, when generating back-to-front
[12:23] <rhickey>   not too often in Clojure

xi14:07:39

Personally I always use vectors

👍 4
Crispin14:07:29

yep. agree. Use vectors unless theres a special reason you want a list.

✔️ 4
walterl15:07:27

yeah, that's the "rule of thumb" as i understand it. (and i saw that quote in a SO question simple_smile.) applying that, though, i found myself stumbling over the semantics a few times, and that got me thinking that i'm misunderstanding something.

walterl14:07:51

as it is, it means that i need to by very aware of the concrete type of the seq i'm working with, to know what effect a conj will have. it feels like i'm just missing something, and would appreciate being pointed in the right direction.

Alex Miller (Clojure team)14:07:43

conj and cons are not seq functions

Alex Miller (Clojure team)14:07:09

they are collection functions and have different polymorphic behavior based on the collection type

👆 12
Alex Miller (Clojure team)14:07:39

you might find some of these similar faq questions helpful https://clojure.org/guides/faq#conj

walterl14:07:25

that FAQ is very good! i guess i'll just have to read all of it 🙂

Alex Miller (Clojure team)14:07:15

please do! Most of the questions were added from questions like yours in these forums, so keep asking questions! :)

💯 4
Crispin14:07:19

they are consistent in their time behavoir (is that the term)? For example conj always places in the optimal position (head of a list, tail of a vector). cons is for constructing cons cells, so doesn't apply to vectors.

walterl14:07:33

that makes a lot of sense. thanks @alexmiller, @crispin. i'm off to read those links 🙂

🍻 4
Crispin15:07:04

There is a lot of deep thought behind the design decisions. Like when I first saw (contains? [:a :b] 1) => true I thought it was wrong. But then when it was explained, my mind was blown at how correct it was 🤯

jaihindhreddy15:07:39

Yup. The way most fns in core depend on well thought out abstractions and not concrete DS impls is amazing, and pleasantly surprises me repeatedly. It "just works" while doing close to no magic.

dpsutton15:07:30

there's a lot of thought for sure, but that's just an implementation detail in this case right?

dpsutton15:07:13

and a misleading one in my opinion

andy.fingerhut15:07:31

I doubt that many people use contains? to find out whether an index is in range for a vector or an array in Clojure, given that is not very often a useful thing to do (or at least I haven't wanted to use contains? for that), but that behavior is part of the official doc string of contains?. Not sure whether that affects your categorization of it as an implementation detail or not.

jaihindhreddy15:07:27

I don't think it is an impl detail. contains? tells whether a key is present in an associative thing.

jaihindhreddy15:07:35

And a vector is an associative thing

Alex Miller (Clojure team)15:07:44

it's mostly useful when using something like get-in to dive through a structure that is a mix of vectors and maps

Crispin15:07:25

Yep. vectors are keyed by their index, not their contents. Sets are keyed by their contents, and so (contains? #{:a :b} :a) => true. Its actually completely consistent.

dpsutton15:07:41

its certainly consistent and helpful in some situations.

dpsutton15:07:08

i think the "mind blown at how correct it was" is a bit more enthusiasm than i have

Crispin15:07:41

Small things impress small minds, I suppose. 😋 I had only thought about it shallowly, and its another example of the deep thought behind the design of clojure.

Ashley Smith15:07:09

Hello, I have a question about use vs require. I've read that use is basically the same as require, but you can use all the name spaces functions. I wanted to use require with :as, but for some reason the following snippet won't work if I try (:require [ring.adapter.jetty :as jetty]):

(ns server.space.core
  (:gen-class)
  (:use ring.adapter.jetty))
; (:require [ring.adapter.jetty :as jetty]))


(defn app-handler [request]
  {:status 200
   :headers {"Content-Type" "text/html"}
   :body "Hello from Ring"})

(defn -main
  [& _]
  (run-jetty app-handler {:port 8080})
  ;(jetty.run-jetty app-handler {:port 8080})
The command run-jetty is the problem as it cannot be found.

Alex Miller (Clojure team)15:07:38

use is require + refer-all

Ashley Smith15:07:08

That's what I read, I just didn't use /, I used . instead when doing jetty/run-jetty

Crispin15:07:03

jetty/run-jetty

Ashley Smith15:07:31

oh gosh that feels dumb 😛

Crispin15:07:11

not dumb. this is the channel for it.

eskemojoe00716:07:53

I have my repl up and running, then I add a package to my project.clj dependencies. Do I have to restart my repl to get that package available?

eskemojoe00716:07:57

Or is there some slick way to do that?

Alex Miller (Clojure team)16:07:19

generally, yes you have to restart your repl

Alex Miller (Clojure team)16:07:43

however, there are various plugins or ways to get this to work in a limited way

Alex Miller (Clojure team)16:07:30

but they are fiddly enough, and adding new deps is infrequent enough, that imo they are not with using

eskemojoe00716:07:59

Fair. I tried to compare java.time with standard operators, and it got mad. So I need to add clojure.java-time

eskemojoe00716:07:58

Is there a reason I can't get this to work with clojure.java-time: (require '[jave-time :as time])

mtkp16:07:56

maybe jave -> java ?

😫 4
😁 4
walterl16:07:43

what is the "Right Way" to prepend 2 values to a vector (vec (cons 1 (cons 2 [3 4 5]))), (-> [3 4 5] (cons 2) (cons 1) vec), (into [1 2] [3 4 5]), (vec (concat [1 2] [3 4 5])), or something else?

andy.fingerhut16:07:46

@clojurians-slack100 The first thing to realize is that for Clojure's built-in vector, if you want the result to be a vector, it takes linear time to prepend an element, which is fine if you do it rarely, but a performance-killer if you do it commonly.

andy.fingerhut16:07:09

Given that, I don't think there is a "right way", because people rarely do it. As long as you don't actually choose a way that is slower than linear time, I'd say go for what is clear to you.

walterl16:07:46

to give some context, this is part of [this kata](https://github.com/gigasquid/wonderland-clojure-katas/tree/master/card-game-war): i'm taking pop-ing the "top" card from each player's deck, and putting it on the "bottom" of the deck of the player with the highest card. i'm using vectors for the decks, and that may very well be wrong.

andy.fingerhut16:07:08

Raising up a level, if you do want to do this as a frequent operation during run-time, it is worth asking what set of operations you want out of a data structure, and perhaps pick a different one that supports them more efficiently.

walterl16:07:05

i think that is exactly what i'm struggling with 🙂

andy.fingerhut16:07:07

If the operations you are referring to are limited to a few operations per second, for human reaction times, and to vectors limited to card hand sizes, I doubt you will ever notice a performance issue.

andy.fingerhut16:07:27

If you are trying to simulate billions of card games per minute, then it could be a performance issue.

walterl16:07:47

i understand, thanks 😬 👍

walterl16:07:11

then i guess (into [1 2] [3 4 5]) it is 🙂

andy.fingerhut16:07:16

If you ever do get into a situation where you want a persistent data structure like a vector with efficient add and remove operations at both ends, the core.rrb-vector library may be worth looking into. If you need remove-from-front, add-to-back only to be efficient, Clojure has the PersistentQueue type.

walterl16:07:18

i'll look into those, thanks

dpsutton16:07:41

https://github.com/clojure/data.finger-tree as well. although i've looked and never found of an example of this used in production

👍 4
walterl16:07:37

but now you're also touching on part of the modelling problem that i'm struggling with: i chose the back of a vector to represent the top of the deck, simply because that is the value that pop gives me. i.e. it was a very naive choice. was it "ok", though?

andy.fingerhut16:07:12

I know that core.rrb-vector has some outstanding bugs that have been found via its production use in the fipp pretty-printing library. I don't have performance numbers handy, but I believe the constant factors in the run-time efficiency are better for core.rrb-vector's data structure, vs. finger trees. That said, I do believe they both have good big-O run-time performance.

andy.fingerhut16:07:17

If the common operations are add-card-to-top, remove-card-from-top, and it is an uncommon operation to access the bottom of a deck, then top=end-of-vector is a good choice for Clojure vectors, to keep the frequent operations efficient.

walterl17:07:21

afaict it's only the one case where cards are added to the bottom of the deck (front of the vector), so it's probably fine. thanks, @andy.fingerhut! 🙂

Anik Chowhdury17:07:44

Can anyone know how to render same page using selmer in luminus?

noisesmith17:07:07

@anikchy.cuet93 you would invoke the rendering function to generate the return value of a route handler

noisesmith17:07:08

NB it's a back end only library, it doesn't do client side rendering

SgtZdog17:07:17

Hello all! I could use help getting Cursive setup. I'm trying to debug some tests in the leiningen generated test folder and I don't know how to get a debugger (repl or otherwise) to tie into 'lein test' code execution.

andy.fingerhut17:07:45

Someone here may be more familiar with Cursive than I am, and could help you. I only wanted to mention that there is also a #cursive channel on Clojurians Slack that you may wish to ask there.

SgtZdog17:07:14

ty! I'll try there.

eskemojoe00717:07:17

Is it clojure esque to make tests for every function, or at least important ones? i see in many templates a simple test, but not lots of tests for various namespaces.

eskemojoe00717:07:31

Follow up question, is it normal to write tests for cljc files?

seancorfield17:07:25

@david.folkner I think Clojure devs write a lot fewer tests than you might see in some other languages since they "test" everything as they write it in the REPL (or at least they should 🙂 ).

seancorfield17:07:14

So test usage will vary a lot. I tend to use tests pretty heavily -- probably more than the average Clojure dev? At work, we have about 80K lines of code and 20K of that is tests.

eskemojoe00717:07:16

I get that, I got into the habbit of writing tests for things, so that way its repeatable.

eskemojoe00717:07:41

I have a validation function and struct in my cljc. Where does that test go?

eskemojoe00717:07:09

Since CLJC is kinda both. I have folders in my template for CLJS and CLJ testing.

seancorfield17:07:59

I don't use .cljc enough to have an opinion. I don't do any ClojureScript at all.

noisesmith17:07:19

@david.folkner I don't think you can claim cljc has test coverage unless it has tests that run under both clj and cljs

noisesmith17:07:35

especially because of reader conditionals

eskemojoe00717:07:50

Ahh...so make tests in both locations? That actually makes sense to me.

noisesmith17:07:04

a test can require a cljc file

eskemojoe00717:07:25

Current project is simple one, but I have some big plans for CLJC validation that will need really robust tests.

noisesmith17:07:29

that is, you can have a function, calling test/is, that is loaded in clj and cljs

noisesmith17:07:57

so it is written once, and exercised under both vms

eskemojoe00718:07:39

So make a test>cljc>appname>validation.cljc. Then in each other tests absorb that?

eskemojoe00718:07:12

Is that absorbtion done in the project.clj or within a actual file within each test>clj and test>cljs folders?

noisesmith18:07:27

if a deftest calls a function that calls is, that is works as a test assertion

noisesmith18:07:42

so you can require the ns from each side, and call the function that makes assertions

eskemojoe00718:07:35

That makes sense to me, but then I'm writing tests on both sides of clj and cljs, not a single test right?

noisesmith18:07:53

each deftest only calls a single function

eskemojoe00718:07:01

Yes, but multiple deftest.

noisesmith18:07:11

right - but they are stubs

eskemojoe00718:07:16

Which is fine, I just thought I understood that I could write a single deftest and run it both places.

noisesmith18:07:33

maybe there's a way to make leiningen do that, I'm really not sure

noisesmith18:07:11

leiningen's test running is its own thing - it does a tree walk and loads every ns under some directory

noisesmith18:07:40

as opposed to the clojure.test machinery, that runs every function with the magic test metadata

eskemojoe00718:07:46

So you say, make a test file for my cljc tests, then create standard functions (`defn`) that call test/is and/or other test functions I need. Then make simple wrapper deftests in each clj and cljs files. That makes sense to me.

noisesmith18:07:23

right - that's likely the simplest thing, unless lein knows how to load cljc files for tests (and load tests from multiple directories)

Ashley Smith18:07:08

hello.. its me again.. :'D I've been learning about compojure and ring today, but one thing is confusing me and their IRC is dead. On this page: https://github.com/weavejester/compojure it shows a small webserver serving different pieces of content per route. However, that snippet has no main function, and so if I place that into my core.clj file, it doesn't work. If I was to put a main function in there, surely I need the program to not end straight away, so I need to stall it right? What's really going on here, what is the way forward? I currently have this: https://pastebin.com/2xddrrGz but the app-handler handles everything and ignores the other routes. Anyone with experience?

noisesmith18:07:59

it's odd to me that nothing in app calls app-handler

noisesmith18:07:38

and it's also odd that jetty is run with a specific handler, rather than the app which does routing

Ashley Smith18:07:49

They don't have an app-handler function in their snippet, thats just on there from their docs. I was going to get rid of it when I got this defroute stuff working

Ashley Smith18:07:15

don't look at my paste that's just what I have. What's confusing me is that their snippet seems like it doesn't do anything?

noisesmith18:07:26

OK - then app should be an arg to run-jetty, or your router would never get used

noisesmith18:07:52

and some route(s) would call app-handler to generate a result

Ashley Smith18:07:20

so in terms of my website, will my front end make calls using these routes? Is that what they're for?

noisesmith18:07:29

ring accepts multiple kinds of values - a string (implicitly code 200), a stream (same) or a hash-map describing result code, headers, body

noisesmith18:07:48

your frontend would make requests for those routes, yes

noisesmith18:07:01

usually using the AJAX object

Ashley Smith18:07:31

okay, learning. Sorry for being so slow with this stuff

Ashley Smith18:07:36

its my first time encountering it

Ashley Smith18:07:29

okay! So that looks like it's working! thank you

🍻 4
Owen M20:07:41

So I really wanna use clojurescript for my project, but the further I look into it, I think it might not be the right tool for my use case. Essentially I have a Web app using Firebase firestore as a datastore. It implements a realtime database, I'll have to do some manual configuration to ensure the realtime aspect is respected by Cljs. I read this to get an idea of how: http://timothypratley.blogspot.com/2016/07/reacting-to-changes-with-firebase-and.html. That's the first hurdle. My data is in the form of a bunch of tables & a binary tree. I am trying to transform that into a tournament bracket visualization, think of the world cup (kind of like this http://mediakar.org/wp-content/uploads/2014/07/d181d0bdd0b8d0bcd0bed0ba-d18dd0bad180d0b0d0bdd0b0-2014-07-12-d0b2-16-32-16.png). The binary tree is the knockout stage, the group stage is the tables. I have found some very nice react libraries such as: https://bkrem.github.io/react-d3-tree-demo/ which provide toggleable, zoomable tree visualizations. And I would look to implement something similar in Cljs. But I haven't seen anything similar in Cljs, is there any tooling or resources that could teach me how to implement my own interactive bracket? (zoomable + toggleable) Is Cljs the right language for my use case? I could really use some guidance, thanks.

Justin Duncan21:07:51

Is om-next still an active project? I am having a difficult time finding recent resources(<2years)

lilactown21:07:36

I think om-next is pretty much in maintenance-only mode. I would look at Fulcro as a modern edition of Om

✔️ 4
lilactown21:07:36

@owenmonagan you can use React and libraries in CLJS, or use d3 directly. firebase has a fairly straight forward JS API that should be usable from CLJS as well

lilactown21:07:09

it’s not going to be completely clear-cut, though, as you will probably end up translating a lot of JS into CLJS, which requires some familiarity with both languages

Owen M21:07:12

thank you!

Justin Duncan21:07:37

Thanks a ton, luckily I am a pro in JS 😄

johnj21:07:01

Is it common/good practice to wrap functions under the same name in a new namespace to "centralized" the API ? for ex: (defn do-foo [x] (ns.common/do-foo x...)

noisesmith21:07:00

it depends on why do-foo is even in another ns

noisesmith21:07:28

but no, it's not something you see a lot

noisesmith21:07:53

if anything I've seen (def do-foo ns.common/do-foo)

noisesmith21:07:07

for cases where our idea of doing foo matches what ns.common defines

johnj21:07:48

do-foo is a function that serves as util for other namespaces but also an api for that part of the app

johnj21:07:15

yeah, more like your example

johnj21:07:51

another option is code duplication

johnj21:07:30

guess its not a bad trade-off

bfabry22:07:16

pretty good practice imo for something where you want to say “this namespace is the api”

bfabry22:07:45

I guess it might mess up api doc generation though?

bfabry22:07:04

the (def foo x) form. the (defn foo [y] (x y)) form will generate fine

noisesmith23:07:56

amusingly, this almost works

user=> (defn foo "a doc string" [])
#'user/foo
user=> (def bar foo)
#'user/bar
user=> (doc bar)
-------------------------
user/bar
nil
user=> (alter-meta! #'bar merge (meta #'foo))
{:line 1, :column 1, :file "/Users/justin.smith/.Trash/finops-recon/target/e0c97b7b414aee8746db4bdaacde369a3807c0c2-init.clj", :name foo, :ns #object[clojure.lang.Namespace 0x4a3cef67 "user"], :arglists ([]), :doc "a doc string"}
user=> (doc bar)
-------------------------
user/foo
([])
  a doc string
nil

noisesmith23:07:03

I wonder when nrepl started putting source forms in the .Trash directory

bfabry23:07:50

that might even be better. as any other useful stuff (docstrings, specs etc) only needs to get defined in one place then