Fork me on GitHub
#clojure
<
2017-09-16
>
didibus04:09:00

QUESTION: Is there something that can be used from Clojure to create a Java class and instance at runtime? Like a proxy that doesn't need to extend from anything, and you can just define custom methods? Or like a macro that both defines a protocol and its implementation and reify it into an inctance all in one go?

noisesmith04:09:59

gen-class can do this, but you'd need to do some trickery to meta-program a gen-class properly

didibus04:09:36

Hum, I didn't think of this, you can call it at runtime?

didibus04:09:48

Doc says: "When not compiling, does nothing."

didibus04:09:28

I think this could give me what I want: https://github.com/jgpc42/insn

didibus04:09:32

Hum, that might be too low level for me actually

noisesmith04:09:42

iirc gen-class literally checks for a flag like *compiling* which is dynamic and you could override- worth trying at least?

noisesmith04:09:32

the flag is *compile-files*

seancorfield04:09:52

@didibus Depending on what you're trying to do, couldn't you use definterface to declare whatever methods you want and just proxy that interface with the methods defined?

noisesmith04:09:13

yeah, that might actually be the simpler option

seancorfield04:09:52

boot.user=> (definterface Greeter (^String greet []))
boot.user.Greeter
boot.user=> (proxy [Greeter] [] (greet [] "Hello"))
#object[boot.user.proxy$java.lang.Object$Greeter$150fd98b 0x6d9cee8a "boot.user.proxy$java.lang.Object$Greeter$150fd98b@6d9cee8a"]
boot.user=> (.greet *1)
"Hello"

seancorfield04:09:42

proxy acts as a proxy for Object in the absence of a more specific class, and you can implement whatever methods you have interfaces for...

didibus04:09:22

Setting *compile-files doesn't seem to work.

didibus04:09:01

Ya, I guess that seems like the best route, could make a macro on top of them to do it all at once.

didibus05:09:41

Any idea how I can have this return a meta:

