Fork me on GitHub
#beginners
<
2017-12-09
>
Sivaram Konanki04:12:00

I have a question. How do I add maven repo url or specify default repo in .lein/profiles.clj?

noisesmith04:12:14

@konanki.sivaram it's mentioned in the output of lein help sample

noisesmith05:12:08

it's a big output, the thing to search for is :repositories - the content of it is online too if you google for "sample project.clj leiningen"

kgofhedgehogs13:12:56

Is there way to generate and define all this functions from list like [:account :message]?

(def select-accounts* (partial select-from-table* db :account))
(def insert-accounts* (partial insert-into-table* db :account))
(def update-accounts* (partial update-in-table* db :account))
(def delete-accounts* (partial delete-from-table* db :account))
(def account-exist? (partial row-exist? db :account))

(def select-messages* (partial select-from-table* db :message))
(def insert-messages* (partial insert-into-table* db :message))
(def update-messages* (partial update-in-table* db :message))
(def delete-messages* (partial delete-from-table* db :message))
(def message-exist? (partial row-exist? db :message))

schmee14:12:18

Here’s one way you could do it, only tested to macro-expand this in the repl so it might need some tweaking 🙂

(defn def-crud-functions [thing]
  (let [ts (name thing)]
    `(do
       (def ~(symbol (str "select-" ts "s*")) (partial select-from-table* db ~thing))
       (def ~(symbol (str "insert-" ts "s*")) (partial insert-into-table* db ~thing))
       (def ~(symbol (str "update-" ts "s*")) (partial update-in-table* db ~thing))
       (def ~(symbol (str "delete-" ts "s*")) (partial delete-from-table* db ~thing))
       (def ~(symbol (str ts "exists")) (partial row-exist? db ~thing)))))

(defmacro defcrud [things]
  `(do [email protected](for [thing things] (def-crud-functions thing))))

alexmiller13:12:34

sure - use a macro

genec14:12:54

Is there a good reference summarizing the various clojure editors? Seems like the only two options that give you interactive / immediate feedback are emacs or intelliJ/Cursive. I like proto-repl but it tends to hang on me and the package for vs code doesn't offer the interactivity (i could be wrong though) Do I really have to learn emacs to use Clojure?

schmee15:12:00

you most certainly do not have to learn emacs. I’m using vim since that’s what I’ve been using for a long time for all my coding and with a few plugins it works great for Clojure

genec15:12:57

thanks for the info

seancorfield19:12:32

As a random data point, I switched to Atom/ProtoREPL about a year ago after years of Emacs and I've been very happy with that choice.

New To Clojure20:12:39

@U04V70XH6 That's unusual for an emacs user! 🙂 What makes it better than emacs for you?

seancorfield20:12:59

I wanted something that felt more modern and was easier to keep configured and maintained. Emacs is great but it's fussy and it just feels so old-fashioned these days.

seancorfield20:12:34

I first started using Emacs back in the 17.x days and switched away to more IDE-like editors early during the 19.x series. I came back to it after I started learning Clojure in the pre-release days of 24.x and was a bit surprised it really hadn't changed (in, what, twenty years?).

New To Clojure20:12:23

Thank you, @U04V70XH6! As for me I don't like Electron apps much for being a bit alien on any system and so I keep using Emacs (probably I'll try using Vim at some point in the future).

kgofhedgehogs15:12:08

@genec, very. Using it right now

kgofhedgehogs15:12:22

Though Its hard (for me) to setup. There also is config for newbies https://github.com/ctford/vim-fireplace-easy I using it too

kgofhedgehogs15:12:42

In vim-fireplace there is repl integration, but I dont know about eclipse-ccw and vscode plugin

genec15:12:56

anyone using clojure with vscode? that would be my preferred setup as I use vscode / ionide for F# development at work

New To Clojure15:12:08

Also there's https://github.com/gregsh/Clojure-Kit for Intellij users (alternative to Cursive).

