Fork me on GitHub
#beginners
<
2016-01-29
>
polymeris00:01:14

thanks, slester

Josh Horwitz02:01:59

Has anyone ever felt like they will never be able to jump out of the beginning knowing the syntax into actually using Clojure? That’s where I am and have been, it’s frustrating!

jonahbenton02:01:12

@joshua.d.horwitz: yes- that's pretty common for me, in fact. i was reading about clojure off and on probably for about a year before i wrote any code

jonahbenton02:01:06

and i struggled a lot with the reading- coming largely from the C-style languages, though i had some lisp and scheme long long ago

jonahbenton02:01:57

the absence of syntax- like the absence of an else signal in an if statement- was very difficult to get my brain around for reading, much less writing

jonahbenton02:01:47

my suggestion would be- open a repl, and just start by typing something like (println (str "hello" "world"))

seancorfield02:01:58

@joshua.d.horwitz: Yeah, it can be a big shift from just "playing with Clojure" to actually "programming with Clojure". There’s a lot to get your head around in terms of the mindset for building things in a functional style.

seancorfield02:01:22

@joshua.d.horwitz: What have you worked your way through in terms of exercises? Clojure Koans? 4clojure?

Josh Horwitz02:01:07

I’ve made it through almost all of the Clojure Koans and up to about 100 in 4clojure

seancorfield02:01:19

I’d say you’re doing pretty well then!

jonahbenton02:01:35

yeah, that's great!

seancorfield02:01:37

What do you feel is the biggest obstacle to taking the next step?

Josh Horwitz02:01:13

But to be honest, I really didn’t understand what I was doing and had to look up hints

seancorfield02:01:07

I’ve been doing Clojure in production for five years and I still have to look stuff up all the time simple_smile

jonahbenton02:01:20

yeah, everybody is always learning and looking things up

jonahbenton02:01:00

if you like puzzles and games you could set yourself a task of encoding the rules of a game that you like in clojure

mj_langford03:01:13

While 4clojure has some interesting problems, you can write great software while being unable to solve much of it

mj_langford03:01:30

@joshua.d.horwitz: I found the http://purelyfunctional.tv courses were a huge change from playing to writing real utilities

seancorfield03:01:35

What helped me get over that initial hump was to take some code I had at work and rewrite it in Clojure several different ways.

seancorfield03:01:20

If you normally program on the JVM, you can always try those Clojure versions out in situ as a replacement for your original work code.

donaldball03:01:28

I never really felt comfortable with clojure until I learned the basics of paredit, tbqh

donaldball03:01:53

The ability to edit my code as sexps gave me the ability to easily experiment with different forms until I could develop my own aesthetic

Josh Horwitz04:01:49

I have never really used paredit

seancorfield04:01:50

Yeah, I hadn't thought of that... Seeing code-as-forms rather than code-as-a-string-of-characters does help with some internalization of Clojure's "way of thinking"...

seancorfield04:01:22

I've gotten so used to editing with s-expressions that I tend to forget I'm doing more than "editing text". I've even got to the point where paredit-convolute-sexpr seems fairly natural (on the few occasions I need it).

seancorfield04:01:58

So @joshua.d.horwitz what sort of projects would you like to try to tackle with Clojure to get into really "using" it?

Josh Horwitz04:01:36

I’m not sure, I’d love any guidance or help, or any good open source projects, I have a tough time focusing lol

seancorfield04:01:53

I think you're going to need to give us something in order to make recommendations! 😸

seancorfield04:01:25

By which I mean you need to narrow the space a bit...

gabehollombe07:01:44

@polymeris: reductions is an interesting function, too, if you want each step along the way — https://clojuredocs.org/clojure.core/reductions

Josh Horwitz14:01:21

@seancorfield: I’m going to try and think of something! I was thinking of making a website or something along those lines, where family can go to see updated info about my daughter

clojuregeek15:01:56

anyone seen this error before? I can't figure it out 😞

Exception in thread "main" java.lang.NoSuchMethodError: com.fasterxml.jackson.core.JsonParser.setCurrentValue(Ljava/lang/Object;)V, compiling:(core.clj:210:1)

jonahbenton15:01:59

@clojuregeek: check your lein deps :tree to see if there are multiple versions of jackson

clojuregeek15:01:27

Hmm something with [metosin/compojure-api "0.22.0"] ...

clojuregeek15:01:00

and maybe conflicts with [amazonica "0.3.43"]

jonahbenton15:01:52

yeah. a lot of services depend on jackson under the hood. try using :exclude in the dep that points to the older jackson

clojuregeek16:01:08

