Fork me on GitHub
#beginners
<
2018-06-07
>
ryan.russell01100:06:34

just a heads up... http://pragprog.com is has a coupon code order66 that will get you 30% off on any ebook, audio book or screencast!

ryan.russell01100:06:06

I just got Clojure Applied ($25.00) and Web Development with Clojure ($24.00) for a total of $34.30. Pretty good deal if you ask me 🙂

narayan01:06:04

Thanks @... just got myself 3 books for < $55! Worth the investment!

ryan.russell01101:06:44

what did you get?

kyselyradek01:06:55

Thanks a lot! I was just planning to buy some books from there 😂

narayan01:06:58

Programming Clojure, Web Development with Clojure & Clojure Applied @

ryan.russell01101:06:18

ah cool! We have the same Clojure library now haha

narayan01:06:30

Just a week back I had already purchased Getting Clojure by Russ Olsen

ryan.russell01101:06:26

I thought about getting that one.. but am still on the fence about it. I'm afraid it will be too much like Brave and True level... I get bored reading pretty easily... so I needed project based books to keep my mind engaged and see how it all goes together from a bigger picture....

ryan.russell01101:06:48

Getting Clojure seemed like it was based on "why" not "how".. I also figured that after Programming Clojure I wasn't sure how much more (or different) it could offer

narayan01:06:36

@ I guess we all have our own ways to learn ... myself I like example based books ... and we need to read books which panders to our learning style 🙂

ryan.russell01101:06:58

oh for sure... everyone learns differently! 🙂

ryan.russell01100:06:40

The question now is .. which one should I read first? I've read Programming Clojure and got tired of reading and moved on to doing Codewars and actually writing code... which one is a good follow up?

donaldball02:06:32

4clojure is a nice set of exercises

lady3janepl08:06:46

Right, so I have a “running with scissors” kind of question

lady3janepl08:06:16

Given a simplified example wherein: 1) I have a type X defined with deftype 2) with a :volatile-mutable field next which will only ever contain type X itself (or nil) 3) and a protocol function implementation that walks down the chain of Xes via said next field and loop-recur …is there any way I can set! the value of next field on an object down the chain that is not “self”, but I know that it is going to be of type X? (Still in that protocol function, inline implementation)

bronsa08:06:24

user=> (defprotocol p (f [_ _]))
p
user=> (deftype t [^:volatile-mutable a] p (f [_ x] (set! (.-a ^t x) a)))
user.t
user=> (let [t1 (t. 1) t2 (t. 2)] (f t1 t2))
1

lady3janepl09:06:16

thanks @bronsa 🙂

mhsmit09:06:30

@gadfly361: Working with sodium and implemented the rating component. How do I get it's value? (-> % .-target .-value) returns nil (https://react.semantic-ui.com/modules/rating)

troglotit10:06:49

When I want to have primitive with metadata should I just use ^:my-meta [a] and use it like 1-ary tuple?

gadfly36111:06:15

@mhsmit This is for using soda-ash (instead of sodium, CC @deg)

[sa/Rating
    {:max-rating 5
     :on-rate    (fn [_ rating-map]
                   (let [{:keys [maxRating
                                 rating]} (js->clj rating-map
                                                   :keywordize-keys true)]
                     (js/console.log "The maxRating is" maxRating)
                     (js/console.log "The currrent rating is" rating)
                     ))}
    ]

deg12:06:28

@mhsmit Take a look at Sodium's value->event-fn and value->atom-fn, both in core.cljs. They exist to sugar around the need to grab the second value from a Semantic-UI component.

deg12:06:09

FWIW, I hate those two function names, and would consider renaming if I get any better suggestions.

mhsmit12:06:53

@gadfly361 thanks... 😄 .. I did this (get (-> %2 js->clj) "rating")

gadfly36112:06:45

@mhsmit that works :)

aj07mm14:06:27

hi! I'm a little familiar with the language already. I want to know now how to structure a project in terms of business logic. How do you map the entities (if there is such a thing?). I mean what is the parallel of object oriented mapping of classes in Clojure?

