Fork me on GitHub
#beginners
<
2017-09-26
>
genec00:09:21

@seancorfield thanks for the link, very useful. It's pointing me towards either maps or records as I'm building a small DSL

genec00:09:03

I'm still not clear on how to use core.match to pattern match on record types though.

genec00:09:30

but sounds like the advice is don't do it

seancorfield00:09:41

Yeah, I think core.match is rarely used in reality. It has a fairly specialized use case -- structural pattern matching isn't an idiom in Clojure like it is in some other languages.

seancorfield00:09:16

The default starting position is pretty much always "start with maps, switch to records only when you need them"

genec00:09:42

@seancorfield thanks, appreciate the advice

rcustodio01:09:06

is lein uberjar good?

rcustodio01:09:20

I see ppl remove it from a lot of projects

noisesmith01:09:45

wait, what do you mean by removing it from projects?

rcustodio01:09:06

from project.clj

noisesmith01:09:09

uberjar is a task that lein can perform, do you mean they remove the uberjar specific config?

noisesmith01:09:54

it's not apropriate to use uberjar on a library, and leiningen should not be generating uberjar config for a libarary project

rcustodio01:09:54

Sorry, it was my mistake, I was in a wrong folder... lol

rcustodio01:09:09

in library we use deploy?

noisesmith01:09:30

right, or install for local usage

rcustodio01:09:04

its kind of hard to adapt.. i'm used to npm.. which is easy to get private from github

noisesmith01:09:19

if what you want is to use a library like monger, you don't need to install it, just add it to your dependencies. If you need to use a library for your project, you'll need a private repo (or alternatively everyone can install it on their own machine, but having a private repo saves a lot of trouble)

rcustodio01:09:26

Yes.. I guess it does.. I'm trying with this https://github.com/tobyhede/lein-git-deps but it doesnt help at all

seancorfield02:09:30

@rcustodio You normally wouldn't pull in a dependency from GitHub in Clojure. What are you trying to do?

rcustodio13:09:07

Something like npm... which you use github ssh url to pull private dependencies

seancorfield15:09:05

I guess the simple answer is: don't do that -- it's not idiomatic in Clojure. Why do you want to do that? What problem are you trying to solve?

rcustodio15:09:43

We are developing libraries, but they are private, when we develop services we will need to use that private libraries... this lein-git-deps is practical like npm, easy to explain and use, and it doesn’t need an additional server to keep the private repo

rcustodio15:09:45

We don’t use aot, once here they said is a bad thing

seancorfield17:09:13

Ah, OK. Probably worth looking at running an internal Archiva repo or similar. For now if you're good working from your internal Git repo and SHAs...

rcustodio17:09:53

We still gonna use lein-git-deps, seems like its not idiomatic and the clojure community kind of disapproves it, but it's a practical way that will help us for now... thanks for your tips.. if lein-git-deps start to get in the way we see the archiva repo

genec11:09:52

Any idea why eval-match always matches on A? (defrecord A []) (defrecord B [x]) (defrecord C [x y]) (defn eval-match [x] (cond (type x) A "Type A" B "Type B" C "Type C" (str "No Match: " x))) (eval-match (A.)) (eval-match (B. 1)) (eval-match (C. 1 2))

sundarj11:09:55

that's not how cond is used

sundarj11:09:21

think you mean case?

genec11:09:50

@sundarj I tried case, but I couldn't get it to match, it always returned No Match (defn eval-match [x] (case (type x) A "Type A" B "Type B" C "Type C" (str "No Match: " x)))

sundarj11:09:49

see what (type x) is outside of the function

genec11:09:24

This works, but was trying to figure out other ways to do matching (defn eval-cond [x] (cond = [(type x) x] [A x] (str "A " x) [B x] (str "B " x) [C x] (str "C " x))) (eval-cond (A.)) (eval-cond (B. 100)) (eval-cond (->C 100 200))

noisesmith17:09:23

you must mean condp here and not cond, right?

genec11:09:41

