Fork me on GitHub
#clojure
<
2017-09-15
>
donyorm04:09:10

So I have the following macro in my code:

(defmacro run-sym [sym & args]
             (require (symbol (namespace sym)))
             `((resolve ~sym) ~@args))
Which I would think works, however when I run it I get the following error: java.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to clojure.lang.Named. What causes this? And how can I fix it?

noisesmith04:09:22

sym needs to be a literal symbol, it can't be a form that returns one

donyorm04:09:42

it is a literal symbol.

donyorm04:09:58

Here's my test line: (run-sym 'clojure.string/join " " [1 2 3 4 5])

noisesmith04:09:13

you passed in (quote clojure.string/join)

noisesmith04:09:20

that's a list

donyorm04:09:28

How do I pass a literal symbol? I haven't had to do that

noisesmith04:09:41

just leave off the '

noisesmith04:09:52

most forms will automatically resolve symbols, macros don't

donyorm04:09:10

right it's a macro, I haven't used those much.

noisesmith04:09:49

or you could use `(do ...) to put the require inside the macro body output too

noisesmith04:09:00

then ~ on the symbol / namespace call etc.

noisesmith04:09:45

come to think of it that's the only way to have one input that works with both forms I think...

donyorm04:09:08

Got it to work. Thanks!

ikitommi05:09:48

@josh.freckleton hi, you can add any swagger data with key :swagger, e.g. :swagger {:deprecated true}.

kwladyka13:09:42

How do you use boot in Intellij + Cursive? I am asking especially about REPL

danm13:09:55

Personally, I don't

danm13:09:03

I just run a repl in a terminal

danm13:09:37

Cursive also seems built around lein, and failed to find a load of my dependencies even after I'd converted my build.boot to a project.clj, so I gave up in favour of clojure-kit until Cursive gets proper boot support, then I'll try again

danm13:09:14

That might also have been because i have loads of different Clojure projects within a single 'project', but it didn't seem to work even when I just loaded one of them

kwladyka13:09:55

yeah, i used to Cursive, but i have to use boot sometimes and then issues come. clojure-kit is something like cursive?

kwladyka13:09:39

Did you try solutions like nightlight or atom for Clojure? I was trying atom in the past but it was definitely not ready then.

danm13:09:46

Well I use IntelliJ for a load of other languages I use, so I wanted something that I could do Clojure in there too

danm13:09:12

clojure-kit is an unofficial plugin for IntelliJ to do Clojure, but it is written by a guy who works for IntelliJ, so...

danm13:09:45

It's not as full featured as Cursive, but it doesn't have issues finding my dependencies, and gives me syntax highlighting which is the main thing I wanted

kwladyka14:09:59

thx for sharing your experience with Intellij. I have similar situation, but as long as i have to use boot i start to think again if intellij is good choice in such case

jetzajac14:09:28

@kwladyka clojure-kit runs boot to figure out deps and to run a repl. I would prefer the other way around to integrate with IDEs. Ideal IDE would listen to proj configuration updates on a socket for maximum flexibility.

danm14:09:02

@teng 2nd argument is 'default', or "What to return if key doesn't exist in map"

danm14:09:37

(def x {:a 1 :b 2})
(x :c "NOSUCHKEY")
will return "NOSUCHKEY"

danm14:09:39

Useful if you want to default for nonexistent keys, rather than returning nil and then checking if you got a nil and returning some other value if you did

jetzajac14:09:27

BTW it is useful to distinguish having a nil as a value in map and an absent key.

danm14:09:05

That too

carter.andrewj16:09:53

Hi guys, I'm hitting a really weird compilation error with defprotocol - namely java.lang.RuntimeException: Method code too large!

carter.andrewj16:09:16

It's a big protocol, but surely there isn't a limit to how many methods a protocol can have?

carter.andrewj16:09:15

Anyone seen this before? (And can tell me how to overcome the underlying problem, without having to refactor... well... everything?)

carter.andrewj16:09:17

Have seemingly managed to prove that the issue is the number of methods I'm defining (by commenting out chunks until the error went away; and then commenting out different chunks to make sure it wasn't related to the last chunk I redacted)

bfabry16:09:36

how many methods does this protocol have?

tbaldridge16:09:44

@carter.andrewj there's a limit to how much code you can put in a single method.

tbaldridge16:09:01

Are you using core.match or core.async's go?

carter.andrewj16:09:16

Yeah, but this is just the protocol - the methods haven't even started compiling at this point

carter.andrewj16:09:23

It's about 50 - haven't counted

tbaldridge16:09:34

in a single protocol?

bfabry16:09:07

I'm guessing that defining the protocol is defining a method with some inlined table somewhere or something

tbaldridge16:09:33

no, the're just a fair amount of code involved in defprotocol

carter.andrewj16:09:42

Okay - I managed to solve it by cutting the definition in half and chaining the second half as an extend-protocol

carter.andrewj16:09:50

But would rather not have to hack my way around it

tbaldridge16:09:55

But really, break that thing up a bit. Good protocols are normally < 10methods, most should be <5

carter.andrewj16:09:20

It's a core protocol defining a lot of helpers for higher-order classes

tbaldridge16:09:38

why can't these just be normal functions?

tbaldridge16:09:00

And often you can break stuff down. Instead of IList for example you can have IAppendable, ICounted, IIndexable, etc.

tbaldridge16:09:16