aj07mm14:06:41

and if there is any material that I can study about that

alexmiller14:06:31

re oo mapping: don’t

alexmiller14:06:03

I wrote a lot about domain modeling in the first chapter of Clojure Applied if that’s of interest (some of that I would love to revisit now in light of spec’s release)

aj07mm14:06:22

How the modeling works in Clojure then?

alexmiller14:06:20

make maps with data

christian76714:06:41

Maps with specs 👌

manutter5114:06:50

@aj07mm Consider, here's a model for a customer contact: {:first-name "Somebody" :last-name "Something" :email ""}

manutter5114:06:56

A vendor contact: {:first-name "Somebody" :last-name "Something" :email ""}

manutter5114:06:31

A sales lead: {:first-name "Somebody" :last-name "Something" :email ""}

manutter5114:06:08

Now if you have a full-name function, it just works with Customer Contact, Vendor Contact, Sales Lead, etc.

manutter5114:06:52

(defn full-name [data] (str (:first-name data) " " (:last-name data))

aj07mm14:06:06

do you usually define it as a template somewhere in the project, more like a class?

manutter5114:06:54

It's possible, but often that's a premature optimization, at least in the early stages of development

manutter5114:06:27

The trick is to try and move your point of view from "I need to define all the nouns" to "I need to define all the verbs."

manutter5114:06:17

The OOP perspective sees everything in terms of defining a bunch of nouns with built-in behaviors, but that's inherently unnecessarily complex.

manutter5114:06:08

The FP perspective is to define the verbs, i.e. how does your data need to be transformed to accomplish your objectives.

petterik14:06:53

I recommend namespacing your keys also. So instead of :first-name, maybe :user/first-name or :your-product-name.user/first-name if it's the first name of a user in your system. Another example would be instead of :id, which could be anything, make it specific like: :youtube.video/id (if that's what it's referencing).

aj07mm14:06:59

@manutter51 that was clarifying!

manutter5114:06:03

I've found that a lot of your modeling actually happens outside of your code, such as in your database. Defining your tables (if you're using SQL) tends to define, or at least strongly guide, your data model in the code.

aj07mm14:06:41

how do you usually represent the relationships?

manutter5114:06:32

It depends, but you can do things like nested data structures (line items on an order, for example).

aj07mm14:06:38

I mean, that is not a good question

aj07mm14:06:48

what is the default database for a clojure project?

aj07mm14:06:10

a relational one? or there is some other model that suits the FP way of thinking?

manutter5114:06:13

Whatever you choose, you can use SQL, NoSQL, flat CSV text file, whatever

manutter5114:06:56

Datomic is pretty interesting, but I wouldn't start with that if I were just learning Clojure. SQL works just fine, or Mongo, or whatever you're already familiar with.

aj07mm14:06:56

I'm questioning because of the talks of Rich on Datomic

michael.gaare14:06:58

try Datomic if you really want to go whole hog

manutter5114:06:30

Definitely worth playing with Datomic.

aj07mm14:06:54

thanks everyone for the anwsers!

jgh14:06:15

datomic is really nice with clojure, but quite expensive if you're using it for a commercial project

jgh14:06:44

Personally I'm using Postgres but that's because I'm also using PostGIS which I can't really do through Datomic.

michael.gaare14:06:02

@jgh it’s free now actually

michael.gaare14:06:08

unless you want support

jgh14:06:23

I thought it was like $5000/yr after 1 year if you want updates

michael.gaare14:06:32

“support” 😄

jgh14:06:44

ah well updates are important for databases heh

jgh14:06:15

although i guess datomic isn't really the database

michael.gaare14:06:26

for Datomic, there’s not a lot of major bugfixes anymore, it’s more around bringing in new stuff

michael.gaare14:06:39

and yes, the actual data layer is something else

dylanrdrake15:06:34