i did that.. and a few other things, I'm just going to try a different solution because i need this done. Thanks for the debugging help simple_smile

sveri17:01:19

@clojuregeek: I would try to explicitly include the version you need in your project.clj and exclude everywhere else it is used

clojuregeek17:01:06

i don't directly use jackson ...

Kamuela17:01:30

What’s an HTTP server library that’d be idiomatic Clojure of something that express does with Node.js?

shaun-mahood17:01:49

@kamuela: What parts of express are you thinking of? If you mean an entire framework, the closest thing I'm aware of is http://www.luminusweb.net/

shaun-mahood17:01:04

Lots of good docs on that site that should help you ask more specific questions if it's not exactly what you need.

Kamuela17:01:30

shaun-mahood: something that would expose me to HTTP requests and let me work with them

shaun-mahood18:01:06

Ok, then you could also look at Compojure https://github.com/weavejester/compojure

shaun-mahood18:01:30

It's about as close to standard as things get as far as I can tell, and I've seen it recommended a couple of times as a great way to see what idiomatic Clojure code looks like

Kamuela18:01:32

thanks @shaun-mahood checking it out

Kamuela18:01:27

thanks again @shaun-mahood this looks like exactly what I needed to play with

Kamuela18:01:34

I’m just playing around and I already feel some of that Clojure productivity

shaun-mahood18:01:18

@kamuela: Are you looking at Luminus or Compojure?

Kamuela18:01:17

Compojure**

shaun-mahood18:01:18

Nice. There are lots of good materials online too if you run into any issues.

jonahbenton18:01:15

@kamuela compojure is definitely easy to get up and running with, the code style is familiar for people coming from other platforms, and it's likely the most commonly used routing library. definitely worth starting with. that said, something that distinguishes clojure from other languages is the ability to take what's called a "data driven" approach- define what you can in data, rather than in code. The pedestal web framework takes this approach: https://github.com/pedestal/pedestal. So, where compojure uses macros to define routes, pedestal uses a data structure. Where ring- the web processing library underneath compojure- uses functions wrapping functions for middleware- pedestal defines middleware in a data structure. It can be a harder concept to grok, coming from other languages, but can lead to more power when one has mastered it In any event- good luck!

Kamuela18:01:05

@jonahbenton: Testament to the strength of this community that you immediately tried to get me to change my mind simple_smile

Kamuela18:01:17

I will take a look as well

shaun-mahood18:01:39

I think both are excellent options and really should give Pedestal a try one of these days

jonahbenton19:01:14

@kamuela heh, not trying to change minds, just pointing out another guidepost in the learning process. simple_smile have fun!

krchia19:01:53

hi, anyone familiar with yesql?

krchia19:01:38

the function i defined in sql when called in clojure will return a list containing a hashmap

krchia19:01:01

i’m wondering if it’s possible to just get the hashmap? or is the list there for multiple values from a query

jonahbenton19:01:48

@krchia yes, the existence of the list represents the possibility that multiple rows may be returned from a query. and each row is a hashmap where keys are columns and values are row elements. so if you have a query that will always return one row, just take (first) of the list

krchia19:01:30

ah geez, in the middle of asking i realized that i hadn’t considered the possibility that queries might return more than 1 result..

krchia19:01:34

im such a noob

jonahbenton19:01:46

sure, no worries, good luck!

krchia22:01:45

hi i’m trying to figure out what’s the biggest length that a encrypted password will be

krchia22:01:55

is there a better way than

krchia22:01:57

(defn big [num] (loop [x num max 0] (let [encrypt-count (count (encrypt-password (random-string 20)))] (cond (= x 0) encrypt-count (> encrypt-count max) (recur (- x 1) encrypt-count) :else (recur (- x 1) max)))))

krchia22:01:02

i’m using buddy

lucien.knechtli22:01:18

what hasher are you using?

lucien.knechtli22:01:53

honestly, most hashers always have the same length output no reason to do a loop

jonahbenton22:01:46

@krchia yeah, hashing will produce the same length data, no matter what the input; encryption will produce encrypted text in blocks of fixed size

jonahbenton22:01:55

where the number of blocks will correspond to the length of the source. so just encrypt any string that is the maximum length password- that's the maximum length encrypted version

lucien.knechtli22:01:57

shouldn't even be neccessary to use a max length pass - all the commonly used hashers output a constant length digest (IE sha-256 outputs a 256 bit digest no matter what)

jonahbenton22:01:13

yeah- that's hashing- the above is encrypting, so it's reversible

lucien.knechtli23:01:48

true - although most of the time when people say they're "encrypting" a password it's a misnomer

krchia23:01:01

