beginners

Getting started with Clojure/ClojureScript? Welcome! Also try: https://ask.clojure.org. Check out resources at https://gist.github.com/yogthos/be323be0361c589570a6da4ccc85f58f.
st3fan 2020-11-15T01:24:45.247300Z

Oh nice that is like Python’s StringIO

kmyokoyama 2020-11-15T01:27:24.249100Z

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)?

Ben Sless 2020-11-15T10:08:20.251400Z

Just beware if your functions are side-effectful. Laziness + futures + side effects = sadness

kmyokoyama 2020-11-15T01:31:45.249200Z

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

jsn 2020-11-15T01:58:12.249500Z

`(defmacro m [& args] `(list ~@(for [a# args] `(future ~a#))))` ?

👍 1
kmyokoyama 2020-11-15T02:01:33.249800Z

It works, thanks.

souenzzo 2020-11-15T02:10:39.250Z

Without macros

(map (fn [[f & args]] (future (apply f args)))  [[prn 1] [prn 2]])

2020-11-15T02:12:04.250200Z

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=>

2020-11-15T02:12:30.250400Z

(uses pmap, so gross)

2020-11-15T02:12:50.250600Z

in general laziness + futures = weirdness

kmyokoyama 2020-11-15T02:24:53.251200Z

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.

Tony Vo 2020-11-15T17:33:30.253400Z

Hi, I ran into this issues and couldn't figure it out

Tony Vo 2020-11-15T17:34:02.253500Z

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))

Tony Vo 2020-11-15T17:34:30.253700Z

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])))
  )

Tony Vo 2020-11-15T17:34:53.253900Z

with the world-of-two define as:

(def world-of-two #{[0 0] [0 1]})

Tony Vo 2020-11-15T17:35:32.254100Z

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)

uosl 2020-11-15T17:37:38.254300Z

Should (get-all-neighbors [world-of-two]) perhaps be (get-all-neighbors world-of-two)? It seems to fail at destructuring.

Tony Vo 2020-11-15T17:38:20.254500Z

damn .. you're right

Tony Vo 2020-11-15T17:38:26.254700Z

this is the second time I ran into this issue

Tony Vo 2020-11-15T17:38:45.254900Z

keep forgetting I don't need to use [] on method invocation

Tony Vo 2020-11-15T17:38:53.255100Z

BAD HABIT!!!!!

uosl 2020-11-15T17:39:01.255300Z

haha, I'm curious where that habit comes from?

Tony Vo 2020-11-15T17:39:37.255500Z

java

Tony Vo 2020-11-15T17:39:44.255700Z

actually it still fail after removing that []

Tony Vo 2020-11-15T17:40:33.255900Z

@regen

uosl 2020-11-15T17:40:48.256100Z

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])

Tony Vo 2020-11-15T17:42:16.256300Z

yeah ... from repl .. that's what I print out for me

Tony Vo 2020-11-15T17:42:26.256500Z

but from lein spec, it failed

uosl 2020-11-15T17:42:56.256700Z

can you try quoting the list after should=?

uosl 2020-11-15T17:43:11.256900Z

so it becomes (should= '(

Tony Vo 2020-11-15T17:43:28.257100Z

damn .. quote works

Tony Vo 2020-11-15T17:43:40.257300Z

thanks @regen

uosl 2020-11-15T17:43:51.257500Z

No problem! Remember that lists will get evaluated if you don't quote them.

Tony Vo 2020-11-15T17:44:07.257700Z

what do list evaluated to?

uosl 2020-11-15T17:44:11.257900Z

Like a function

Tony Vo 2020-11-15T17:44:31.258100Z

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])

uosl 2020-11-15T17:44:34.258300Z

