Fork me on GitHub
#clojure
<
2017-02-27
>
javahippie06:02:32

I have a problem with Java Interfaces and reify, did anyone of you ever reify a method from a Java Interface with return type void?

javahippie06:02:23

For Java/Clojure Interop I need the method to run some side effects, but I am always getting a error

rauh06:02:06

Hvae you tried ^void?

javahippie06:02:41

My call looks like this right now. I added void after someone suggested it at http://stackoverflow.com

rauh06:02:58

Have you tried putting it before receive?

rauh06:02:04

No, inside the parens

javahippie06:02:41

Works like a charm 🙂 Thank you very much!

javahippie06:02:26

That’s a neat feature for next time, thank you

isaac07:02:54

is clojure has array-set?

istvan07:02:36

does Java has array-set? 🙂

istvan07:02:05

not sure what array-set is

edlich11:02:53

Does someone has a reference how to start / spawn a process, send him strings, read strings from him (and finally send him a quit?) in Clojure?!

qqq11:02:15

You probably want the Java Process API. Clojure probably just leverages JVM instead of having its own lib for this.

edlich11:02:29

Yea java.lang.Ruintime but

edlich11:02:43

clojure has sh. And I found this: https://github.com/Raynes/conch

edlich11:02:50

Should be the solution 🙂

qqq11:02:10

imho, the Java api is genreally very easy to work with

qqq11:02:12

and very bug free

qqq11:02:39

unless there's some particular feature you need from the clj lib (which is not clear in which case), it may be easier to just go with java docs, as they're bery well written and very well tested

edlich11:02:41

Thanks qqq. I will eval both.

qqq11:02:57

one lesson I learned a hard way is: unles the clj library is really really really popular (as in half the clj community uses it), the following will probably be true: 1) more sample code on interenet for java api 2) more stack overflow responses for java api 3) and in general, easier to just deal with the java api since clj interop is so nicely done

edlich11:02:14

hm. Thanks for the hint.

conormcd12:02:59

The other lesson I have learned in the same area is: If you're writing a shell script, write a shell script. Don't write shell scripts in any other languages. It's OK to shell out to a simple command but as soon as you find yourself building a pipeline you should extract that into a shell script and shell out to that instead.

conormcd12:02:59

IOW if you see things like |, &&, || or ; then you need to extract it out of Clojure or else you'll have a horrible time debugging it.

qqq12:02:10

unless you can do it with boot or elisp 🙂

qqq12:02:18

but yeah, if you see the above symbols, just write a shell script

conormcd12:02:19

I've seen that mistake made in PHP, Python, Ruby and – most recently – Clojure. It has never ended well. 🙂

qqq12:02:29

though I have to admit, I can't think of the last time I've had to write a shell script -- between elisp and boot, I rarely have to chain multiple shell cmds together

qqq12:02:56

I guess if I had to glue multiple external programs together, shell scripts wuld be the only way to go

edlich12:02:02

True. Might be better to write a bash script and then mangle the output in clojure for processing...

qqq12:02:18

@edlich: what is the actual problem you're trying to solve?

edlich12:02:19

Thanks a lot for the tons of hints here!

edlich12:02:55

I am in chess programming. My goal is to generate opening books.

edlich12:02:35

all opening books so far are taken from grandmaster games. As far as I know nowone has created yet an opening book with the strong engines like stockfish, komodo, etc.

gfredericks12:02:56

edlich: does an "opening book" from strong engines just mean a precomputation of the engine's evaluation for an opening position? to speed up actual gameplay?

gfredericks12:02:33

and nobody's done this before because they didn't trust strong engines to evaluate opening positions until recently?

edlich12:02:04

Perhaps Gurus like Jiri Dufy are cleaning the book with the computers.

edlich12:02:33

But I refuse to take a book generated from strong players with ELO 2400-2800 if the current engines have ELO 3300.

edlich12:02:06

And as far as I know nowone has tried this before.

gfredericks12:02:11

okay; so it's possible that these 3300 engines are still really bad at openings

gfredericks12:02:27