oh right, it’s buddy/hash

krchia23:01:38

i didn’t know there was a difference between both

lucien.knechtli23:01:45

so yea - constant length, which depends only on the hash function you're using

krchia23:01:55

sorry, id on’t seem to be getting constant length

krchia23:01:10

i do something like (count (encrypt-password "111”)) and i get different values

lucien.knechtli23:01:17

really? what's the output look like?

krchia23:01:29

110, 174, 103

lucien.knechtli23:01:09

er what exactly is your encrypt-password function doing?

krchia23:01:31

hash/encrypt from buddy.hashers

lucien.knechtli23:01:28

you should be getting something like "bcrypt+sha512$4i9sd34m..."

lucien.knechtli23:01:14

hashers/encrypt?

krchia23:01:28

it does look that without the count

jonahbenton23:01:38

(hashers/encrypt "111") always gives me a 98 char string

jonahbenton23:01:01

user=> (hashers/encrypt "111") "bcrypt+sha512$a80d3246e31344e0d9720455473b6f40$12$be9630434562ef5d7f029a5ebf71f479d85a6f6a2f968f9b" user=> (hashers/encrypt "111") "bcrypt+sha512$01e85c69303b2a727052c6cd619b69ee$12$952a5feb253c506bd592d89f3d7dc93cd40f242f81a8ef41"

lucien.knechtli23:01:25

yea, thats what it should look like

krchia23:01:44

that’s weird, i’m getting strings of different length with the same input

krchia23:01:52

is it my version of buddy or something?

jonahbenton23:01:59

(hashers/encrypt ) of any length string will give you 98 chars back

krchia23:01:30

i’m using 0.9.0

krchia23:01:55

worthanot0.server> (encrypt-password "111") "bcrypt+blake2b-512$38926065266c68dba599d48e2d6f1ad5$12$cb93f46b437b5651f9dc4880cb8dfe76725f90a4f12721be" worthanot0.server> (encrypt-password "111") "pbkdf2+blake2b-512$75b178d2fe9e8c582887d8b9$50000$81f5b68911a37ae47af52cd45d6d41fdee26640b7afba360d201d346161ce537002ae409ac80537e3b3fc061ee120b16889358e7a3a8124e0967fc5e95023ac7" worthanot0.server> (encrypt-password "111") "bcrypt+blake2b-512$26c43be256d419042903901569177e4e$12$18b9e413404225e9377b1610634cc13b4cfe091cf695cc64"

lucien.knechtli23:01:46

wow what. its switching encryptions

krchia23:01:09

i don’t specify any specific identifier..

lucien.knechtli23:01:29

try (hashers/encrypt "secretpassword" {:alg :pbkdf2+sha256))

lucien.knechtli23:01:10

that should keep it consistent. no idea why its switching

krchia23:01:48

i should’ve looked more closely at the output

lucien.knechtli23:01:49

or just set it to the default :bcrypt+sha512

krchia23:01:00

i will do just that. thanks simple_smile

Kamuela23:01:52

I think Clojure for JVM is straightforward but I'm actually still confused by how this builds for JS

jonahbenton23:01:54

@kamuela buddy is only for JVM, it uses the JVM library bouncycastle under the hood

jonahbenton23:01:01

sorry, wrong nick!

Kamuela23:01:36

No problem, I asked in a general sense @jonahbenton

lucien.knechtli23:01:20

pretty much everything i've seem about clojurescript suggests that it's a pain to compile multiple separate js files - if I want to make a non-SPA app, would the suggested approach be to have separate clojurescript apps which are routed to by something like nginx?

lucien.knechtli23:01:06

for instance - If I want a static landing page, with links to a couple pages which serve clojurescript, do I need to serve the static parts of the website and each page containing clojurescript separately?

seriousbug23:01:38

I managed to get multiple js files pretty easily with Boot, maybe you could try that?

seriousbug23:01:56

This was pretty helpful to begin with: https://github.com/Deraen/saapas

lucien.knechtli23:01:28

hm, i'll check it out. Wasn't able to figure it out using lein

lucien.knechtli23:01:18

pretty compelling usecase for boot if it makes it easy. I might just be looking at lein the wrong way though

seriousbug23:01:29

Same for me, I ended up switching from lein to boot because of that.

lucien.knechtli23:01:26

does boot have the equivalent of lein plugins? I've been using them pretty heavily

seriousbug23:01:13

It does, they are called tasks I think. This example project sets up automatic clojurescript reloading, like figwheel

lucien.knechtli23:01:37

nice. I'll check it out when I get a chance simple_smile

seriousbug23:01:49

Hope you find it useful simple_smile