(defmacro tm [s]
  `(^void ~s))

(macroexpand-1 '(tm name))

didibus05:09:39

It expands to:

(name) 
and I want
(^void name)

noisesmith05:09:57

@didibus emit a call to with-meta

didibus05:09:22

I'm not sure how to resolve void though?

didibus05:09:24

(meta (vary-meta 'n assoc :tag `Integer))
this works, but not for the aliases like void
(meta (vary-meta 'n assoc :tag `void))

noisesmith05:09:35

tags are allowed to be strings - and I didn't say vary-meta, I said with-meta

noisesmith05:09:50

but I guess vary-meta works, it's just more complex than you need

didibus05:09:36

I guess, but vary-meta retains meta, with will lose the original meta. Which probably don't matter for what I'm doing here.

noisesmith05:09:01

oh, right, because s is passed in, good point

didibus05:09:03

So a tag of "void" will type hint to void correctly?

noisesmith05:09:14

also, your macroexpand doesn't show metadata, but if you bind *print-meta* it can

didibus05:09:35

Oh, that's neat to know

noisesmith05:09:28

user=> (binding [*print-meta* true] (prn ^:a {}))
^{:a true} {}

noisesmith05:09:59

+user=> (binding [*print-meta* true] (prn '^void 'foo))
^{:tag void, :line 12, :column 36} (quote foo)
nil

noisesmith05:09:28

+user=> (-> '^void foo meta :tag)
void
+user=> (-> '^void foo meta :tag type)
clojure.lang.Symbol

noisesmith05:09:37

looks like it wants the symbol 'void

tengstrand06:09:38

@carr0t cool, thanks for the info!

genRaiy12:09:51

i have a question about fn definitions inside defrecord / deftype vs normal fns

genRaiy12:09:31

they don’t seem to support :pre and :post conditions - is that right?

genRaiy12:09:23

here are some worked examples

genRaiy12:09:40

Maybe this a well known problem … in which case, OK … I’ll move along

genRaiy12:09:59

But if I’m missing something, I would appreciate some tips / advice

mpenet12:09:10

I think if you create the impl via extend-protocol it might work

mpenet12:09:20

Since it will be just a normal fn under the hood. When it s inline like in your example I think it s optimized and compiled differently

genRaiy13:09:34

@mpenet I don’t have any luck when using extend

genRaiy13:09:20

I was doing it wrong @mpenet… you are of course correct

mpenet15:09:06

inline it compiles to a method of the record (class), via extend it does a runtime lookup in the proto to find the corresponding clj fn that was registered

mpenet15:09:49

But it is an impl detail

genRaiy13:09:43

I lose access to x as I have to go via this

genRaiy13:09:01

but we do get :post conditions back too

rcustodio13:09:28

Do any1 knows about TCP/uso?

qqq15:09:41

input: [a b c d e] output: [ [ a b c d e], [ b c d e], [c d e], [d e] [e]] is there a builtin for this? (it's fine if it returns lists instead of vectors)

qqq15:09:00

hmm, stack overflow suggests (reductions (fn [s _] (rest s)) x x)

bronsa15:09:53

either that or (take-while seq (iterate rest x))

lambeta15:09:42

hi hivemind, I always see

:repositories [["releases" {:url ""
                            :creds :gpg}]]
anyone knows what the http://blueant.com does mean? it seems that is a unowned domain name.

eggsyntax19:09:46

Awesome books.

noisesmith15:09:18

it's an example of using a private repository

lambeta15:09:32

@noisesmith thanks. I do agree that’s better to use http://example.com to avoid unnecessary confusion.

qqq16:09:57

is there a builtin for (fn [x y] [y x]) ?

noisesmith16:09:22

not that I know of, I would use (comp vec rseq vector)

noisesmith16:09:42

leaving out vec if I don't strictly need a vector of course

noisesmith16:09:48

anyway the rseq / vector combo is the only one that doesn't need to arrange the items twice

qqq16:09:58

I was hoping there would be something like swap2 or something

noisesmith16:09:36

if we have varargs flip it would be (flip vector)

didibus19:09:23

@qqq What about

(apply - (reverse [1 2]))

noisesmith19:09:15

wait, where did - come from?

didibus19:09:27

Oh, just an example, I assumed he wanted that function to reverse arguments to a function. So I showed it in example

didibus19:09:55

Any good reason why dissoc doesn't work on vectors? My only guess is because Clojure seems to default to not giving you any potentially inefficient collection functions.

noisesmith19:09:42

that's pretty much it, the best option for an efficient collection that does this is a finger-tree

didibus19:09:11

Is that in core?

noisesmith19:09:54

no, it's a decent library though, worked on by people who work on core https://github.com/clojure/data.finger-tree

didibus19:09:04

Interesting, I'll have to give it a look

eggsyntax19:09:35

Is there any way to access the form originally used to define a var, if that var was defined in the repl? eg if I do (defn f [x] (inc x)) or (def a 3) is there any way to recover that expression, given the name of the var? clojure.repl/source will do it if it was defined in a source file, but I specifically want ones that were defined in the REPL. I'm experimenting with doing it by creating a REPL using a custom :read fn which saves off the forms, but I wanted to be sure there wasn't already a good existing solution.

noisesmith19:09:29

if you look at what clojure.repl/source does, it uses the line number info and such to extract the source

noisesmith19:09:42

there's no tracking of the actual input form that was compiled

noisesmith19:09:27

you could make your own version of fn / def / defn etc. that does this

noisesmith19:09:39

but ... yeah, nothing built in

eggsyntax19:09:31

That's what I suspected. I would find it useful to be able to say, "give me the def for this form, preceded by the defs for any locally-defined vars contained in the form." It would make it easier & less tedious to move code from the repl to a source file.

eggsyntax19:09:56

I'm having plenty of fun experimenting with a custom :read fn for the repl, though 🙂

Aleh Atsman19:09:47

hi, can someone explain how to use client_middleware in aleph, so that i can do not parse the response body manually? (edited)

pwrflx23:09:32

hi! can I have a .cljc and a .cljs / .clj of the same namespace? (eg I have a utils namespace and there is some stuff in there which can be shared, some not)