@sundarj it's test.match.A

genec11:09:32

this still returns No Match (defn eval-match [x] (case (type x) test.match.A "Type A" B "Type B" C "Type C" (str "No Match: " x))) (eval-match (A.)) '

sundarj11:09:33

yeah looks like case treats the thing it is passed literally

genec11:09:35

I don't understand how to match on the type or a record as this also returns "No Match" (let [x (type (A.))] (case x A "A" test.match.A "test.match.A" "No Match"))

sundarj11:09:05

boot.user=> (case boot.user.A boot.user.A "a")

java.lang.IllegalArgumentException: No matching clause: class boot.user.A
boot.user=> (case 'boot.user.A boot.user.A "a")
"a"

sundarj11:09:01

@genec you can use condp or a multimethod

genec11:09:43

@sundarj the quote is interesting, but not sure how to quote the type of a function argument. I think you're right condp is the best option. I was just trying to understand case and cond better. Thanks for the help!

sundarj11:09:17

no problem 🙂

genec11:09:05

@sundarj this works (let [x (type (B. 1))] (condp #(= %1 %2) x A "A" B "B" "No Match"))

sundarj11:09:37

@genec you could just use = directly, no need for the anonymous fn

genec11:09:27

@sundarj right, I was building up to this, in which case I need the lambda. thanks. (defn type-to-string [x] (condp #(= %1 (type %2)) x A "A" B (str "B : " (:x x)) "No Match")) (type-to-string (A.)) (type-to-string (B. 100))

sundarj11:09:58

wouldn't (condp = (type x) ...) work?

genec11:09:00

but using the let looks cleaner

genec11:09:30

@sundarj omg! yes! thank you, that's it. (defn type-to-string [x] (condp = (type x) A "A" B (str "B : " (:x x)) "No Match")) (type-to-string (A.)) (type-to-string (B. 100))

sundarj12:09:29

@genec for completeness, here's the multimethod version:

boot.user=> (defrecord A [])
boot.user.A
boot.user=> (defrecord B [x])
boot.user.B
boot.user=> (defmulti type->string type)
#'boot.user/type->string
boot.user=> (defmethod type->string A [x] "A")
#object[clojure.lang.MultiFn 0x4ccb03cd "clojure.lang.MultiFn@4ccb03cd"]
boot.user=> (defmethod type->string B [x] (str "B : " (:x x)))
#object[clojure.lang.MultiFn 0x4ccb03cd "clojure.lang.MultiFn@4ccb03cd"]
boot.user=> (type->string (A.))
"A"
boot.user=> (type->string (B. 42))
"B : 42"

sundarj12:09:02

oh right and the default:

boot.user=> (defmethod type->string :default [x] "No Match")
#object[clojure.lang.MultiFn 0x4ccb03cd "clojure.lang.MultiFn@4ccb03cd"]
boot.user=> (type->string 2)
"No Match"

genec12:09:12

@sundarj thank you very much, that's great

genec12:09:23

I forgot about the default too

Aron12:09:30

anyone using vscode with visual:closure? i am getting exceptions in the repl when trying to evaluate stuff in the editor

genec12:09:02

Do you mean the clojureVSCode extension? I tried both of the vs code Clojure extensions as I really like vs code, but ended up using Atom with proto-repl as I had trouble getting the vs code / Clojure setup working.

genec12:09:19

@ashnur have yo watch this? https://www.youtube.com/watch?v=73PnuVBkXxU it's now called Clojure code

Aron12:09:37

i have not

genec13:09:45

interesting, I hadn't heard of that one

Aron13:09:41

will try a different one next time i will have time to mess with clojure.

genec14:09:20

@ashnur For vs code the Clojure nRepl extension by Andrey Lisin is the most popular and the latest version starts / connects to nRepl when you open an project now. There's also Atom with proto-repl that's pretty popular and also lighttable if you want something that just works out of the box for playing around with Clojure.

Aron14:09:16

i ignored the mention of atom earlier, and thanks for suggesting, but will ignore it for a while, because sadly my machine doesn't bare the specs required for running atom with all the things that i need. vscode feels more lightweight, certainly more snappy

Aron14:09:49

as i mentioned previously, next time i will have some time for learning, will try a different extension, actually, already installed the version Lisin authored

genec14:09:14

sounds good. I just updated and tested the extension from Andrey and it works fine, takes a few seconds to connect to the nRepl. ctrl + shift + e evaluates the file. Whereas the proto-repl lets you evaluate blocks of code so it's more interactive (if that makes sense)

genec14:09:38

we're fortunate to have so many open source tools to use

Aron14:09:06

dunno, i wish i had 1 tool that works instead of 1000 that doesn't

Aron14:09:34

certainly we are fortunate that we are allowed to create freely and give it away for corporations

Aron14:09:46

</protest>

genec14:09:29

Just realized that if you select a block of code and ctrl + shift + e then it evaluates just the selected block, if nothings selected then it evaluates the file. cool!

Joe Lane17:09:32

Hey friends, silly convention question. I’ve got a function that will either return a byte-array or nil. Whats the best convention for handling the optional return value of this function, from the callers perspecive?

noisesmith17:09:14

@joe.lane some-> is handy if you know a result might be nil

Joe Lane17:09:24

great, thanks!

bigos17:09:43

I am a Clojure noob. I want to build a desktop app using seesaw. However, I have a problem with the choice of the build tool. On one hand, if you google for leiningen vs boot you will get lots of hits praising superiority of boot, but on the other hand, I have big troubles making the basic examples work. To what extent I should trust Google preferring boot. From a noob perspective, is it better to ignore boot and stick to leiningen?

chris17:09:07

I like boot, but lein is fine and I used it for a long time

noisesmith17:09:22

@ruby.object most things will assume lein familiarity, even boot related stuff often does

noisesmith17:09:35

for a beginner, use lein until you know you need boot, I’d say

noisesmith17:09:03

leiningen is also much more thoroughly documented

chris17:09:22

the reason there are a bunch of blog posts about 'boot is better than lein' is because lein is the defacto standard and it's what most people are familiar with

chris17:09:51

it's not cause lein is garbage

chris17:09:58

(lein is actually very good)

genec18:09:50

lein is great and don't forget there are plug-ins for it too

jaymartin18:09:28

One thing I do like about boot as a beginner is the repl experience. When you work in a directory from boot repl, boot automatically creates a file called .nrepl_history which contains the repl expressions that you’ve executed. So, if i’m firing up a repl to do some quick experimenting I reach for boot repl.

jaymartin18:09:56

But I agree in general about starting with lein.

jaymartin18:09:40

Gorilla REPL is also a fun way to record repl history: http://gorilla-repl.org/index.html

noisesmith18:09:11

I think .nrepl_history is a thing nrepl does, you get it with lein too

jaymartin00:09:32

On my system, I only get the nrepl history file with leiningen if I have a project.clj file in the present working directory, whereas with boot I get the history file regardless.

genec18:09:29

@ruby.object if you're learning seesaw you should also check out quil http://quil.info/

noisesmith18:09:37

also, nothing beats clojure.jar for quick repl experiments (if you don’t need other deps)

bigos18:09:01

@genec i definitely will have a look, now i need to find how to integrate it with a desktop application

bigos18:09:02

@genec I guess it's time to start trying out the examples 🙂

bigos19:09:33

@genec quil+lein is amazing, I did lein new quil hello quil, opened the core.clj file, started repl and selected menu Load all project files

bigos19:09:00

and this thing worked first time, i saw the window with animated ball

genec19:09:31

@ruby.object I agree 100%, I find with clojure and lein things just work. There are some good lein tutorials on youtube that are worth watching. here's a good one to start with. https://www.youtube.com/watch?v=mDwNgQhh0hY

jaymartin00:09:32

On my system, I only get the nrepl history file with leiningen if I have a project.clj file in the present working directory, whereas with boot I get the history file regardless.