Oh nice that is like Python’s StringIO
Is there a way to create a macro (let's call it m
) that works like that: (m (f 1) (f 2))
expands to ((future (f 1)) (future (f 2)))
, ie a seq of future
calls (note that (f 1)
and (f 2)
were not evaluated yet)?
Just beware if your functions are side-effectful. Laziness + futures + side effects = sadness
The problem with, say,
(defmacro m
[& fns]
`(map #(future %) ~fns))
Is that it expands to something like
(clojure.core/map (fn* [p1__11890__11891__auto__] (clojure.core/future p1__11890__11891__auto__)) ((f 1) (f 2)))
and then (f 1)
and (f 2)
get evaluated before the map
takes place`(defmacro m [& args] `(list ~@(for [a# args] `(future ~a#))))` ?
It works, thanks.
Without macros
(map (fn [[f & args]] (future (apply f args))) [[prn 1] [prn 2]])
user=> (doc pvalues)
-------------------------
clojure.core/pvalues
([& exprs])
Macro
Returns a lazy sequence of the values of the exprs, which are
evaluated in parallel
nil
user=>
(uses pmap, so gross)
in general laziness + futures = weirdness
Thank you all for the answers! pvalues
is exactly what I was trying to do in the end. Well, looking at the source code for pvalues
, and then pcalls
, and finally pmap
, I think it was not a trivial task at all.
Hi, I ran into this issues and couldn't figure it out
here's the prod code:
(defn get-neighbors [[x y]]
#{[(dec x) (inc y)] [x (inc y)] [(inc x) (inc y)]
[(dec x) y] [(inc x) y]
[(dec x) (dec y)] [x (dec y)] [(inc x) (dec y)]})
(defn get-all-neighbors [world]
(mapcat #(get-neighbors %) world))
and here's my test code:
(context "get-all-neighbors"
(it "should return all neighbors"
(should= ([1 0] [-1 0] [1 1] [-1 -1] [1 -1] [-1 1] [0 -1] [0 1] [0 0] [1 0] [-1 0] [1 1] [-1 2] [0 2] [-1 1] [1 2]) (get-all-neighbors [world-of-two])))
)
with the world-of-two define as:
(def world-of-two #{[0 0] [0 1]})
and herew's the error I get:
1) Game of life get-all-neighbors should return all neighbors
nth not supported on this type: PersistentHashSet
java.lang.UnsupportedOperationException: nth not supported on this type: PersistentHashSet
... 2 stack levels elided ...
at game_of_life$get_neighbors.invokeStatic(game_of_life.clj:4)
at game_of_life$get_neighbors.invoke(game_of_life.clj:4)
at game_of_life$get_all_neighbors$fn__10467.invoke(game_of_life.clj:10)
... 9 stack levels elided ...
at game_of_life$get_all_neighbors.invokeStatic(game_of_life.clj:10)
at game_of_life$get_all_neighbors.invoke(game_of_life.clj:9)
Should (get-all-neighbors [world-of-two])
perhaps be (get-all-neighbors world-of-two)
? It seems to fail at destructuring.
damn .. you're right
this is the second time I ran into this issue
keep forgetting I don't need to use [] on method invocation
BAD HABIT!!!!!
haha, I'm curious where that habit comes from?
java
actually it still fail after removing that []
I ran your code without the [] and it seems to work for me: ([1 0] [-1 0] [1 1] [-1 -1] [1 -1] [-1 1] [0 -1] [0 1] [0 0] [1 0] [-1 0] [1 1] [-1 2] [0 2] [-1 1] [1 2])
yeah ... from repl .. that's what I print out for me
but from lein spec, it failed
can you try quoting the list after should=
?
so it becomes (should= '(
damn .. quote works
thanks @regen
No problem! Remember that lists will get evaluated if you don't quote them.
what do list evaluated to?
Like a function
so what does this evaluate to ? -> ([1 0] [-1 0] [1 1] [-1 -1] [1 -1] [-1 1] [0 -1] [0 1] [0 0] [1 0] [-1 0] [1 1] [-1 2] [0 2] [-1 1] [1 2])
So ([1 0] [-1 0] ...
will basically try to call the first vector as a function, with everything else as arguments.
without the quote?
yes. I get Wrong number of args (15)
but if you had ([1 0] 0)
it would return 1, since you can use vectors as functions with the index to get as an argument.
Also, lists and vectors are treated as equal in Clojure (= [] '())
, so it's more common to use vector literals in tests like that
thanks ... this is deep
hehe, it will come naturally soon enough [=
thanks, it's my fervent hope and dream
How would you conj
vals in equal keys in different maps to create a single map?
(def a {:foo [123] :bar [345] :buzz [45]})
(def b {:foo [888] :bar [777]})
; result should be {:foo [123 888] :bar [345 777] :buzz [45]}
I feel there’s some combo of reduce
and map
involved here?merge-with into
might do what you need -- depending on what other types of values you have in the map.
user=> (merge-with into a b)
{:foo [123 888], :bar [345 777], :buzz [45]}
user=>
@slack.jcpsantiagoah I knew there was an elegant solution for this instead of monkeying around 😄 yeah that’s what I was looking for thanks!
Note: if you have values in the map that are not vectors, merge-with into
will fail -- because into
can only merge vectors.
:thumbsup:
Is there a corelib function that is the equivalent of F#s Option.map? Basically, I want to do nil punning for my functions. This function would take as input my function F, and return a function that, if has input nil, returns nil. If input is non nil, pass it to my function F Is there such a wrapper function? Or is this not something that clojurians do? I come from a F# background so this is how I was approaching this problem. Background: I have a function that takes in a string and does some processing. I want to map this function over a Map (for a given set of keys), but it is possible the Map doesn't have the key, so it might return nil. In this case, I want to punt the nil down the line, so to speak.
check https://clojuredocs.org/clojure.core/some-%3E and co
Or (map #(and % (f %)) data)
depending on whether you just want to apply one function or, via some->
, short-circuit a chain of function calls.
(note: and
won't work if you values can be false
-- you'd need some->
in that case)
Hi!
I tried to implement this following Java code in Clojure and I have a question about this
keyword:
package hello;
import org.freedesktop.dbus.DBusConnection;
import org.freedesktop.dbus.exceptions.DBusException;
public class DBusHelloWorldServer implements DBusHelloWorldInterface
{
private DBusConnection dbusConnection;
public boolean isRemote()
{
return false;
}
private boolean stop=false;
public String helloWorld(String name)
{
stop=true;
return "Hello World : "+name;
}
public void start()
{
try
{
System.out.println(this);
dbusConnection = DBusConnection.getConnection(DBusConnection.SESSION);
dbusConnection.requestBusName("mon.premier.bus");
dbusConnection.exportObject("/Main", this);
while (!stop)
{
try {
Thread.sleep(1000);
} catch (Exception e) {}
}
dbusConnection.disconnect();
}
catch (DBusException e)
{
e.printStackTrace();
}
}
public static void main(String[] args)
{
new DBusHelloWorldServer().start();
}
}
In the try block, the exportObject take 2 arguments.
The second one is referencing the current class with this
.
How can I interop?
Currently I had:
(defn start []
(let [dbus-conn (. DBusConnection getConnection DBusConnection/SESSION)]
(doto dbus-conn
(.requestBusName "mon.premier.bus")
(.exportObject "/Main" ?))))
I don't know what to replace the question mark with.
Any clue?
Do I have to use reify
?
In the Java code, the this
is passing the instance of class DBusHelloWorldServer from which the call to the exportObject method is being made. Presumably that because the dBusConnection object is going to do something with that object reference. Do you know what it will do with it? e.g. will it call some method on that object later? Save it in some data structure? Something else?
From within a normal Clojure function defined at the top level, there is no this
enclosing object that makes sense to refer to. But if you create an object, as you suggest using reify
, then inside of the reify
you can specify an implementation for any number of methods you want, and all of their bodies will have access to a this
reference for that object.
Thanks guys, that was what I was looking for but somehow Google failed me
Thx @andy.fingerhut
Here is the exportObject method doc: https://dbus.freedesktop.org/doc/dbus-java/api/org/freedesktop/dbus/AbstractConnection.html#exportObject(java.lang.String,%20org.freedesktop.dbus.DBusInterface)
Maybe I must also implement the extended Interface with reify and reference it.
import org.freedesktop.DBus;
import org.freedesktop.dbus.DBusInterface;
public interface DBusHelloWorldInterface extends DBusInterface
{
@DBus.Description("Petit message de HelloWorld avec un nom en paramètre")
public String helloWorld(String nom);
}
So yes, the object passed as the second argument needs to implement an interface which extends DBusInterface
.
You advise me to use gen-class
or reify
to extend an interface?
How can I do that?
I believe it might look something like this with reify
:
(ns some.ns
(:import (some.package.here.where.this.interface.is.defined DBusHelloWorldInterface)))
(reify
DBusHelloWorldInterface
(isRemote [this]
false)
(helloWord [this name]
(str "Hellow World : " name)))
There is definterface
in Clojure, but it does not provide all of the options for creating interfaces that Java does. In particular, it isn't clear to me whether you can use it to create an interface that extends another interface.
Do you need to create a new interface for this?
Thanks for still being here and for the help @andy.fingerhut
I appreciate.
> Do you need to create a new interface for this?
No, I don"t think so.
I follow this tutorial https://artisan.karma-lab.net/mise-oeuvre-dbus-sous-java who can be simplified in one class implementing DBusInterface
like that:
package hello;
import org.freedesktop.dbus.DBusInterface;
import org.freedesktop.dbus.DBusConnection;
import org.freedesktop.dbus.exceptions.DBusException;
public class DBusHelloWorldServer implements DBusInterface
{
private DBusConnection dbusConnection;
private boolean stop=false;
public boolean isRemote()
{
return false;
}
public String helloWorld(String name)
{
stop=true;
return "Hello World : "+name;
}
public void start()
{
try
{
dbusConnection = DBusConnection.getConnection(DBusConnection.SESSION);
dbusConnection.requestBusName("mon.premier.bus");
dbusConnection.exportObject("/Main", this);
while (!stop)
{
try {
Thread.sleep(1000);
} catch (Exception e) {}
}
dbusConnection.disconnect();
}
catch (DBusException e)
{
e.printStackTrace();
}
}
public static void main(String[] args)
{
new DBusHelloWorldServer().start();
}
}
Now I still can't see how to pass the current reference to the exportObject
method, because it must be a class that implements DBusInterface.
If you can find a way to do it in Clojure without using capabilities that definteface
does not have, or if you can do it without using definterface
at all, then great. There are cases in Clojure where to interface with some things in Java, you need capabilities that Java has of creating classes or interfaces that Clojure cannot do itself (because it wasn't designed to create those things with every possible option, only the ones judged most likely to be useful from a Clojure program). In such cases, I believe most Clojure developers write the smallest amount of Java code they can, compile it, and use those classes or interfaces from Clojure.
I feel like in this case I have to go through gen-class, right?
reify
can be used to create a JVM object that implements one or more interfaces, including DBusInterface. It returns a reference to the new JVM object it creates. You can save that reference wherever you like.
Just as you can call new SomeClass()
in Java and save the return value in any variable or field you want, and then use it later by that name.
All that code in the start
method can be in a method that is within the class, but it could be in code outside of that class too, yes?
If it were in code outside of that class, instead of this
you would pass a reference to the object to exportObject
Maybe there are benefits to using gen-class
that are not clear to me at the moment, but I do not yet see a reason why gen-class
is necessary.
This is what I tried first by following your advice but I had an output error. Wait, I'll try again and tell you the error message.
I get this error Execution error (DBusException) at org.freedesktop.dbus.Marshalling/recursiveGetDBusType (Marshalling.java:241). Exporting non-exportable type interface clojure.lang.IPersistentMap
The evaluated "reify object" #object[main.core$start$reify__149 0x4d666b41 main.core$start$reify__149@4d666b41]
Sorry, often I would be ready to jump in and try to reproduce this issue and think of alternatives, but I'm under some schedule pressure for work today, so not right now. Hopefully someone else may be able to help. There is also a #java channel that might be helpful in finding folks who often interoperate between Clojure and Java.
I understand, I thank you for all these advices! Have a good day.
Or rather, you would assign the return value from that (reify ...)
expression to some variable somewhere, perhaps at the top level with (def dbus-hello-world-server (reify ...))
, or (let [dbus-hello-world-server (reify ...)] ... code here that looks like code in your Java code's start() method ...)
The code that you would write that looks like the Java's start
method you showed would use dbus-hello-world-server
instead of this