kgofhedgehogs15:12:15

@genec, I know one person who stick to vscode clojure development, but he said what this isnt very good setup (but he still using it though)

genec15:12:38

there are a lot of options, but what do you think are the 3 most popular? I'm guessing emacs is 1st

New To Clojure15:12:35

(from State of Clojure 2016 Results and Analysis)

genec15:12:35

cool thanks

genec15:12:50

there are 3 vscode clojure packages

stvnmllr217:12:39

I'm trying to get 5 random items out of a collection. Seems like I'm making it harder than it should be. Anyone know of an idiomatic way to do that?

noisesmith17:12:30

are repeats allowed?

stvnmllr217:12:52

nope. that's the problem

noisesmith17:12:57

(take 5 (shuffle coll))

stvnmllr217:12:48

well.. there ya go! thanks. so obvious! randomize the collection instead of the taking.

stvnmllr217:12:32

of course i had never used shuffle before, so that didn't help. thx again.

genec19:12:57

decided to setup IntelliJ / cursive - takes a bit of time to learn but very nice, works great on Win PC and Mac

alexdavis21:12:40

I’m trying to generate some users with spec and it was going well until I added roles. My problem is there could be 5+ roles in the system but two of them are mutually exclusive, i.e a user can’t be role-a if they are role-b and vice versa. Currently I have