So ([1 0] [-1 0] ... will basically try to call the first vector as a function, with everything else as arguments.

Tony Vo 2020-11-15T17:44:37.258500Z

without the quote?

uosl 2020-11-15T17:44:59.258700Z

yes. I get Wrong number of args (15)

uosl 2020-11-15T17:45:25.258900Z

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.

uosl 2020-11-15T17:46:03.259100Z

Also, lists and vectors are treated as equal in Clojure (= [] '()), so it's more common to use vector literals in tests like that

Tony Vo 2020-11-15T17:46:46.259400Z

thanks ... this is deep

uosl 2020-11-15T17:47:01.259600Z

hehe, it will come naturally soon enough [=

Tony Vo 2020-11-15T18:05:06.259800Z

thanks, it's my fervent hope and dream

👍 1
Santiago 2020-11-15T19:18:22.264800Z

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?

seancorfield 2020-11-15T19:20:06.265500Z

merge-with into might do what you need -- depending on what other types of values you have in the map.

seancorfield 2020-11-15T19:20:45.265800Z

user=> (merge-with into a b)
{:foo [123 888], :bar [345 777], :buzz [45]}
user=>
@slack.jcpsantiago

Santiago 2020-11-15T19:21:22.266500Z

ah I knew there was an elegant solution for this instead of monkeying around 😄 yeah that’s what I was looking for thanks!

seancorfield 2020-11-15T19:21:58.267200Z

Note: if you have values in the map that are not vectors, merge-with into will fail -- because into can only merge vectors.

Santiago 2020-11-15T19:23:43.267600Z

:thumbsup:

2020-11-15T20:00:52.273800Z

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.

rakyi 2020-11-15T20:07:05.273900Z

check https://clojuredocs.org/clojure.core/some-%3E and co

seancorfield 2020-11-15T20:17:33.274200Z

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.

seancorfield 2020-11-15T20:18:03.274400Z

(note: and won't work if you values can be false -- you'd need some-> in that case)

2020-11-15T21:03:45.276800Z

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();
    }
}

2020-11-15T21:05:42.278300Z

In the try block, the exportObject take 2 arguments. The second one is referencing the current class with this. How can I interop?

2020-11-15T21:06:34.278800Z

Currently I had:

(defn start []
  (let [dbus-conn (. DBusConnection getConnection DBusConnection/SESSION)]
    (doto dbus-conn
        (.requestBusName "mon.premier.bus")
        (.exportObject "/Main" ?))))

2020-11-15T21:08:19.279600Z

I don't know what to replace the question mark with.

2020-11-15T21:11:00.279800Z

Any clue?

2020-11-15T21:12:43.280700Z

Do I have to use reify?

2020-11-15T21:14:04.282300Z

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?

2020-11-15T21:18:09.283900Z

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.

2020-11-15T21:29:27.284200Z

Thanks guys, that was what I was looking for but somehow Google failed me

2020-11-15T21:32:09.284400Z

Thx @andy.fingerhut

2020-11-15T21:36:00.286500Z

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);
}

2020-11-15T22:00:59.288400Z

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?

2020-11-15T22:36:05.288700Z

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)))

2020-11-16T14:53:22.306500Z

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.

2020-11-16T14:53:32.306700Z

Do you need to create a new interface for this?

2020-11-16T15:15:18.306900Z

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();
    }
} 

2020-11-16T15:18:59.307200Z

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.

2020-11-16T15:20:33.307400Z

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 definterfaceat 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.

2020-11-16T15:21:21.307600Z

I feel like in this case I have to go through gen-class, right?

2020-11-16T15:21:25.307800Z

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.

2020-11-16T15:22:06.308Z

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.

2020-11-16T15:23:07.308200Z

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?

2020-11-16T15:23:37.308400Z

If it were in code outside of that class, instead of this you would pass a reference to the object to exportObject

2020-11-16T15:24:44.308600Z

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.

2020-11-16T15:26:30.308800Z

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.

2020-11-16T15:29:58.309Z

I get this error Execution error (DBusException) at org.freedesktop.dbus.Marshalling/recursiveGetDBusType (Marshalling.java:241). Exporting non-exportable type interface clojure.lang.IPersistentMap

2020-11-16T15:32:10.309200Z

The evaluated "reify object" #object[main.core$start$reify__149 0x4d666b41 main.core$start$reify__149@4d666b41]

2020-11-16T15:32:34.309400Z

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.

2020-11-16T15:35:28.309600Z

I understand, I thank you for all these advices! Have a good day.

2020-11-15T22:39:47.290600Z

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 ...)

👍 1
2020-11-15T22:40:24.291200Z

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