Fork me on GitHub
#beginners
<
2017-09-06
>
donyorm01:09:39

@dimovich An important note: luminus is not really a framework, more of a premade, preconfigured collection of composable libraries. Still super useful and a great way to get started

funkrider03:09:39

Hi - I am new to clojure and wondering if there is a good resource that explains how state is maintained within a typical clojure app? For example I want to know what exactly does def-ing an atom within a namespace file actually do? Is the atom visible globally for example and what does changing the state of the atom do when you are in a REPL?

noisesmith03:09:33

all namespace level bindings are globally visible (but, of course, namespaced)

noisesmith03:09:54

changing the state of the atom in the repl changes the only global value of that atom

noisesmith03:09:00

for state that represents initialized resources, it's best to use a library like stuartsierra's component or weavejester's integrant

noisesmith03:09:41

in that case the state would be visible as a var during development, and would be an ephemeral shared binding visible to components that use it in production

dimovich05:09:04

@eggsyntax @genec @donyorm thanks for the suggestions!

lepistane17:09:49

Could anyone walk me through deploying app to heroku? it's my first deploy and my first clojure app so assume i am noob

lepistane17:09:21

i saw https://www.heroku.com/java (clj tab) is it really this easy??

hmaurer19:09:43

hi! have you managed to do it?

rcustodio18:09:44

Hi... I would like to know if (:gen-class) is necessary? Or just for the core with -main? (I use Java Interop but not the otherwise)

rcustodio18:09:55

When to use it

noisesmith18:09:50

you only need gen-class if you need to create a class for something from java to call

hmaurer19:09:11

you need it for the namespace containing -main too, right?

hmaurer19:09:28

oh, because it’s called from java I assume

noisesmith19:09:33

without gen-class you can do java -cp my-uber.jar clojure.main -m my.ns

noisesmith19:09:10

though yeah, you need gen-class or a shim if you want a jar that can be run directly without such a trick

hmaurer19:09:47

@noisesmith do you still need to AOT compile that namespace?

noisesmith20:09:23

no- since clojure.main is already compiled, you don’t need aot or gen class to start your code that way

noisesmith20:09:51

also, you can use a similar trick to use your production jar to start up a repl that has all your namespaces in scope but doesn’t run your main

noisesmith20:09:14

(sometimes useful for emergency exploritory debugging)

hmaurer20:09:14

oh I see, so you invoke clojure.main which will then compile and invoke my namespace

noisesmith20:09:27

that’s exactly it, yes

noisesmith18:09:21

and even then, there’s the alternate choice of having the client call your code via clojure.lang.RT clojure.java.api.Clojure or writing a small java wrapper that uses RT yourself

noisesmith18:09:49

also, there are a few categories of bugs that never happen if you avoid aot and gen-class, so there’s decent reasons to avoid it if possible

noisesmith18:09:35

oh, I guess RT isn’t the right entry point any more, now they recommend clojure.java.api https://clojure.org/reference/java_interop#_calling_clojure_from_java

rcustodio18:09:05

Okey... another.. what is the best way to manage state in clojure? (erlang the state is always received as a parameter), thinking about immutable we always have to drop and create a new one, but how to do that in clojure when for example you use dbcon in several namespace

rcustodio18:09:22

I'm having some trouble to understand that

noisesmith18:09:40

some popular libs for this include stuartsierra/component and weavejester/integrant

noisesmith18:09:15

what ends up happening is that you have a global top level binding of your stateful components at dev time, and in production it’s passed as an argument to the things that use it

noisesmith18:09:42

there’s an alternative called mount that just makes everything global but gives you shorthands to control the state

rcustodio18:09:03

global is bad for functional, right?

noisesmith18:09:24

that’s arguable - for things that are immutable, typically global is better than hidden is

noisesmith18:09:34

for stateful things, there’s active argument

noisesmith18:09:41

if you start with a full featured web app template, they’ll typically be opinionated and offer some sort of app state management setup by default