(s/def :user/role
  (s/with-gen (s/or :ident (s/and (s/keys :req [:db/ident])
                                  #(contains? user-roles (:db/ident %)))
                    :key user-roles)
    (fn [] (sgen/elements user-roles))))

(s/def :user/roles
  (s/with-gen (s/coll-of :user/role)
    (fn [] (sgen/vector-distinct (s/gen :user/role)))))
but I’m not sure of how to conditionally exclude specific roles… I’m still very new to this so any criticism is welcomed

galbacarys22:12:04

Hey, I’m having some macro troubles, could someone help me out?

noisesmith22:12:17

you don't have to ask permission to ask a question - if someone can help they'll chime in, and if you don't get help you can try another time

galbacarys22:12:26

What would cause a “No matching ctor found for class” exception when defining a macro? I’m really stumped as to why it’s happening and the stack trace is completely useless. I’m not using any java interop

noisesmith22:12:06

everything in clojure is java

noisesmith22:12:12

(on the jvm at least)

noisesmith22:12:19

what does the macro look like?

noisesmith22:12:29

also, what class is it talking about?

galbacarys22:12:41

It’d be really hard to tease out just the part that’s giving me trouble, lemme see if I can throw together an example that triggers the same thing. maybe that’ll help me figure it out

noisesmith22:12:56

can you at least show the error stack trace?

noisesmith22:12:43

a macro can do anything a function can, which means they can do anything the vm can do - there's a lot of ways to get that error message

noisesmith22:12:55

at least knowing what class it was trying to construct might be a clue

galbacarys22:12:41

it was trying to construct a class based on a function I was defining within the macro, best I can tell. I have to restart my repl, my emacs just exploded lol

galbacarys22:12:43

gimme 2 minutes

noisesmith22:12:12

practically everything you ever do with clojure constructs instances of classes, so there's lots of places you could make a bad argument to a constructor

abiduzz42022:12:19

Hi guys, I write articles on Clojure on a daily basis taking brave clojure as a reference. Check out my latest article on Functions in Clojure: Day 4 : https://medium.com/@abiduzair420/functions-in-clojure-day-4-6a38c6e18661

galbacarys22:12:41

It’s not super helpful as to what’s going on

noisesmith22:12:31

what is defpipeline

galbacarys22:12:11

It’s the macro I’m working on. I think I see what I’m doing wrong though

noisesmith22:12:27

what is new-pipeline that's inside it?

galbacarys22:12:47

It’s a function I’m defining inside a let

galbacarys22:12:10

long story short, I’m defining a new function to do some behavior based on user input, then that’s getting dumped into a global registry. I have a let to define all the bits that I need to finally build up the new function into new-pipeline and one of those steps is invoking another macro, and I think I’m borking the creation of the function

noisesmith22:12:17

@g.albacarys I figured out what you are doing

galbacarys22:12:42

how on earth did you derive anything from that stack trace?? 🙂

noisesmith22:12:46

a macro is a function that needs to return the object that the compiler needs to compile to generate your bytecode

galbacarys22:12:21

I see the problem now.

noisesmith22:12:28

if you put a function inside the macro output - as an object directly - the compiler blows up with that error because it doesn't know how to take a function as an input to the compiler

noisesmith22:12:24

the thing a macro returns should consist of simple data structures (the kind that clojure knows how to read from the repl as literals), plus strings, numbers, symbols, keywords, etc.

noisesmith22:12:40

symbols will be replaced with whatever has that symbol as a name in the context that the macro is called

noisesmith22:12:11

by putting a function directly inside the value the macro returns, you confuse the compiler

galbacarys22:12:12

that makes a heck of a lot of sense, thanks!

galbacarys22:12:37

so I should just return the unevaluated form of whatever I want the result of the macro to be as the output, and let the compiler magick it to life

noisesmith22:12:58

hmm... it's not quite that simple...

noisesmith22:12:37

but yeah that is how it should be done

noisesmith22:12:59

now I am trying to make a simple reproduction of your error - I think I understand it but so far I'm not reproducing

galbacarys22:12:03

I know what I’m doing-my last return isn’t actually that function, it’s a map that, among other things, contains the new-pipeline function I was creating. new-pipeline is kind of a red herring in that stack trace, like you said I’m not returning a simple object

galbacarys22:12:32

So for example, my code is eventually resulting in this:

galbacarys22:12:27

(defmacro foo [] {:asdf (fn [some args] (println some) (println args)) })

galbacarys22:12:06

so I’m returning a map that has a function that’s already been eval’ed, it isn’t a simple object so the compiler is barfing

noisesmith22:12:41

yeah but that foo doesn't break in my repl

noisesmith22:12:26

that's the part that still confuses me... anyway, the right path with macros is to return the form to be compiled, so I can see how things like that could mess with the compiler, even if some of them do work

galbacarys22:12:48

lol I’ll just keep that as a rule of thumb then, and totally ignore the fact that it might sometimes work

noisesmith22:12:13

... I'll let you know if I figure out a more consistent pattern for when this goes wrong

noisesmith22:12:28

@g.albacarys minimal repro

+user=> (defmacro foo [] {:asdf (constantly :broken) })
#'user/foo
+user=> (foo)
IllegalArgumentException No matching ctor found for class clojure.core$constantly$fn__5394  clojure.lang.Reflector.invokeConstructor (Reflector.java:163)

noisesmith22:12:50

same pattern works for functions, (must be special cased by the compiler) but breaks for higher order code that generates functions

noisesmith22:12:56

oh wow this is super weird

+user=> (defmacro foo [] (constantly :broken))
#'user/foo
+user=> (foo)
#object[clojure.core$constantly$fn__5394 0x1c3146bc "[email protected]"]
+user=> ((foo))
IllegalArgumentException No matching ctor found for class clojure.core$constantly$fn__5394  clojure.lang.Reflector.invokeConstructor (Reflector.java:163)
+user=> (defmacro foo [] (constantly :broken))
#'user/foo
+user=> (foo)
#object[clojure.core$constantly$fn__5394 0x73dce0e6 "[email protected]"]
+user=> (*1)
:broken

galbacarys22:12:07

@noisemith constantly is a clojure function as opposed to a random undefined symbol, so maybe that’s the difference?

noisesmith22:12:06

but I'm calling ((foo)) and that breaks, and (let [f (foo)] (f)) breaks, but (def f (foo)) (f) does not break

noisesmith22:12:18

so now my question is why it would sometimes work haha

galbacarys22:12:25

🙃 who knows