Fork me on GitHub
#clojure
<
2018-04-01
>
qqq00:04:50

is there a swap! that returns both the old and new values ?

pauld00:04:04

I don't know of one, but semantically wouldn't this just be like a history of values you might keep in a 2-vector?

pauld00:04:59

or the atom could be of the form [old new]

pauld00:04:08

or you might want to use 2 refs in a transaction

pauld00:04:12

or if this is for debugging purposes, and you don't mind breaking the rule of side effects in 'f', put a println statement in there.

seancorfield01:04:32

@qqq There is in the latest Clojure, yes.

qqq01:04:02

@pauld: is

(defn xswap! [atm f & args]
  (swap! atm (fn [[o n]]
               [n (apply f n args)])))

(defn xreset! [atm v]
  (swap! atm (fn [[o n]]
               [n v])))

what you had in mind?

qqq01:04:33

@seancorfield swap/reset-vals! is even better, thahnks!

seancorfield01:04:11

(the most interesting new fn in 1.9 is halt-when but it's also really hard to use 🙂 )

sophiago02:04:07

This question is rather poorly fleshed out (even for me), but it's pretty rare I use deftype and definterface because tbh I find them rather clunky. I'd like to define a type for a data structure I'm essentially using as intermediate form, data.avl/sorted-map-by with a custom comparator I wrote, as well as somehow enforcing the types of at least the keys: Zach Tellman's version of vector from the deprecated clj-tuple, which should all be of equal length (also ideally that all elements in the keys as well as the values are of the abstract class Number, although that's less important). I'm not primarily thinking of using Spec for this because the primary purpose I'm currently imagining (here's the really poorly fleshed out part) is the ability to write a constructor that builds them up lazily like difference lists so I can chain together many functions on them and only realize the entire value at the end, similar to threading a collection through bunch of functions with into at the end. I'd also like to be able to define a print-method for the type, but that's secondary at this point. Any thoughts on how to go about this?

sophiago02:04:02

I'm obviously concerned about performance here, so a lot of my thinking is that most of the functions on this type run much faster with a particular ordering, hence why I'm using sorted-map-by, but ordering itself can obviously be expensive as is reduction of duplicate keys: something pretty much all the functions do first. I'm guessing if I can figure out how to delay these operations until the end of a series of functions then I can eliminate many computations that were duplicated inside each function, in addition to eliminating all the intermediary removal/insertion/reduction/sorting and instead doing it once at the end while retaining the benefits of this IR form. Not sure if that adds some color.

qqq06:04:28

Is there any IDE which will let me develop as follows: 1. write

(defn foo [x y z]
  (debug-launch-ide!))
2. pass the function foo around 3. C-x C-e some other code 4. when function foo is invoked, it pops me into an IDE, shows me the value of x, y, z 5. I write the body of foo, hit play 6. execution continues

seancorfield06:04:28

Nope, haven't seen anything like that.

qqq06:04:57

@seancorfield: is this debug-launch-ide! another thing I'm obsessed with but no one else cares to solve? 🙂

seancorfield06:04:07

Probably 🙂

cfleming06:04:31

That could be achieved in Cursive using the debugger, but it would be clunky without me adding support for it.

andy.fingerhut06:04:39

There is no "launch IDE" part in what I am about to say, but I think Stuart Halloway's "REPL-driven development" has some tips on firing up a REPL when an exception is raised, and mentions something about showing locals, but this is fuzzy in my memory, so may not be close enough to what you want to be useful.

cfleming06:04:55

It’s very smalltalk-like, that workflow.

andy.fingerhut06:04:03

Search for "exception" in the transcript. The next slide after that one talks about some code for examining locals, I believe.

andy.fingerhut06:04:12

Nothing there says anything about writing a function in the REPL and replacing it, while it is in the middle of being called.

qqq06:04:18

@andy.fingerhut : 1. Thanks for the link, will look into it. 2. The current best I have is (println ...) (assert false) ==> look at args in repl, write code in emacs, rerun 3. But this has the problem that the data is 'dead', and all I have is the println form of it. 4. In theory, I think this "rewrite function in the middle of calling it" is do-able via two steps: alter-var-root! for changing all future calls calling it once for the current call so in theory, it seems possible

danielo51508:04:17

Hello folks, I'm trying to implement a recursive async function that loops over until certain value is returned from an API

danielo51508:04:30

not sure about the best way of managing the sate

danielo51508:04:14

I think this may work, but I am unsure about function boundaries:

(defn waitForUpgrade [service] 
 (let [self (:self (:links service))
       name (:name service)]
  (go-loop
   (<! (timeout 1000))
   (if (= (:state service) "active") 
    (prn (str "Service " name " upgraded"))
    (recur (<!(Get self)))))))

danielo51508:04:01

Ok, I think I'm almost there

danielo51508:04:11

Here it is the new version

danielo51508:04:23

(defn waitForUpgrade [service] 
 (let [self (:self (:links service))
       name (:name service)]
  (go-loop [_service service]
   (<! (timeout 1000))
   (if (= (:state _service) "active") 
    (prn "Service " name " upgrade finished")
    (do (prn "Service not yet ready, waiting again" (:state _service))
        (recur (<!(Get self)))))
   _service)))

danielo51508:04:07

I need to pass a slighlty more complex stuff to recur

danielo51508:04:30

But this is not working

danielo51509:04:54

Ok, I have a correct final version

danielo51510:04:26

Which is much simpler IMO

danielo51510:04:43

(defn go-wait-for-upgrade [service] 
 (let [self (:self (:links service))
       name (:name service)]
  (go-loop [_service (<!(Get self))]
    (<! (timeout 1000))
    (if (= (.-state _service) "active") 
        (do (prn "Service " name " upgrade finished") 
            (js->clj _service))
        (do (prn "Service not yet ready, waiting again" (.-state _service))
            (recur (<!(Get self))))))))

danielo51510:04:47

Works perfectly

danielo51510:04:03

One question, how can I accum a value inside a ->> pipeline ? I need a value that I compute later on the pipeline and I need both the computed value and the original value

danielo51510:04:03

| do something         <- I need this value
| do something-else <- I need this value
| do the-final-stuff   <- Iwant to use both values

pauld10:04:46

Sounds like a job for reduce.

pauld10:04:34

or wrap the functions #() such that they return process a vector?

danielo51511:04:05

I ended using two helper functions and a tuple

danielo51511:04:57

The first step now returns a tuple, then I apply something to the first element of the tuple and then apply that tuple on the final function

danielo51511:04:07

I call it tuple, but it is a vector

danielo51511:04:13

not sure if the correct construction

danielo51511:04:33

This is my helper function:

(defn retuple-first [processor tuple] 
 [(processor (first tuple)) (last tuple)])

danielo51511:04:54

Then the pipe is like this:

(defn upgradeImage [imageName service]
 (go (->> service
        finishUpgrade
        (<!)
        (upgradePayload imageName {:pene "POLLĂ“N"}) ; <- returns a tuple
        (retuple-first (partial action :upgrade)) ; <- process first tuple element
        (apply Post) <- apply the positional arguments to post
        (<!))))

danielo51511:04:47

However this seems a bit fragile

pauld11:04:01

You could also break down the pipeline inside a let statement. The threading operator is supposed to make a pipeline of nested functions look simpler, if it starts to break down, I would reach for more traditional methods.

danielo51511:04:42

Maybe I'm too seduced by the pipelineoperator

danielo51511:04:03

What do you mean by breaking it inside a let statement ? To have two pipelines inside each let statement ?

pauld11:04:11

Like breakdown the pipeline into 2 or more pipelines and give the results meaningful names inside a single let just inside the toplevel go operator.

danielo51511:04:12

Ah, that looks fine!

danielo51511:04:16

I'll check it out

zentrope22:04:18

Is it possible, with clj/clojure, to combine aliases such that one of them has deps, and the other has a main? The command (`clojure -A:cljs:client`) drops my into a repl.

dominicm22:04:59

What if you reverse the order?

zentrope22:04:23

I think it basically works. I had one of the aliases at the top level, instead of inside the :aliases map.

zentrope22:04:29

Indentation error. ;)

zentrope22:04:57

Order doesn’t matter (in this particular case).

dominicm22:04:23

It is supposed to work, even if there's multiple main-opts, the last will be chosen @U06246PUK

zentrope22:04:41

Yes, just tested that. Confirmed.

zentrope22:04:25

@dominicm Using juxt/pack, I have an :uberjar alias, and a :server alias with lots od deps (not in the main :deps), and then I “-a :server:uberjar”, those extra-deps in server aren’t picked up or merged. Intentional?

dominicm05:04:54

You figured it out, I read deps.edn. The first reason is that it means I can add dependencies. The second is that I want more semantic information (for future reasons)

zentrope23:04:34

Adding a -Stree prints the deps I want. Hm.

zentrope23:04:45

Hm. Looks like juxt/pack doesn’t pick up from java.class.path, so I guess it won’t work for this particular scenario.

qqq23:04:30

Is there a standard package that provides ClojureUtils.COR_NAMESPACE ? I can't fid it on Google.

qqq23:04:25

The context is:

RT.var(ClojureUtils.CORE_NAMESPACE, REQUIRE_FUNCTION).invoke(INITIALISE_NS_SYMBOL