Most of the time you can almost have a 1:1 ratio of protocols and methods.

dpsutton16:09:24

do you have 2 complete and distinct implementations of those 50 functions?

carter.andrewj16:09:00

Some have 2-3, others have up to 12

bfabry16:09:31

if they don't change at the same time they shouldn't be named by the same abstraction

carter.andrewj16:09:46

I'm doing is writing a library for handling analytical data contextually - so the higher-level types are things like a measure, aggregate or transform, etc... The goal is to be able to handle these things generically (hence the protocols) but they also have a hierarchical ownership (e.g. a transform might operate on two aggregates)

dpsutton16:09:13

for instance, how general is your protocol? maybe carve out 7 protocols that are more specific

bfabry16:09:32

IMeasure, IAggregate, ITransform, IFact, IWarehouseEntity

carter.andrewj16:09:36

Yeah, it can certainly be broken down into sub-sections

dpsutton16:09:37

defprotocol Analyze => ^

dpsutton16:09:34

and if you have up to 12, then you have at least 12 types and you have therefore 600 functions implementing this protocol!

carter.andrewj16:09:34

Well each of those has their own protocol already for the methods specific to their types - this is the general set of methods that are universal, but require different implementations

tbaldridge16:09:45

for example, look at core.matrix: https://github.com/mikera/core.matrix/blob/develop/src/main/clojure/clojure/core/matrix/protocols.cljc#L173 A lot of things be done to a matrix, but they're all given their own protocol.

carter.andrewj16:09:45

I can absolutely break it out into smaller sub-protocols, it just seemed tidier to keep everything in the same place - given that a lot of them are going to always be dependent on the others

bfabry16:09:22

life will be better if you break them up into areas of responsibility/change I guarantee it

carter.andrewj16:09:19

Happy to follow that way of operation

carter.andrewj16:09:52

And there are certainly clearly defined areas that I could break out

carter.andrewj16:09:25

Is it going to be general code-management issues I run into without that? Or something else?

carter.andrewj16:09:41

(Just trying to better inform myself)

dpsutton16:09:29

so crazy thought. if you have 50 functions and up to 12 different implementations, many many of these must have common implementations. at this point i think i might write a macro to do this for me

carter.andrewj16:09:45

(I did have things broken out in earlier iterations - but it seemed pointlessly opaque to have every type of dependent record invoking the same 10 different protocols

dpsutton16:09:06

can a macro expand to more than one form? ie return ~@forms?

carter.andrewj16:09:46

(Ha - I did consider that it might have been worth learning macros to do this, but that was only after I'd gone a significant distance)

hiredman16:09:47

the main thing is don't define the protocols and implementations in the same file, people almost always want to do this, but it very easily turns in to circular references between the implementations helper code and the protocol definitions

carter.andrewj16:09:16

No worries there - I've got everything filed away separately already

carter.andrewj16:09:47

Anyway - thanks for the help guys

nfisher18:09:01

Hi all, I’ve started on a project to address the read and start-up time in Clojure. It’s a bit of an experiment at the moment so far I have it doing most symbol extraction, next I’ll be working to build an AST. Lexing the Pedestal repo at the moment takes about 184ms which is spread across 4 readers and 16 lexers. If you’re interested in taking a peek it’s here: https://github.com/nfisher/cljbuck

mtnygard18:09:18

@dpsutton You can often get a similar effect by returning `(do ,,,) with multiple forms inside the do.

dpsutton18:09:31

i was wondering if he could get around the method too large boundary by returning a (deftype ~type [implement protocol]) (extend-protocol ~type [more stuff here]) but this is apparently not possible. a do form would preserve and actually exacerbate the method too large error

noisesmith18:09:01

yeah, calling out to functions is the best way of fixing that

noisesmith18:09:18

now, you could make a macro that defined a function and also made a method body that called it…

noisesmith18:09:39

not especially efficient but it could help maybe?

didibus22:09:36

QUESTION: Any way I can take a arbitrary Java POJO and print it into something the Clojure reader can read back into the Java POJO?

viirii23:09:56

I have a question regarding namepsace and difference in compilation for CIDER vs lein

viirii23:09:27

all 4 files compile and pass tests on cider. two_test.clj does not compile on lein though, with Exception in thread "main" java.io.FileNotFoundException: error, regarding parent.child.one-test

viirii23:09:45

My hunch is that even with the dependencies specified, only items in src/ can be imported into other namespaces.

hiredman23:09:01

there is no difference, if you are seeing one it is as a result of something you did

viirii23:09:38

any idea as for why it would pass/compile in cider, but not in lein ?

hiredman23:09:40

but you ns forms are also incorrect

hiredman23:09:50

should be :require

viirii23:09:58

those are not copy & paste

hiredman23:09:06

and you alias both one and one-test as one

viirii23:09:30

sorry I should’ve been more careful with the sanitization

hiredman23:09:55

my guess would be you haven't restarted the cider repl in a while and the running code has diverged from what you have in your files

hiredman23:09:14

if you kill cider and restart it you will get the same error

viirii23:09:29

I re-started emacs/cider and it compiled and ran

hiredman23:09:41

your example is all kinds of wrong, so it is hard to get anything useful from it, I don't think anyone will be able to help based on it

viirii23:09:50

ok. I’ll try to reformat it

hiredman23:09:58

it isn't a formatting issue

hiredman23:09:11

the namespaces don't match the file paths