noisesmith18:09:33

(eg. luminus, liberator, pedestal)

rcustodio18:09:54

Hmm, I understand, lein template luminus x?

noisesmith18:09:14

lein new luminus

rcustodio18:09:46

okey, thanks very much

rcustodio18:09:13

State is kind of auto when I read erlang code (I don't program erlang, but a friend does)

noisesmith18:09:26

each of the popular ones have a few options (eg. if you want to set up a frontend SPA using cljs and a react wrapper with the figwheel dev tool)

rcustodio18:09:19

I will take that as a reference to lean how to manage state in clj... but I'm not building a web app, at least not for now

noisesmith18:09:21

yeah - erlang is definitely a bar other langs should be aiming for. Clojure tends to be better for pragmatics (high performance, library availability) but definitely isn’t as resilient

noisesmith18:09:13

if you aren’t making a web app, you could just start with the example code on the component or integrant github pages

rcustodio18:09:20

Mayber one day this will be good (https://github.com/jfacorro/clojerl)

noisesmith18:09:27

since the web apps are doing a bunch of setup you probably don’t care about

noisesmith18:09:44

well, that loses the library and performance benefits of clojure

noisesmith18:09:57

there’s also LFE which is inspired heavily by clojure

rcustodio18:09:16

I dunno about LFE

rcustodio18:09:34

I see.. thanks

rcustodio18:09:42

It's the "clojure" for erlang vm, seems like it

noisesmith18:09:20

it’s definitely the lispy erlang that I hear about the most at least

noisesmith18:09:51

it’s not nearly as much like clojure as the one you linked though

rcustodio18:09:15

One of the advantages of clojure is the JVM, lfe or clorjerl doesn't have that

lepistane19:09:50

when i push my project to heroku while it's doing it's thing i get

WARNING: Use of undeclared Var cljs-time/core at line 634 /tmp/build_0f5901ac8b59834755b6b827adb2602c/target/uberjar/cljsbuild-compiler-0/cljs_time/core.cljs
http://htembh.herokuapp.com - app error google cant help me what do i do?

hmaurer19:09:27

@lepistane your app is a ClojureScript app?

lepistane19:09:41

it's full stack one yes

lepistane19:09:57

based on luminus template @hmaurer

hmaurer19:09:20

Mmh. I am not familiar enough with Clojure/Script to help about the warning, but until someone more competent than I shows up: what happens if you ignore the warning? 😄

hmaurer19:09:44

Ah, app error

hmaurer19:09:57

Did you check the heroku logs? (on the dashboard)

lepistane19:09:51

it might be the database

lepistane19:09:57

could you tell me how to set up that

lepistane19:09:16

so it does the job of profiles.clj

hmaurer19:09:40

What database do you need for your project?

hmaurer19:09:52

If you are just trying out Clojure I would first deploy a project without a DB

hmaurer19:09:58

but Heroku has a free postgres tier

hmaurer19:09:11

you should be able to add it as an addon to your application on the heroku dashboard

lepistane19:09:15

i need db to get questions/answers for app

hmaurer19:09:22

it will then put the postgres connection string in an environment variable

hmaurer19:09:33

which you can then use in your Clojure code to connect to the DB

lepistane19:09:31

but dont know where to add env variable and all that

hmaurer19:09:41

Go in “settings”, “reveal configs vars”

hmaurer19:09:53

it should tell you the name of the env var containing the postgres connection string

hmaurer19:09:17

(you don’t need to add it; Heroku adds it automatically, you will only need to use it in your Clojure code)

lepistane19:09:57

not sure where to put that string in my clj code

hmaurer19:09:46

Not sure. Is your code exactly matching a luminus template? And in that case, can you send me the command you used to generate the project?

hmaurer19:09:49

So I can take a look

lepistane19:09:53

https://github.com/StankovicMarko/htembh - project added heroku remote then git push heroku master

hmaurer19:09:05

@lepistane ah, it’s already using the DATABASE_URL env var, so it should just work once the heroku addon is provisioned

hmaurer19:09:10

you might need to restart your app though

hmaurer19:09:23

and run the migrations on the DB

hmaurer19:09:30

not sure what the best way is to do that

lepistane19:09:40

it works now o.O

lepistane19:09:00

oh my god it might've been the wait 5 min till db becomes available

hmaurer19:09:09

yeah maybe 🙂

lepistane19:09:25

one more thing

lepistane19:09:47

before i express my gratitute

lepistane19:09:54

how do i populate it?

lepistane19:09:02

i saw there is pg:copy or something like that

lepistane19:09:14

maybe i can copy local db to that on heroku?

hmaurer19:09:32

On the readme of that github project it mentions you should load a bunch of sql files in the DB. This should guide you in how to connect to the DB from your laptop: https://devcenter.heroku.com/articles/connecting-to-heroku-postgres-databases-from-outside-of-heroku

hmaurer19:09:55

I would personally just get the connection string and use a GUI (e.g. Sequel if you are on os x)

hmaurer19:09:09

Assuming Heroku allows remote connection to Postgres DBs, but it appears they do

lepistane19:09:14

also 😞

Failed to load resource: the server responded with a status of 500 (Internal Server Error)

hmaurer19:09:35

that might be because the DB migrations haven’t been ran; check the heroku logs

lepistane19:09:51

yea that's true

lepistane19:09:53

i am an idiot

hmaurer19:09:16

heroky allows you to basically start a bash shell on a dyno

hmaurer19:09:41

You might be able to run lein migratus migrate there; I am not quite sure though

lepistane19:09:51

you said something about using GUI i can use pgadmin 4 and connect to that db

lepistane19:09:06

create those tables manally

hmaurer19:09:08

yeah I think so

lepistane19:09:15

that seems easiset

lepistane19:09:44

i will try something

lepistane19:09:51

thank you ver much

hmaurer19:09:51

so you can just manually run them in order if you want to

hmaurer19:09:01

(the .up.sql ones)

hmaurer19:09:10

you’re welcome 🙂

lepistane19:09:15

thank you ❤️ you are very kind and helpful

rcustodio22:09:29

Silly question... defrecord / defprotocol cannot have private funcs?

alexmiller22:09:43

they are not objects

rcustodio22:09:18

If I need private so I use (defn-) only

alexmiller22:09:07

even those are not actually private (the vars are still globally accessible)

rcustodio22:09:00

I understand, thanks!!

rcustodio22:09:11

Functional there is no private then

alexmiller22:09:32

but regardless protocol methods cannot be marked as private - the whole point of implementing an interface or a protocol is to provide a public implementation

rcustodio22:09:57

I understand

seancorfield22:09:08

(since we hardly ever have mutable state in Clojure, you might ask yourself "What do I want private functions for?"...)

didibus06:09:42

I believe a true private would be a useful security tool. I think its one of the reason Java 9 is going back to private having no mechanism of being accessed at all.

didibus06:09:21

But I'd rather see it as its own thing, like mark something as secure, or even better, having first class capabilities of some sort: "https://en.wikipedia.org/wiki/Capability-based_security"

didibus06:09:16

So you could restrict access to certain Vars to only specific code which had explicit access.

didibus06:09:08

I'm thinking:

(def ^{:secure :login} creds {:user "aa" :pass "bb"})

(defn ^{:permission :login} login [] ...)
Then at compile time, :login is replaced by a crypto-key, and access of creds is automatically authenticated with it. The login fn would know it, but no other method would.

didibus06:09:45

Am not an expert on capabilities though

hmaurer23:09:53

@seancorfield the only use-case I can think of is trying not to leak implementaton details out of namespaces

hmaurer23:09:21

but even then..

tbaldridge23:09:35

use multiple namespaces then

alexmiller23:09:53

well I’d say the main reason is to communicate to a user which parts of a namespace I publicly commit to supporting