When developing an SPA with Clojurescript and Reagent, what is common practice for getting the initial state of the app from the server? Do you do an ajax request back to the server on page load or is there a way to have the initial state preloaded in the atom when the user first requests the page?

noisesmith15:06:40

I've used a combination of rendering script tags setting values you can access into the template for config, and Ajax or websockets for runtime data

dylanrdrake15:06:55

So rendering the data in an html tag then populating the state atom with that?

dylanrdrake16:06:17

Could I create a <data> tag that contains an edn string then just read that into the state atom?

lee.justin.m16:06:52

why not just make an ajax call on load? seems much simpler and gives you a lot of control over how and when data gets loaded

dylanrdrake16:06:30

@ that's most likely what I am going to do. I just didn't know if making a request for the page then making another request for the data was considered inefficient because it is making 2 requests

lee.justin.m16:06:19

@ if you are worried about that kind of optimization you’re going to have to get really sophisticated because you’re talking about optimizations on the order of dozens of milliseconds. that’s a whole new world of hurt.

lee.justin.m16:06:51

just keep it boring. you’ll be much happier.

dylanrdrake16:06:54

oooh ok. thank you @

dylanrdrake16:06:20

I'm all for keeping it simple but I don't want to put what might be considered bad practice into the code of a project

lee.justin.m16:06:10

no its totally normal to make an ajax call to get user data once the SPA is loaded

dylanrdrake16:06:11

but it sounds like it's perfectly fine

noisesmith17:06:22

specifically I use a script tag for special tokens that should be known on load - just a few magic strings

noisesmith17:06:37

everything else is just ajax / websocket

joshkh19:06:55

just chiming in because why not - when dealing with data already stored in a session (such as a returning user) i feed that right into the constructor of the app. for example https://github.com/intermine/bluegenes/blob/dev/src/clj/bluegenes/index.clj#L85

joshkh20:06:17

@ out of curiosity, what's your go-to web socket library (if any)?

noisesmith20:06:38

in the past I used sente

joshkh20:06:35

i've been having major issues with sente, mainly a 5 second timeout after a first reconnect (aka user has authenticated). have you come across that?

noisesmith20:06:23

but I no longer work on a webapp and haven't used the latest sente

joshkh20:06:29

hmm, okay. i must have wired something backwards. thanks. 🙂

joelv15:06:42

is there a way to look at the resource paths when lein run is invoked? I'm having trouble loading my log4j.xml in the resources directory

noisesmith15:06:58

The resources are just entries in the classpath

alexmiller15:06:27

(System/getProperty "java.class.path")

noisesmith15:06:05

If you are running from a jar, make sure you are using io/resource and not io/file

noisesmith15:06:22

(if accessing it directly)

kwcharllie37919:06:29

Hi Clojurians! I am trying to develop simple command line. I am receiving following error:

Compiling reader.file
Compiling reader.cli
Compiling core.app
java.lang.IllegalAccessError: wrap-main does not exist, compiling:(app.clj:1:1)
Exception in thread "main" java.lang.IllegalAccessError: wrap-main does not exist, compiling:(app.clj:1:1)
	at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:3657)
	at clojure.lang.Compiler.compile1(Compiler.java:7474)
	at clojure.lang.Compiler.compile1(Compiler.java:7464)
	at clojure.lang.Compiler.compile(Compiler.java:7541)
	at clojure.lang.RT.compile(RT.java:406)
	at clojure.lang.RT.load(RT.java:451)
Here is my app: https://github.com/FieryCod/recomputing-with-swapped-operands I am unable to spot where I commit the mistake. Could you please help me?

noisesmith19:06:10

I'd expect process-args to blow up if :help wasn't in the opts because the cond is incomplete, but those files look like they should load at a first glance

noisesmith19:06:19

did you get that error when first starting the app, or when reloading after an edit?

noisesmith19:06:28

what command showed this error?

kwcharllie37919:06:00

both lein uberjar and lein run -m core.app -h

noisesmith19:06:55

for some reason your reader.cli ns is broken - I can't see why though - it loads without error but doesn't define anything