(especially if their designers haven't been focused on openings)

gfredericks12:02:16

but even if that's true you might be able to get quality results by doing sufficiently deep searches

gfredericks12:02:48

(I don't actually know anything about this, just speculating)

qqq12:02:52

where do you call can external program ?

edlich12:02:01

Hence I want to fork this engines with a fen position and get the calculation back for eval.

edlich12:02:23

I call it from hand, from the shell script or from clojure. Whatever is best.

edlich12:02:49

I dream of calling: stockfish8_64_bmi2.exe FEN and the script does this for all best 3 moves and 3-5 moves deep.

kauko12:02:55

I have a dev-settings.edn. Can I use functions in that file? For example, maybe I'd like to use a flag to connect to a different database. :database (database :dev)

kauko12:02:28

After a quick try I just get lojure.lang.Symbol cannot be cast to java.util.Map$Entry 🙂

pesterhazy12:02:33

there's an undocumented reader macro

pesterhazy12:02:35

(read-string "#=(println :boom)")
:boom
nil

gfredericks12:02:12

that's not edn though

pesterhazy12:02:16

@kauko, you could abuse that to do calculations when reading an EDN file

gfredericks12:02:34

so if it works then the filename dev-settings.edn is misleading, at least

pesterhazy12:02:36

@gfredericks yeah but you could use read-string to read the file

pesterhazy12:02:50

that's true 😉

mpenet12:02:56

prolly better off using something like juxt/aero

pesterhazy12:02:00

dev-settings.edn++

pesterhazy12:02:14

yeah I don't recommend it

pesterhazy12:02:46

there's literally dozens of configuration libraries out there like https://github.com/weavejester/environ

mpenet12:02:27

aero is quite nice I have to say (we used to use env)

mpenet12:02:38

but both are ok

kauko12:02:25

I'll have to look into those, thanks 🙂

pesterhazy12:02:32

ah wow aero looks great

pesterhazy12:02:45

you gotta watch out for those 4 letter libraries

kauko12:02:13

I knew about aero actually, but only now I really understand what it's for

istvan12:02:59

kauko i usually have 3 files dev preprod prod

pesterhazy12:02:46

😆 (aero is edn really, ok?)

sova-soars-the-sora18:02:58

Hi everyone, ah I love clojurians. Always get the help i need... and sometimes i can offer some 🙂

sova-soars-the-sora18:02:09

I'm trying to incorporate new information into an existing app state atom

sova-soars-the-sora18:02:32

(def nf-atom (atom { :entries [ { 
           :id 5
           :title "a-title-goes-here"
           :score 10}
         {:id 6
          :title "newer-item"
          :score 30}]}))

sova-soars-the-sora18:02:20

Say I have a map that says {:id 6, :score 85} as fresh data. How can I incorporate this new information into my existing atom? I think assoc-in would be the right choice, but I'm not certain how to "match on :id" and affect only the one...

moxaj18:02:11

@sova is there a reason you can't index :entries by :id? would make it a lot easier

sova-soars-the-sora18:02:01

@moxaj no such reason, other than I don't know how xD ...are you saying there's a way to index atom submaps on a :key?

jrychter18:02:28

sova: i'd suggest (atom {6 {:id 6 :title "newer-item}}) instead of the :entries array, unless there is a reason not to.

moxaj18:02:46

I mean, just use a map instead of a vector, like {5 {:id 5 ..} 6 {:id 6 ..}}

jrychter18:02:30

Then you could simply (swap! nf-atom update 6 merge new-data)

sova-soars-the-sora19:02:57

@moxaj @jrychter Ah I see. yes, my app state atom has gotta stay the way it is, i'm using it with om.next ... i'll have to figure out a way that plays nicely with the existing structure since there's already a lot depending on how the data is stored

sova-soars-the-sora19:02:06

@jrychter although merge works almost perfectly... I just want to overwrite the :id matching map with newer data... hrm

sova-soars-the-sora19:02:20

doing it my naive way it adds a new map to the vector, which is closer than i was.

sova-soars-the-sora19:02:21

I don't have very many things on the clientside though, so I think that I could just walk through (the vec of maps) and find the matching one, and update some attribs?

sova-soars-the-sora19:02:49

if only there were a smash in addition to merge xD

seancorfield19:02:22

If it helps @sova you can assoc on a vector, using the index as a key: (assoc [:a :b :c :d] 2 :x) => [:a :b :x :d]

seancorfield19:02:47

You’d need to know the index of each :id — and you’d have to be careful not to have code push items onto the front of that vector (since the index of an element could change).

sova-soars-the-sora19:02:48

@seancorfield Cool, that is potentially helpful. Although I'm still going to look for a way to do it that doesn't require me messing with indices...

shaunxcode19:02:46

and you are not ok with (swap! nf-atom update :entries #(for [item %] (if (= (:id item) id-to-update) new-item item))) ?

joshjones19:02:59

@sova, do you want to replace the data that matches the id, or merge it in?

nathanmarz19:02:00

@sova With Specter you can do it like this:

(defn entry-nav [id]
  (path :entries
        ALL
        (selected? :id #(= % id))))

(swap! inf-atom
  (fn [m]
    (transform (entry-nav (:id new-data))
      #(merge % new-data) m)))

joshjones19:02:02

this replaces:

(defn swap-fn
  [{v :entries :as nf} d]
  (loop [i 0]
    (when-let [m (get v i)]
      (if (= (:id m) (:id d))
        (assoc-in nf [:entries i] d)
        (recur (inc i))))))

(swap! nf-atom swap-fn {:id 6 :title "hey-o" :score 90})

nathanmarz19:02:31

Then you can re-use entry-nav for other transformations or for querying, such as:

(select-any (entry-nav 5) @inf-atom)
;; => {:id 5, :title "a-title-goes-here", :score 10}

sova-soars-the-sora20:02:55

@joshjones "do you want to replace the data that matches the id, or merge it in?" ... < I want to merge it in (keep original data & overwrite matching keys)

sova-soars-the-sora20:02:53

Specter looks amazing... thanks for pointing to that.

joshjones20:02:10

(swap! nf-atom swap-fn {:id 6 :title "hey-o" :new-key 42})
=>
{:entries [{:id 5, :title "a-title-goes-here", :score 10}
           {:id 6, :title "hey-o", :score 30, :new-key 42}]}
@sova

hans20:02:34

Are pull requests to tools.nrepl in GitHub okay or is JIRA the way to go?

joshjones20:02:07

@sova forgot one detail, hang on 😉

PB20:02:22

Unrelated to clojure question: It seems that people are starting to turn to me, more and more for teh answers to their problems. In many cases the answer is a well worded search engine search away. How do I encourage people to stop asking me these questions, politely?

PB20:02:47

@jr that doesn't come across as passive aggressive?

jr20:02:56

it does. encourage code reviews as an async way to improve code instead of blocking your peers to wait for an answer

jr20:02:46

often times there is a better way to do it that can be addressed later

joshjones20:02:12

@sova

(defn swap-fn
  [{v :entries :as nf} d]
  (loop [i 0]
    (if-let [m (get v i)]
      (if (= (:id m) (:id d))
        (update-in nf [:entries i] merge d)
        (recur (inc i)))
      nf)))
another user posted a solution using for earlier which did not work, but this working version is cleaner than the above imo:
(defn swap-fn
  [{v :entries :as nf} d]
  (assoc nf :entries
            (vec (for [entry v]
                   (if (= (:id entry) (:id d))
                     (merge entry d)
                     entry)))))

sova-soars-the-sora20:02:34

that werks perfectly

joshjones20:02:18

it’s not pretty really, but neither is the structure you are having (or choosing?) to use 😉

sova-soars-the-sora20:02:55

yes, I admit it's not the best it could be, but I've already built most of the pirate ship around it.

sova-soars-the-sora20:02:12

I wish there were an interactive primer on @atoms

sova-soars-the-sora20:02:25

where I could learn really well all the data manipulation funkshns

sova-soars-the-sora20:02:25

Either way, as long as it works, which it does 😃

tolitius21:02:05

@nathanmarz: curious, would this be a sub par solution to yours?

(defn f [xs {:keys [id] :as data}]
  (transform [:entries ALL #(= (:id %) id)]
             #(merge % data)
             xs))

=> (swap! nf-atom f {:id 6, :score 85})
{:entries [{:id 5, :title "a-title-goes-here", :score 10} {:id 6, :title "newer-item", :score 85}]}

nathanmarz21:02:16

I like doing things like entry-nav so that I can think about my transformations in terms of application concepts instead of lower-level data structure concepts

tolitius21:02:33

@nathanmarz: makes sense, you also have an :id concept baked into the entry-nav, would that be an example of an "application concept" in this context?

tolitius21:02:59

cool, thanks

kgofhedgehogs22:02:21

Is there way to make copy of this structure, but filled with zeroes instead of original values?

[[[0.45 0.78]
  [-0.12 0.13]]
 [[1.5] [-2.3]]]

zylox22:02:36

postwalk would probably get you there

zylox22:02:38

probably overkill

tolitius22:02:39

@kgofhedgehogs (with specter):

=> xs
[[[0.45 0.78] [-0.12 0.13]] [[1.5] [-2.3]]]

=> (setval [(walker number?)] 0 xs)
[[[0 0] [0 0]] [[0] [0]]]

dominicm23:02:52

I need to figure out Mr. Anderson in boot so I can use things like Specter in libraries.

qqq23:02:37

let kw be a keyword; is there ever a situation where (get obj kw) and (kw obj) return different values?

bfabry23:02:28

I don't think so, given the preconditions you stated. the behaviour if kw is nil is different though

qqq23:02:36

but nil is not a keyword

qqq23:02:39

so kw != nil

bfabry23:02:02

yeah exactly what I meant by preconditions 🙂

qqq23:02:31

cool, I was reading some other code, and it had (get (...) :literal-keyword)

qqq23:02:50

and I couldn't figure out why they did not just write (:literal-keyword (...))

bfabry23:02:06

maybe it originally had a not-found value and it got removed

weavejester23:02:42

(:foo {} :bar) => :bar

qqq23:02:13

I have never seen that

bfabry23:02:18

oh I didn't know kw's took not-found values. so maybe the code was originally written but someone uninformed like me 😆

qqq23:02:45

I'm not convinced many people outside of #{'weavejester} knows about that feature.

weavejester23:02:03

AFAIK the keyword function syntax isn’t any different to get 🙂

weavejester23:02:33

Also: ({} :foo :bar) => :bar

qqq23:02:18

@weavejester: your handle looked familiar, so I looked you up on github, and saw you listed as "freelance clojure dev" -- could you DM me your conditions for freelance work? [hourly wage, min project size, etc ... ]