Fork me on GitHub
#clojure
<
2017-09-24
>
tbaldridge00:09:11

@sophiago sure, feel free to ping me here, or even in a pm when the time comes

sophiago00:09:22

Thanks! It's quite ironic actually, the numeric part I'm optimizing now I assumed I would be able to swap out for a library yet none come close to meeting my needs, whereas the complicated control flow analysis and source transformation already existed.

beoliver03:09:41

can any-one explain how the following would be converted to clojure, including the import.

ArangoDB arangoDB = new ArangoDB.Builder().host("192.168.182.50", 8888).build();

beoliver03:09:22

ArangoDB is a class Builder is a static class inside ArandoDB, Builder calls super() host is a method on Builder build() is method of the ArangoDB class

the2bears04:09:11

Should you use a 'new' on the static builder like that?

tbaldridge04:09:52

@beoliver inner classes don't really exist on the JVM, they're simply naming sugar. So You'd want to import ArandoDB$Builder

tbaldridge04:09:59

and yeah, the new doesn't look right

beoliver07:09:43

@the2bears @tbaldridge - the code is directly from the git hub page for the project https://github.com/arangodb/arangodb-java-driver (i think they used maxConnections(...) instead of host(...) but same difference.

beoliver07:09:52

well

(.build (-> (new ArangoDB$Builder) 
            (.host "127.0.0.1" 8888)))
seems to work (at least it returns #object[com.arangodb.ArangoDB 0x703a3035 "com.arangodb.ArangoDB@703a3035"] which is something 😄

genec12:09:59

@beoliver What do you think of ArandoDB? I hadn't heard of it.

beoliver12:09:42

@genec It seems nice - havn't used it enough to be critical, but I have the impression that most people that use it are satisfied (obviously not clojurians by state of the libs)... Trying to decide if I should write a wrapper around the java lib or just write a new one? The most popular clojrue lib https://github.com/Lepetere/clarango looks dead (hasn't been touched in 2 years - and looks like version 3.0+ of the db breaks it)

beoliver13:09:34

I've come unstuck again with these nested classes. If anyone has any hints feel free https://stackoverflow.com/questions/46390544/clojure-importing-nested-classes

abdullahibra14:09:38

what is the best practice for naming methods which handle different types, ax example: i have two namespaces A and B both should has method foo but each will handle different data structure, so it's the best to use them as A/foo B/foo or write multimethod which handle them ?

abdullahibra14:09:31

i'm asking about best practice in FP in general

vandr0iy15:09:55

@abdullahibra go multimethods, it'll be much cleaner and readable a month later 😉

darwin16:09:40

@abdullahibra don't use multimethods unless you really need to, they have runtime performance implications, they are not composable and they are less readable than plain functions. IMO multimethods are worth it when you need runtime polymorphic dispatch which is open. by open I mean that you expect consumers/callers of your code to potentially extend the hierarchy by defining their own implementation. From what you wrote it does not seem to be the case. Why not renaming your functions to A/foo-with-ds-a and B/foo-with-ds-b if you want to be explicit, or don't rename them and implement runtime assert/spec to warn caller about wrong data structure passed?

reefersleep11:09:52

How are they not composable?

dominicm16:09:00

@abdullahibra Generally, I namespace all functions I use. I'm presuming that the different data structures they handle are indicated (even partially) by their namespace, in which case I would go with A/foo or B/foo every time. It's not often that I :refer something.

darwin16:09:33

and one last note, if you needed to do one umbrella function which does the dispatch, you can write it as plain clojure function, say X/universal-foo, which has one huge cond to dispatch to individual namespaces based on data structure passed, this would be like multimethod, but closed (and without unneeded overhead).

andrewboltachev19:09:54

Hello. Is a list of all Clojure reserved words (like ns, def, defn, if) etc available somewhere?

Alex Miller (Clojure team)19:09:56

technically, there aren’t really any reserved words other than “true”, “false”, and “nil” - those are the only special symbols read explicitly in the reader

Alex Miller (Clojure team)19:09:37

almost everything else is a namespace or var name (that you can shadow and use yourself).

Alex Miller (Clojure team)19:09:46

there are some special forms that the compiler understands, as defined in https://clojure.org/reference/special_forms. Everything else (and even some of those) are just vars declared in clojure.core namespace

souenzzo20:09:40

See also: (dir clojure.core)

andrewboltachev19:09:11

thanks@hmaurer. I tried this one, but it's incomplete

andrewboltachev19:09:56

huh, that's really quite a bit: http://dpaste.com/0P9XQEW 😄

the2bears19:09:51

Not really "reserved" words, though, as they're mostly names in name spaces.

the2bears19:09:11

I think the special forms are more complete than you think 🙂

the2bears19:09:04

But I don't completely grok the reader stuff yet, so I may well be wrong.