noisesmith20:06:58

this likely isn't the source of the problem, but those are all terrible namespace names - the point of a namespace is to differentiate something, and core.app and reader.cli etc. are extremely generic and high likelihood to clash with other projects that picked bad namespace names

noisesmith20:06:41

it's possible that something else on your classpath in fact already defines reader.cli namespace and doesn't have anything in it, but it's unlikely welp, lol

seancorfield20:06:58

It's definitely a name clash -- I renamed cli.clj to wrap_cli.clj (and changed the ns to reader.wrap-cli and it all worked.

seancorfield20:06:19

So there's something, somewhere defining reader.cli and clobbering your namespace.

noisesmith20:06:34

right, pick namespaces that do the job required of a namespace :D

kwcharllie37920:06:42

Thank you, thank you! I simply do not know how to correctly name them. It's because I came to clj world from the js.

noisesmith20:06:34

the point of a namespace (as with a js package) is to differentiate things. a generic name is a poor one because of the random likelihood that some other project already used it

noisesmith20:06:52

a js package named "code" or "app" would have the same problem

noisesmith20:06:47

the java convention is to reverse a domain you own and use it as a prefix, and I often go with that, eg. org.noisesmith.foo

kwcharllie37920:06:39

Ok thank you for your effort in teaching me. I really appreciate it. I will do like you told me.

seancorfield20:06:48

Using your GitHub username is often unique enough (fierycod.app, fierycod.reader.cli, fierycod.reader.file)

seancorfield20:06:07

Looks like it's something in Leiningen -- if I fire up @kwcharllie379’s project with clj, I can load the namespace just fine.

seancorfield20:06:51

It also loads fine in Boot.

seancorfield20:06:20

Hmm, I'm going to take back that assertion about Leiningen -- since I can create a fresh app, add reader.cli as a namespace (without tools.cli) and it loads just fine...

kwcharllie37920:06:43

Thank you @seancorfield. Last question is it possible to have a namespace named with dash? Like fierycod-app?

kwcharllie37920:06:13

I know that it's possible to name it like fierycod_app but I am wondering if dashes are also supported

seancorfield20:06:25

Yes, namespaces with - are fine -- but the filename must have _ in that position.

seancorfield20:06:41

so src/fiery_app.clj would have (ns fiery-app)

seancorfield20:06:54

(although single segment namespaces should be avoided)

kwcharllie37920:06:35

Ok but what if I want to have src/some-namespace/core.clj

kwcharllie37920:06:49

how the ns will look like then?

seancorfield20:06:24

No, the file would have to be src/some_namespace/core.clj with (ns some-namespace.core ...) in it.

seancorfield20:06:36

_ in filenames, - in namespaces.

kwcharllie37920:06:54

Ok i see so there is no possibility to have - in filenames

seancorfield20:06:39

I figured out the reader.cli issue -- you have test/reader/cli.clj which has the same namespace as src/reader/cli.clj so it is overwriting it!

kwcharllie37920:06:15

I must say that Clojure community is very active and I'm really glad that you're so helpful and so kind for others.

seancorfield20:06:45

Test namespaces should also be unique within your project. For src/reader/cli.clj you would normally write test/reader/cli_test.clj with (ns reader.cli-test ...)

kwcharllie37920:06:42

Ok understand now. Will note that. Thanks one more time 🙂

seancorfield20:06:27

In the #beginners channel, we love helping folks who are just learning Clojure!

kwcharllie37922:06:23

Got question about LOC of the core.clj. Why the code is so huge and it's not separated into various namespaces? Is there a rationale for that?

andy.fingerhut23:06:14

Some of the clojure.core namespace is actually spread across multiple files, via calls to "load", so it might even be more LOC than you are currently thinking. I suspect the idea was that everything in the clojure.core namespace is to be considered as a fairly large standard library available in all Clojure programs without having to have another require/use in your code.

andy.fingerhut23:06:58

Most of those functions I can think of are fairly general-purpose data manipulation functions.