Fork me on GitHub
#clojure
<
2016-09-18
>
ezmiller05:09:09

has anyone else had the experience working with vim that commented out text doesn’t get highlighted as such?

andmed06:09:08

hi. cant get it about java interop. this works

public static void main(String[] args) throws Exception {
        Path path = Paths.get("test.txt");
        Reader reader = Files.newBufferedReader(path);
    }
(file not found). this
(let [path (Paths/get "test.txt")
        reader (Files/newBufferedReader path)])
does not work Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.net.URI, compiling:(/tmp/form-init6447706182627723560.clj:1:73

andmed06:09:29

are these calls not equivalent? environment is the same

andmed06:09:20

yes, call with URI is overloaded in Paths/get but for some reason Clojure version can't see the call with String

hiredman06:09:50

Paths.get is a java var args method, which at the jvm bytecode level means the arguments are passed as an array, so that is what you do from Clojure

hiredman07:09:15

you have to pass an array of Strings

andmed07:09:49

@hiredman oh, i see, thanks!

Abhinav Sharma13:09:39

Hii people!! I have this question about VMs and libraries. Why do we make separate clojure libraries with sane functionality as the native VM ( like strings etc) in clojure(script)? What exactly is the benefit that we gain from native implementation?

akiva13:09:18

Hi, @abhi18av. A lot of people don’t like interop so there are a lot of wrappers out there around Java. Sometimes, however, it simply has to do with Clojure’s LISPness and how it does certain things for performance reasons.

akiva13:09:44

Personally, I try to avoid bare metal Java as often as I can. For no real reason, really. I’m just not a huge fan of the interop syntax.

Madara Uchiha13:09:57

Guys, is there an equivalent to JavaScript's Promise.all() in Clojure?

Madara Uchiha13:09:07

In JavaScript, if you have an async action, you have the function running the action return a Promise, you can then pass an array of Promise objects to Promise.all(), and it then returns a Promise which resolves when all of the promises of the array have been resolved, with an array of values in the same order as the promises, or rejects when the first Promise rejects.

Madara Uchiha13:09:25

(Promises in JS are more similar to Clojure's future type)

Madara Uchiha13:09:14

While I like the way of processes and channels, more often than not I just need a value from a function, and just wait until it's available, sometimes I just want something like

Abhinav Sharma13:09:24

Oh, right. Thanks @akiva. Also, is there another benefit that we can by default parallelism the library internals while recreating the functionality as a Clojure lib?

akiva13:09:15

There is some really serious optimization going on behind the scenes, if that’s what you mean.

kauko13:09:22

@madarauchiha so in the snippet's case, you'd want a list of get-url results?

Madara Uchiha13:09:44

No, I would like a single future that would resolve with a collection of results

Madara Uchiha13:09:13

Assuming that get-url performs a GET request on the URL and returns the body of the result

Madara Uchiha13:09:44

I would want future-all to return a future for a collection of bodies, in the same order as the original urls collection.

Madara Uchiha13:09:47

JavaScript also has future-race which would return a future that resolves with the result of the first future that resolves (`Promise.race()` in JS)

Madara Uchiha13:09:00

But that's less of an obvious usecase.

Madara Uchiha13:09:01

(The obvious usecase is a timeout Promise.race([doAction(), rejectAfter(2000)]); Promise that resolves with the result of doAction() but rejects after 2000ms if it hadn't resolved by then)

kauko13:09:11

Hmm, can't immediately think of a solution that doesn't use channels

Madara Uchiha13:09:35

If it accepts a collection of futures and returns a future, I don't mind the internal details.

Madara Uchiha13:09:56

While an implementation of this would be a fun exercise and I would be happy to see what people can come up with

Madara Uchiha13:09:06

I was wondering if Clojure had something like it builtin

kauko13:09:46

I've never really used Clojure's futures, promises or delays tbh

kauko14:09:04

mostly core.async

Madara Uchiha14:09:12

A delay is essentially a memoized function, I'm still struggling between the differences between promises and futures

Madara Uchiha14:09:44

But the idea is, while processes and communication channels are nice you often just need a function and a result.

kauko14:09:50

A promise is initially a barren container for a value, and at some point a value will be delivered to it

Madara Uchiha14:09:50

Without the full blown structure around it.

kauko14:09:02

Futures are blocks of code

Madara Uchiha14:09:15

@kauko Right, so a promise is essentially a deferred

Madara Uchiha14:09:28

Which is less pretty than JavaScript's Promise object

Madara Uchiha14:09:51

In JS, we used to have deferred values as well

Madara Uchiha14:09:24

You'd create a new $.Deferred() then continue execution, then sometime in the future call d.resolve(value) or d.reject(err)

Madara Uchiha14:09:38

At the end of the function, you immediately return d.promise()

Madara Uchiha14:09:44

The problems with that approach were primarily OO based, since this new $.Deferred() constructor isn't really a constructor, because it doesn't bring the object to a usable state (you still need to call .reject() or .resolve() on it, as well as .promise() to get anything meaningful out of it

Madara Uchiha14:09:07

The newer Promise constructor accepts a function with two parameters, which are also functions, resolve and reject

Madara Uchiha14:09:18

Essentially merging Clojure's future and promise into one

Madara Uchiha14:09:48

(Those were 180 seconds of JavaScript history, with MadaraUchiha)

Madara Uchiha14:09:24

In any case, one thing that no one ever seems to talk about (at least, the brave and true never mentions so far) is how to handle errors

Madara Uchiha14:09:36

If I have my get-url function, and I encounter a server error

Madara Uchiha14:09:39

How do I handle it?

pseud16:09:26

Spent hours on this and I can’t seem to cobble together enough macro understanding to get it done, I’m at an impasse. http://paste.ubuntu.com/23198691/ Why exactly does evaluation explode when I give a variable instead of a value ? My hypothesis is that I’m still playing with the symbol myvar instead of its actual value {:incr 1}. Now that’s great and all but how would I remedy that ?

pseud16:09:56

@madarauchiha the project I work on uses the promesa library for promises ( http://funcool.github.io/promesa/latest/ ) in that case, there’s a catch function in core. See the “Error handling” part of the link.

ghadi16:09:02

created this to turn java objects into printable map-like things https://gist.github.com/ghadishayban/c36368d1de6ce15ba2a782c3cfc9211a kind of like a more modern version of clojure.core/bean

ghadi16:09:31

bean is cool but it re-reflects on every object

Abhinav Sharma17:09:12

@akiva, I see. Btw is there a way to use C/C++ libs in Clojure? No not the JNI but is there a port of the project towards this goal?

akiva17:09:01

It can only do what Java can do.

pseud17:09:06

Question while I idle — is it a crime to use eval in clojure ? I have a macro problem (basically I can’t expand a variable into its value in a macro - and I need this structure because I’m trying to stuff it into a ‘case’ form which is also a macro). Anyway - long story short, I can build up a list representing the case form I’d like - but I may need to eval that list to eventually make it do something. So… is using ‘eval’ the worst thing possible, ever.. or is it legitimate in some instances

weavejester19:09:27

@pseud eval is fine, as long as you’re aware of all that it does.

weavejester19:09:19

It’s unsafe, so sanitise your inputs, and often, but not always, there are more efficient/safer/simpler ways to achieve the same thing.

weavejester19:09:15

But sometimes eval is necessary. Sometimes it’s useful to compile a declarative data structure into a function, for instance.

arohner19:09:21

is there a swagger lib for generating client fns? I have a server serving swagger, and I want to auto-gen the fns to call the API using clj-http

pseud20:09:16

There is no way to replace a variable by its value before going into a macro, right ? Essentially (mymacro x) => (mymacro {:k1 “v1”}) The reason I ask is that my macro needs to compute on the literal structure of the map and this (obviously) fails if I just get a symbol for a variable.

seancorfield20:09:54

@pseud Correct, macros execute before code is actually evaluated. They transform code to code, there are no values at that point.

seancorfield20:09:37

Generally, with macros, it’s best to write what you want as a function first, and then use the macro to create a layer of syntactic sugar over the function(s).

seancorfield20:09:58

Unless you have a very specific syntax tweak and can write a simple macro straight off 🙂

pseud20:09:14

likewise there’s no layering of lambdas and calls to macros within macros to be sneaky and coax out a value of an incoming var, right ?

darwin20:09:42

@pseud not in general, you could use eval in specific scenarios (basically re-reading your source and eval-ing interesting bits of it)

darwin20:09:58

but eval is evil in hands of plebs 🙂

pseud20:09:41

I’d love to, but (confession time), I was writing something in a clojure repl and have battled all day with splicing a body into a case-statement. Now in clojure, I finally tried out building a list and passing it to eval - that worked beautifully, but using that in clojurescript later on will be… problematic 😞

seancorfield20:09:44

The evaluation context inside a macro is not going to be the same as for normal code so "Here Be Dragons!" on that...

seancorfield20:09:42

Yeah, this is why macros (and eval) should be considered a "last resort". Aside from portability issues to cljs, they don’t compose and your code won’t "scale" in complexity.

darwin20:09:24

@pseud what is that x ? what is your end goal? maybe we could find some solution

darwin20:09:38

it is possible to go quite far if the things you feed into macro boil down to constants, or expressions of constants and limited set of clojure functions, here I was able to build a simple css cljs macro, which accepts clojure-code as input, to produce validated css strings as output: https://github.com/binaryage/cljs-devtools/blob/fd117bce8e777de190605e4c693604bc9074aa66/src/lib/devtools/defaults.cljs#L226 https://github.com/binaryage/cljs-devtools/blob/fd117bce8e777de190605e4c693604bc9074aa66/src/lib/devtools/defaults.clj#L79-L87

pseud20:09:11

@darwin - x is a map of keywords -> fn’s I wanted then to make a macro which spat out a new function which had a case-form whose body is made from processing the aforementioned map such that I eventually get a structure like

[:incr ((fn [m a] …) m a)
 :decr ((fn [m a] …) m a]
Because, with such a structure, it’s trivial to spit out a case-form and voilá, from a map of functions down to a case-form that I want.

pseud20:09:56

But naturally, the argument I get in a macro just evaluates to a symbol, now If I input an actual map of keywords -> fns everything is perfect.. But passing in a var will obviously explode as I’m then trying to rearrange the structure of a single symbol (in this case ‘x’)

darwin21:09:09

so, x is known at compile time, why don’t you write a macro which will produce x (data), then expand it in place when passing it to mymacro?

pseud21:09:22

Not sure I follow

pseud21:09:01

The point of the variable is not that I have a def somewhere. The point is that I wanted to treat these initial maps as well.. maps. Be able to merge them etc before generating the resulting function holding the case form

darwin21:09:34

instead (mymacro x) write (defmacro x [] {:some “data”}) and later (mymacro (x))

darwin21:09:01

if you need to work on those maps, you have to do it at compile-time, that means in functions called from macros or macros themselves

darwin21:09:43

x is not seen at runtime, unless you decide to export it as data, e.g. like this (def runtime-x (x))

darwin21:09:34

I know it is a bit mind-bending, you have to know exactly “where you stand” when looking at code

pseud21:09:33

Ah, so in that case, I’d have to do whatever processing I want (e.g. merge, rename-keys) etc in macros, too.

darwin21:09:09

this is often the case, once you switch something to a macro, all inputs have to be turned into macros as well

darwin21:09:57

because you are not working with runtime values anymore, you are working with compile-time values and doing fancy code-rewriting

pseud21:09:00

Oh case form how I hate you 😠

pseud21:09:10

@darwin Well, that’s certainly something to think about. I’ll have a go at it tomorrow. I think 8+ hours of battling macros today has turned my brain to mush. But thanks 🙂

darwin21:09:26

np, good luck!

yury.solovyov21:09:39

@madarauchiha I think it is possible to employ pipeline-* stuff from core.async for this, though I'm not sure it would look super nice