andrewboltachev19:09:11

Is Clojure macroexpansion performed depth-first or breadth-first? Is it possible to change that?

darwin19:09:31

@andrewboltachev "outer" macro is expanded first and its result is expanded further until there is no further expansion detected

Alex Miller (Clojure team)19:09:59

and there is no recursion there - the top macro will receive the unevaluated forms

Alex Miller (Clojure team)19:09:29

so it’s neither breadth nor depth first as far as I would say

darwin19:09:57

@andrewboltachev I believe you can write your own macro-expanding for code you receive in macro as input, this way you can reverse the outer-inner order. This is what I did: https://github.com/binaryage/cljs-oops/blob/master/src/lib/oops/compiler.clj#L21-L36

darwin19:09:56

it is cljs-related, but the idea should be similar, you can "force" macro expansion on your input if you really need

Alex Miller (Clojure team)19:09:34

there are some custom macro expanders out there like https://github.com/ztellman/riddley

souenzzo20:09:08

With #specter

(transform (walker number?) inc '(let [n 1] (+ n 1)))
=> (let [n 2] (+ n 2))
And you can use all others navs, like continue-then-stay and recursive stuff

andrewboltachev19:09:56

@darwin huh great. Btw, it all ends up to use prewalk/postwalk (though it's not a recursion)

andrewboltachev20:09:22

In fact, I'm trying to rewrite the code in such a way that I'll touch only functions

andrewboltachev20:09:16

(when x (fn1 a b)) -> (when x ((dbgfn fn1) a b))

andrewboltachev20:09:41

(but I got ((dbgfn when) x ((dbgfn fn1) a b)))

qqq20:09:17

if I want a single api that: on jvm: provides cuda acceperated blas on js: provides some blas api is core.matrix the best way to go?

darwin20:09:29

@andrewboltachev I'm not that familiar with this, but I believe you can look at metadata of individual sub-forms and get some useful properties from analysis (to determine what symbols are functions maybe). Otherwise you would have to invoke full-blown analysis for your code form, which might be pretty advanced (and slow?) thing to do.

andrewboltachev20:09:35

@darwin Yes, exactly. I'll probably just filter out all the macros (pretending there're just a few) by their name. I was just trying to follow the idea: If “code is data”, then let's edit it. But this doesn't work straight away.

darwin20:09:32

well, code is data, but if you want to rewrite it, you should better do it based on a template, not on compiler's analysis knowledge

darwin20:09:05

knowing if a given symbol is a macro, function or something else is not encoded in the form itself

andrewboltachev20:09:36

True. In that sense my idea would be better implemented via hacking a compiler probably (which knows that and has explicit step — macro expansion, all the transformations etc)

darwin20:09:30

look at the metadata first, maybe you'll find something useful there 🙂

darwin20:09:58

also you can force macro-expansion on your macro input, so you can work on already expanded code, so there will be no "macro-calls", only "function-calls" and quoted data

andrewboltachev20:09:28

there should be also like :env somewhere? may be this already holds all the macros' names?

darwin20:09:07

as I wrote, if you force macro-expansion, macro names are no longer your issue, you will have to detect quoted stuff, which might look like function calls, but is quoted, so you don't want to touch it

Alex Miller (Clojure team)20:09:21

macro vars have {:macro true} meta on them, in case that’s helpful

laujensen20:09:35

Has anyone looked at getting httpkit to run over https/wss ?

andrewboltachev20:09:09

@laujensen if you're running a server, you might probably do this via nginx (or apache2 etc) to add certificates if you speaking of client and have troubles calling https, then you'd better try to figure out if all certificates (of a target server) are in place

laujensen20:09:13

I have it running locally with ws:// and its working fine. Then when I pushed to a server running https behind nginx with certs, it just says connection failed. Which I take it to mean that its not getting ported in/not listning on the port

andrewboltachev20:09:04

@laujensen is all the proxy_pass etc in place?

andrewboltachev20:09:24

(or other provider's tool, this one for RapidSSL)

andrewboltachev20:09:59

@laujensen you might also check with curl

darwin21:09:07

@andrewboltachev eval is evil, what if x is implemented as launch-nukes-to-north-korea!?

andrewboltachev21:09:48

@darwin it just evaluates to the name, and doesn't do actual function call 🙂

andrewboltachev21:09:39

i.e. I have another tool that would rewrite 1st symbol of all lists in particular file(s)

andrewboltachev21:09:13

and for me, if this one would work it already would be amazing

andrewboltachev21:09:23

e.g.

user=> (defmacro m2 [x] (eval x))
#'user/m2
user=> (m2 identity)
#object[clojure.core$identity 0x56a9c24a "clojure.core$identity@56a9c24a"]

darwin21:09:11

(m2 '(identity (println "boom!")))

darwin21:09:56

or just (m2 '(println "boom!"))

andrewboltachev21:09:21

user=> (defmacro m2 [x] (when (symbol? x) (eval x)))
#'user/m2
user=> (m2 '(println "boom!"))
nil

darwin21:09:56

you should be able to find something like resolve which should be more light-weight than eval and will do what you are afte5r

andrewboltachev21:09:58

just replacing eval with resolve... uhm, it fires an exception anyway somehow

andrewboltachev21:09:16

i.e. can't macroexpand this way

darwin21:09:52

don't know, but I would be very careful calling eval on arbitrary input in your macros

andrewboltachev21:09:42

and no. can't use macroexpand

andrewboltachev21:09:59

arbitary symbol in my case.

andrewboltachev21:09:45

if only someone would provide something which is symbol? and inside hosts sth callable/evaluatable?

darwin21:09:52

why exactly you cannot (defmacro m3 [form] (my-dbg-transform (clojure.walk/macroexpand-all form)))

darwin21:09:23

where my-dbg-transform walks the form and replaces all lists with dbg wrapper, except for special forms and quoted data

andrewboltachev21:09:37

well, just I've selected different point of application

andrewboltachev21:09:39

as well I want to keep the position inside the source file (line/column)

andrewboltachev21:09:53

didn't think about it though

andrewboltachev21:09:42

i.e. if doing macroexpand vs. this "with-eval" magic is worse in terms of what is possible in keeping all the positions

darwin21:09:30

AFAIK source positions are in metadata, you can be properly providing them if careful enough

darwin21:09:59

but maybe I'm wrong here

andrewboltachev21:09:12

In fact, first I'm using project called rewrite-clj to add this (dbg ...) forms

andrewboltachev21:09:48

(which has that positions info and I'll inject it to there)

darwin21:09:14

you lost me here, if I remember correctly rewrite-clj does source->data->source transformation, or you can use it from a macro? by feeding it forms?

andrewboltachev21:09:02

well, I'm first editing a code (say, whole namespace of files) to wrap every 1st member of list with (dbg first-member)

andrewboltachev21:09:21

(fn1 a b) -> ((dbg fn1) a b)

andrewboltachev21:09:35

(before that require is added to include the dbg)

darwin21:09:22

so now you are doing source -> source transformation, right? without clojure macros

andrewboltachev21:09:36

yes, that's the 1st step

andrewboltachev21:09:51

and then it's everything (functions and macros) wrapped with dbg, thus dbg macro should leave macros as-is and make functions log themselves

andrewboltachev21:09:00

(and in the end I want to build whole call stack/tree and see like wow, it's what has happened when I've ran a request in my very-huge-and-hard-to-debug-project)

darwin21:09:32

I'm afraid this is not going to work. If you rewrite code (my-macro 1 2 3) into ((dbg my-macro) 1 2 3) you change meaning of it, it might not compile at all, if my-macro checks args

andrewboltachev21:09:10

uhm this is also a problem

andrewboltachev21:09:19

I was comparing ((dbg my-macro) 1 2 3) vs. (dbg my-macro 1 2 3) vs. (dbg (my-macro 1 2 3)) etc

darwin21:09:53

and secondary minor problem which comes to my mind is that rewrite-clj does not use tools.reader, they have their own reader, it won't be able to read everything the same way normal clojure reader would

andrewboltachev21:09:02

well, it's "based" on it, but does provide it's own stuff

andrewboltachev21:09:20

uhm, here on real code have another "Can't take value of a macro:" error

darwin21:09:50

wait I take my "I'm afraid this is not going to work" note back, I was thinking about dbg as function, but it is a macro

andrewboltachev21:09:01

oops, it was one with resolve. Will try "eval"

darwin21:09:59

I think you should go (dbg my-macro 1 2 3) route, look at 1st arg and decide what code to emit based on it

andrewboltachev21:09:50

this has failed: (-> x (dbg my-macro 1 2 3))

darwin22:09:05

@andrewboltachev maybe you could mark my-macro arg in 1st phase (dbg (my-marker my-macro) 1 2 3) and make dbg flexible to look it up and remove it from any position

andrewboltachev22:09:53

uhm, might also work btw!

darwin22:09:55

but still it would not be perfect solution, more complex macros could get puzzled by extra arg there

andrewboltachev22:09:36

uhm I'm still having "Can't take value of a macro"

andrewboltachev22:09:28

I mean with (dbg (...original expr...))

andrewboltachev23:09:29

btw how crazy is this:

andrewboltachev23:09:34

(println "foo" ((dbg when) true "Hello world111!"))
      (println "bar" (when true "Hello world222!"))

andrewboltachev23:09:46

foo Hello world111!
bar nil

andrewboltachev23:09:54

(it's inside file itself)

andrewboltachev23:09:09

sorry. wrong chat 🙂