Fork me on GitHub
#clojure
<
2024-01-10
>
p-himik12:01:00

I almost never use Java interop besides calling a few functions, so I'm a bit surprised that Clojure's set! doesn't have an arity that's usable with doto, like ClojureScript does. So in ClojureScript, this construct is valid:

(def obj (doto (create-obj)
           (set! -field1 1)
           (set! -field2 2)))
Would it make sense to extend set! in Clojure to have that arity?

👍 1
delaguardo12:01:55

https://cljs.github.io/api/cljs.core/#setBANG interesting... api reference for cljs doesn't mention this arity

p-himik12:01:37

Hm, right. It's in the impl though, and it's maintained. Perhaps it should be mentioned in the docs as well.

delaguardo13:01:29

yeah, it should be) that would safe me many keystrokes 😄

Maris15:01:50

I am using https://github.com/plumatic/schema/blob/master/src/clj/schema/experimental/generators.clj Is it possible to set a limit of how many items it will generate?

Maris16:01:11

(s/optional-key :descriptions)    (s/constrained
                                      [{:name                                     (non-blank-str-max-length 120)                                     
                                        (s/optional-key :photo-urls)              [(non-blank-str-max-length 250)]}]
                                      #(<= (count %) 99))

Maris16:01:47

This is my schema ^. There is a problem with such-that when more than 99 descriptions gets generated.

p-himik16:01:24

Hi. Can't help with your question, but for future reference, please start topics in a single message. Slack allows using a thread to add extra details or edit the original post where Shift+Enter can add a new line without sending the message.

p-himik16:01:20

It seems that sample works on the top level, when you yourself call it. But I think OP needs to generate, say, a map where a value for a particular key is a collection with fewer than 100 items.

Maris16:01:16

I want to generate ~300 (or more) samples. Sometimes it creates more that 99 descriptions and throws runtime exception.

Maris16:01:15

Couldn't satisfy such-that predicate after 10 tries.

p-himik16:01:21

At least with spec, you can attach a custom generator to a spec. Perhaps the same can be done here.

Maris16:01:33

maybe… I will have a look.

Takis_22:01:13

how to write this in clojure?

public class HelloVerticle extends AbstractVerticle {

    @Override
    public void start() {
        Vertx vertx= super.getVertx();
        System.out.println(this.toString());
    }

    public static void main(String[] args) {
       Vertx vertx = Vertx.vertx();
       vertx.deployVerticle(new HelloVerticle());
    }
}
i tried :gen-class with -start method and i got java.lang.ClassFormatError: Duplicate method name "start" with signature "()V" in class file vertxx/HelloVerticle

hiredman22:01:24

I wouldn't try to copy exactly what the java code is doing

hiredman22:01:40

what you pass to deployVerticle just needs to implement the Verticle interface

hiredman22:01:30

https://github.com/vertx-clojure/vertx/blob/master/src/vertx/core.clj is old and marked as alpha, but may be useful to see how they interact with vertx without doing all the weird stuff java examples do in the name of brevity

Takis_22:01:22

this core.clj, looks complicated, for now i want to extend AbstractVerticle and override its start() method

Takis_22:01:40

i am reading a vert.x book, and trying the code

hiredman22:01:03

then use proxy

Takis_22:01:22

i tried that also, but start wasnt called at all

Takis_22:01:44

but maybe i did something wrong

hiredman22:01:20

should it be called?

Takis_22:01:23

vertx.deployVerticle(new HelloVerticle());
this will call the start

hiredman22:01:27

the docs you are looking at are out of date

hiredman22:01:07

start takes an argument, and an exception is being thrown, but on a different thread and is communicated back via the promise like object that deploy returns

hiredman22:01:35

% clj -Sdeps '{:deps {io.vertx/vertx-core {:mvn/version "4.5.1"}}}'
Clojure 1.11.1
(def vertx (io.vertx.core.Vertx/vertx))

(.deployVerticle vertx
                 (proxy [io.vertx.core.AbstractVerticle] []
                   (start [_]
                     (println "hello world"))))
#'user/vertx
user=> user=> hello world
#object[io.vertx.core.impl.future.Mapping 0xef1695a "Future{unresolved}"]
user=>

Takis_22:01:39

on AbstractVerticle class not the Verticle interface, there is a start method without argument, the java code that i sended is working ok

hiredman22:01:12

but proxy overrides by name only

hiredman22:01:37

so overriding start via proxy will override and start methods regardless of arg count

Takis_22:01:07

i was using it like start [] without argument, because it has 2 start methods one without and one with a Promise

Takis_22:01:23

start [] nothing was called

hiredman22:01:02

the implementation of AbstractVerticle is likely the 1 arg start method is calling the 0 arg start method

hiredman22:01:30

but with proxy when you provide a start method, that method overrides all the start methods on the class

hiredman22:01:00

so Vertx was calling it with 1 arg and it was throwing an error because the start on the proxy can only take 0 args

hiredman22:01:44

but that was happening on another thread and being communicated back to the main thread via the promise like thing that deploy returns, which I doubt you were looking at very hard when proxy didn't work

hiredman22:01:08

so you need something like (start ([] ...) ([p] (proxy-super this start p)) , but I forget the exact usage details of proxy-super, and something to keep in mind is proxy-super is not threadsafe, all of which is why I suggest (and I bet why the nascent clojure library there) biting the bullet and using the interface instead

hiredman22:01:04

it is just (proxy-super start p)

hiredman22:01:07

but that might not call your start override correctly

hiredman23:01:14

% clj -Sdeps '{:deps {io.vertx/vertx-core {:mvn/version "4.5.1"}}}'
Clojure 1.11.1
user=> (def vertx (io.vertx.core.Vertx/vertx))
#'user/vertx
user=> 
(deftype V [^:volatile-mutable vertx
            ^:volatile-mutable context
            start
            stop]
  io.vertx.core.Verticle
  (getVertx [_] vertx)
  (init [_ v c]
    (set! vertx v)
    (set! context c))
  (start [_ p]
    (start vertx context p))
  (stop [_ p]
    (stop vertx context p)))
user.V
user=> 
(.deployVerticle vertx
                 (->V
                  nil
                  nil
                  (fn [vertx context p]
                    (println "start")
                    (.complete p))
                  (fn [vertx context p]
                    (println "stop")
                    (.complete p))))
start
#object[io.vertx.core.impl.future.Mapping 0x6ab4ba9f "Future{unresolved}"]
user=> (.close vertx)
stop
#object[io.vertx.core.impl.future.PromiseImpl 0x30e6a763 "Future{unresolved}"]
user=> 

Takis_23:01:38

thank you for helping me, this with the 2 start methods, with 1 arg it worked, but still i cant make the java code to work

Takis_23:01:22

AbstractVerticle i want to extend, just to follow the java code , while reading the book, deftype i never used it in past

Takis_23:01:46

i think i just need to find books that explain those java things from clojure very good, because they are complicated

Takis_23:01:10

i am still trying to make it work

hiredman23:01:31

Dealing with abstract classes is going to be a real uphill battle

Takis_23:01:17

package ch2;

import io.vertx.core.AbstractVerticle;
import io.vertx.core.Vertx;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HelloVerticle extends AbstractVerticle {
    private final Logger logger = LoggerFactory.getLogger(HelloVerticle.class);
    private long counter = 1;

    @Override
    public void start() {
        Vertx vertx= super.getVertx();
        System.out.println(this.toString());
        vertx.setPeriodic(5000, id -> {("tick");});
        vertx.createHttpServer()
                .requestHandler(req ->
                {
                  ("Request #{} from {}",
                              counter++,
                               req.remoteAddress().host());
                 req.response().end("Hello!");
                })
                .listen(8080);

        ("Open ");
    }

    public static void main(String[] args) {
       Vertx vertx = Vertx.vertx();
       vertx.deployVerticle(new HelloVerticle());
    }
}

Takis_23:01:30

this is all the code, that i want to write in clojure

Takis_23:01:29

its from book, learning vert.x , when reading a book , it helps to just write the same code in clojure, because i dont know vert.x yet, to think of alternative ways

hiredman23:01:30

none of that depends on anything in AbstractVerticle

hiredman23:01:34

I think, in order to use the abstract base class correctly you'll need to use gen-class and aot compile, and then maybe use :exposes to avoid the two start methods having the same name, but not sure

hiredman23:01:55

or you can just not use the base class and do all that stuff right now in a live repl

Takis_23:01:28

thank you alot for helping me, i think for now i will use the java classes from java, and when i find a good tutorial on those i will retry, and yes i will start with gen-class that is the safest option, i tried many times, with gen-class

Takis_23:01:01

it worked now with the proxy, with 1 arg : ) thats important, progress, you helped me, something with those 2 start methods makes things complicated i guess, sometime i will see the gen-class and :exposes, thank you