#clojure log - Jun 13 2015

The Joy of Clojure
Main Clojure site
Google Group
IRC
List of all logged dates

0:19 yedi: anyone have experience with https://github.com/kibu-australia/pushy

3:33 anti-freeze: Morning everyone. Does anyone know how to set up a separate mongodb environment for a compojure app during testing? The tests are littering my database.

3:37 Its cool, I found something on SO

3:38 http://stackoverflow.com/questions/16297871/clojure-database-settings-per-environment if anyone was wondering

3:49 wagjo: hmm https://github.com/google/clojure-turtle

3:54 TEttinger: google has a github?

3:55 quick somebody submit a PR to the empty repo!

3:59 p_l: I don't think they have empty repos on github ;D

4:00 TEttinger: p_l: https://github.com/google/clojure-turtle

4:00 oh!

4:00 p_l: and it's not empty

4:01 TEttinger: it was when I last looked at it!

4:01 now I see it is not

5:28 paulswilliamsesq: d

5:49 Confusion: Wondering how to achieve the following: starting from a macro (defmacro solve [queries] `(l/run* (~'a) ~@queries)), where l is core.logic and and example of queries is [(l/== a 3)], I want to create a macro where the queries can use more logic variables than just 'a'. I have code that determines which free variables are used in the queries and replaces them by gensym symbols. Now I need to expand the macro to take a list of vars and replac

5:49 e the [~'a] by a list of literal symbols. This should be possible, right?

6:16 TEttinger: Confusion: would the literal list of symbols be an argument, or derived from queries?

6:18 Confusion: I have the symbols available separately

6:19 So I can just pass them as an additional argument

6:22 Something like (defmacro solve [vars queries] (let [quoted_vars (map #(quote %) vars)] `(l/run* ~quoted_vars ~@queries))), doesn't work, because the vars are then sanitized (e.g. p1__17226#)

6:24 TEttinger: hm. wouldn't (map #(quote %) vars) be... unnecessary? I dunno, but it's quoted by the fact that it's an argument to a macro, right?

6:24 also, (map quote vars)

6:24 same thing

6:25 justin_smith: also, a nitpick, those aren't vars

6:25 they are bindings

6:25 TEttinger: justin_smith! the hero of the story

6:25 justin_smith: haha

6:26 Confusion: well, I mean 'logic variables' by that, I do not mean clojure Vars :)

6:28 TEttinger, yeah, that expression evolved from something else while trying to replicate the effect of [~'a]

6:28 so indeed (map quote vars) would be the same

6:33 Oh jeez, it's as simple as (defmacro foo [vars queries] `(l/run* ~vars ~@queries))

6:34 justin_smith: oh I am sure you could make it more complicated if you wanted to

6:36 Confusion: Well, I just tried that for a while and it didn't work :P

6:38 TEttinger: `g core.logic aoi

6:38 $google core.logic api

6:38 lazybot: [CoreLogic | Data] http://www.corelogic.com/about-us/data.aspx

6:38 TEttinger: hm

6:38 $google core.logic clojure api

6:38 lazybot: [clojure.core.logic - Clojure Library Overview] http://clojure.github.io/core.logic/

6:39 TEttinger: look at the implementation of run* , Confusion: https://github.com/clojure/core.logic/blob/f3f2b4c6c4a906c1fa512720aa09cb1abe312cd1/src/main/clojure/clojure/core/logic.clj#L1245

6:40 it's very similar!

6:45 Confusion: TEttinger, yeah, indeed, what we ended up with here is just a pointless wrapper around run*.

7:00 ionthas_: Is there any way to write down a more idiomatic way of this function? (mapv + (mapv * gt1 (mapv #(- 1 %) mask)) (mapv * gt2 mask)).

7:01 I have a lot of mapv in there and I wonder if I can shorten the function.

7:03 TEttinger: hm

7:04 ionthas_: (def gt1 [1 2 3 4])

7:04 (def gt2 [4 3 2 1])

7:04 (def mask [1 1 0 0])

7:05 the result is [4 3 3 4]. What I'm doing is merging the two vectors (gt1, gt2) according to the mask.

7:07 TEttinger: ,(mapv (fn [a b mask] (if (zero? mask) a b)) [1 2 3 4] [4 3 2 1] [1 1 0 0]) ; (mapv + (mapv * gt1 (mapv #(- 1 %) mask)) (mapv * gt2 mask))

7:07 clojurebot: [4 3 3 4]

7:07 justin_smith: ,(select-keys [1 2 3] [0 1])

7:07 clojurebot: {0 1, 1 2}

7:07 TEttinger: ,(mapv (fn [a b mask] (if (zero? mask) a b)) [1 2 3 4] [4 3 2 1] [1 1 0 0])

7:07 clojurebot: [4 3 3 4]

7:08 TEttinger: what's that, justin_smith?

7:08 justin_smith: TEttinger: selecting indexes of a vector

7:08 ,(select-keys [:a :b :c :d] [1 3])

7:08 clojurebot: {1 :b, 3 :d}

7:10 justin_smith: next trick is to go from that form back to a vector, of course

7:10 TEttinger: ,(mapv (fn [mask & choices] (nth choices mask)) [1 1 0 0 2 2] [1 2 3 4 5 6] [6 5 4 3 2 1] [9 9 9 9 9 9])

7:10 clojurebot: [6 5 3 4 9 ...]

7:11 TEttinger: so this handles choice from multiple collections

7:12 ionthas_, this look good?

7:13 that many mapv-using code looked like you'd been staring at the problem for a while

7:14 ionthas_: Yes TEttinger thanks I will try this implementations

7:14 Yes, I've been trying to optimize that part of code (it's for a genetic algorithm)

7:15 TEttinger: ah, nth is going to not perform super well in the last case

7:15 easy fix

7:15 ,(mapv (fn [mask choices] (nth choices mask)) [1 1 0 0 2 2] [[1 2 3 4 5 6] [6 5 4 3 2 1] [9 9 9 9 9 9]])

7:15 clojurebot: [2 5 9]

7:15 TEttinger: hm

7:16 ohhhh

7:16 justin_smith: yeah, you need a matrix flip for that one to work

7:16 ionthas_: mmm.... not quite what was planned.

7:18 justin_smith: ,(mapv (fn [mask choices] (get choices mask)) [1 1 0 0 2 2] (map vector [1 2 3 4 5 6] [6 5 4 3 2 1] [9 9 9 9 9 9]))

7:18 clojurebot: [6 5 3 4 9 ...]

7:18 TEttinger: I'm thinking of how to optimize this

7:18 justin_smith: TEttinger: though nth where n is 2 at greatest may be cheaper than building that many vectors

7:20 ionthas_: There will be always 2 vectors to merge. (The two parents, the vector produced is the "child")

7:21 so the mask can be [1 1 0 0] no need for more indexes.

7:21 tahmid: ure

7:22 That was a mistake

7:22 justin_smith: in that case yeah, just use nth

7:23 TEttinger: ,(mapv (fn [mask & choices] (nth choices mask)) [1 1 0 0] [3 4 5 6] [6 5 4 3])

7:23 clojurebot: [6 5 5 6]

7:27 ionthas_: Thanks TEttinger. I will do benchmarks with criterium.

7:27 right now my function looks like this. http://pastebin.com/U41ye9Ur

7:28 The version I posted here was the abreviated one. I the lets improve readability. Maybe is because I'm new. It's a bad practice?

7:29 *I think*

7:29 TEttinger: ,(mapv [1 1 0 0] (mapv vector [3 4 5 6] [6 5 4 3]))

7:29 clojurebot: #error {\n :cause "Key must be integer"\n :via\n [{:type java.lang.IllegalArgumentException\n :message "Key must be integer"\n :at [clojure.lang.APersistentVector invoke "APersistentVector.java" 284]}]\n :trace\n [[clojure.lang.APersistentVector invoke "APersistentVector.java" 284]\n [clojure.core$mapv$fn__6723 invoke "core.clj" 6612]\n [clojure.lang.PersistentVector reduce "PersistentVector...

7:29 TEttinger: gah

7:29 justin_smith: ionthas_: let is fine, but multiplication followed by addition is a less than straightforward way to do selection

7:30 so the version with nth is at least easier to read

7:30 probably performs better too

7:30 ionthas_: ok :)

7:32 thanks justin_smit and TEttinger for the help

7:32 TEttinger: no prob!

7:32 it's fun

7:32 ionthas_: hahahah it is.

7:32 TEttinger: you explained the problem nice and clearly

8:06 TimMc: &(format "lib-%04d" (rand-int 1e4))

8:06 lazybot: ⇒ "lib-1666"

9:23 hyPiRion: TimMc: I saw this before I came on IRC: http://hypirion.com/imgs/lib-1666.png

9:23 TimMc: hah

9:38 fraguk: Any purpose FREE storagewith PHP5 + MySQL, Script Testing, Personal, and more! at https://www.criosphinx.net/free/

9:38 Any purpose FREE storagewith PHP5 + MySQL, Script Testing, Personal, and more! at https://www.criosphinx.net/free/

9:38 Any purpose FREE storagewith PHP5 + MySQL, Script Testing, Personal, and more! at https://www.criosphinx.net/free/

9:39 wasamasa: #ops

9:42 gfredericks: (inc TimMc)

9:42 lazybot: ⇒ 99

10:35 vamsi: i am using sublimerepl with windows,the repl evaluates (nil? nil) to false.

10:36 but the repl on cmd evaluatesthis to true,which one is correct??

10:36 lazybot: vamsi: Uh, no. Why would you even ask?

10:37 vamsi: reading this now and trying the samples out http://www.braveclojure.com/do-things/

10:53 justin_smith: ,(nil? nil)

10:53 clojurebot: true

10:53 justin_smith: sounds like sublimerepl is broken

10:57 fraguk: Any purpose FREE! Create your own clan website & more wih free storage with PHP5 + MySQL, Script Testing, Personal, and more! at https://www.criosphinx.net/free/

10:57 Any purpose FREE! Create your own clan website & more wih free storage with PHP5 + MySQL, Script Testing, Personal, and more! at https://www.criosphinx.net/free/

11:00 justin_smith: amalloy_: you around?

11:58 donbonifacio: I want to put some data on a vector, and the periodically (every sec?) do something on the data and clear the vector. Is there something I can use specific for this?

12:02 justin_smith: donbonifacio: probably an agent, atom, or ref

12:03 though doing something with the data and then clearing it sounds a lot like a queue rather than vector

12:04 donbonifacio: what about clearing? how/when could I do that? any suggestions?

12:04 justin_smith: donbonifacio: that's why I mentioned an agent, atom, or ref. These are mutable containers (though technically you cannot ever clear a vector, they are immutable, but you can replace it with an empty one)

12:05 so the agent can go from holding a vector with contents to holding an empty vector, even though the vectors cannot change

12:06 ,(def a (agent []))

12:06 clojurebot: #'sandbox/a

12:07 justin_smith: ,(send a conj 1)

12:07 clojurebot: #object[clojure.lang.Agent 0x736f370f {:status :ready, :val []}]

12:07 justin_smith: ,@a

12:07 clojurebot: []

12:07 donbonifacio: why didn0t it had [1] ?

12:08 justin_smith: that's what I am wondering

12:08 donbonifacio: hehe :)

12:08 justin_smith: answer: clojurebot is weird

12:08 I think it's because agents use threads, and clojurebot restricts threads

12:08 the send / conj works in a real repl

12:08 donbonifacio: how about then getting the data from the agent?

12:08 justin_smith: @a

12:08 just as above

12:09 donbonifacio: no, I mean, periodically

12:09 justin_smith: periodically @a

12:09 probably something like (fn [state] (do-something state) [])

12:09 which is clearing it

12:09 and also using the contents

12:10 we've got a few options for periodic execution - the easiest thing is a while or loop in a future

12:11 donbonifacio: ok, that loop could deref the agent, operate on the data and clear the agent. Is that it?

12:11 justin_smith: sounds about right, yeah

12:11 donbonifacio: better to use a function as above - it will get the state of the agent and operate on it in one guaranteed uninterrupted action

12:12 separately using @ and clearing is a race condition

12:12 donbonifacio: yes, I'm seing that the update can return the new state

12:12 justin_smith: it could be modified in between the read and right (though you can use eg. transactions)

12:12 right

12:12 donbonifacio: thanks for making things clear for me justin_smith .)

12:12 justin_smith: np, best of luck

12:13 sojacques: Hi everyone, I'm running into an issue with Java interoperability. I have some code working in the repl, but failing and returning me "No matching method" errors when I test-run my project using "lein ring server-headless"

12:13 justin_smith: donbonifacio: also, people often use atoms for this stuff, but I assumed you were talking about a side effecting operation where retries would be bad (which is why I suggested an agent, they do not retry)

12:13 sojacques: Tried googling, couldn't really find much helping me to see what goes differently in the repl

12:14 justin_smith: sojacques: no matching method for what method on what object with what args?

12:14 sojacques: justin_smith: here is a gist: https://gist.github.com/klodio/2e07252a9a9d4a1d683f

12:15 creese: Can you use core.typed to determine behavior at run time?

12:15 justin_smith: sojacques: which of those method calls is getting the error?

12:15 sojacques: justin_smith: No matching method found: push for class com.notnoop.apns.internal.ApnsServiceImpl

12:16 justin_smith: creese: we have multiple tools for dispatching on type, but core.typed is for proving correctness at compile time

12:16 sojacques: justin_smith: my project.clj refers to https://github.com/notnoop/java-apns using : [com.notnoop.apns/apns "0.2.3"]

12:17 justin_smith: sojacques: looks like the wrong argument count https://github.com/notnoop/java-apns/blob/master/src/main/java/com/notnoop/apns/internal/ApnsServiceImpl.java#L45

12:17 looks like it takes exactly one arg

12:18 sojacques: creese: not sure if it's exactly what you're looking for, but I'm using schema for runtime things

12:18 justin_smith: I found this after checking the code, but then what I fail to understand is why it works in the repl (and does what's intended)

12:19 justin_smith: oh, of course, the method has overloads

12:19 http://www.atetric.com/atetric/javadoc/org.apache.servicemix.bundles/org.apache.servicemix.bundles.java-apns/0.1.6_3/com/notnoop/apns/internal/AbstractApnsService.html#push(byte[],%20byte[])

12:20 what are the types of dtoken and payload?

12:21 creese: I have a macro that returns a handler. I want to associate a "type" with the handler so I can pass it as argument to another function to determine run time behavior.

12:21 justin_smith: creese: sounds like you want a multimethod or a protocol

12:22 with a protocol you would want to use something like deftype or defrecord and implement the protocol for each of these

12:22 with a multimethod, you can define any dispatch function you like for method selection

12:23 and then implement variations depending on the dispatch value

12:23 sojacques: dtoken is a string, and payload, well, I define it in the gist using the build method of APNS/newPayload (so it should be PayloadBuilder?)

12:23 justin_smith: sojacques: looking at the defined methods, it seems like the payload should usually be a string or byte[]

12:24 sojacques: right

12:24 creese: Here is a snippet: https://gist.github.com/creese/82e095a0c9ea8a553c44

12:25 justin_smith: sojacques: you could use the type function to verify the type of payload at runtime

12:25 ,(type {})

12:25 clojurebot: clojure.lang.PersistentArrayMap

12:25 sojacques: I'm going to check this now

12:25 justin_smith: creese: as I mentioned last night, start and stop must always return a component

12:25 sojacques: it might help me to figure out why -> (send-push-notification "somedevicetoken" "somemessage") works in the repl

12:26 justin_smith: thanks for the help

12:26 creese: justin_smith: stop) is stubbed out

12:27 Right now, I using a schema like [:tag value]

12:27 justin_smith: creese: start needs to return a component

12:27 http://www.atetric.com/atetric/javadoc/org.apache.servicemix.bundles/org.apache.servicemix.bundles.java-apns/0.1.6_3/com/notnoop/apns/internal/AbstractApnsService.html#push(byte[],%20byte[])

12:27 err

12:27 creese: also, the component code shows exactly how protocols work - the component system calls start / stop on every component and you define what start and stop do

12:27 I mean your code using component, that is

12:28 creese: what you are doing with type* and handler is very close to how multimethods work

12:28 creese: justin_smith: not a map?

12:28 justin_smith: creese: it should almost always return "this", but idiomatically you would name it "component" instead of this

12:29 creese: because if you use other components, they will be passed in as keys on your this arg

12:30 creese: justin_smith: Here, type* is used to get the name of the exchange.

12:30 justin_smith: and it makes more sense to access (:resource component) rather than (:resource this)

12:30 clojurebot: It's greek to me.

12:31 creese: (assoc this :key value) everywhere?

12:32 justin_smith: creese: if you want to keep track of whether your component is started, or provide any resource to other components, yes

12:32 creese: and similarly, you should dissoc in the stop method

12:32 creese: yeah, I've seen that

12:32 justin_smith: which can prevent stale resources from being used

12:33 sojacques: justin_smith: the payload is a String

12:33 creese: what about the run time question?

12:33 justin_smith: sojacques: OK, then something's weird, because there is definitely a matching method there...

12:33 sojacques: therefore: https://github.com/notnoop/java-apns/blob/master/src/main/java/com/notnoop/apns/ApnsService.java#L66 -> I'm calling it with a String token, and a String payload

12:33 yeah :(

12:33 justin_smith: creese: like I said, use a multimethod or a protocol

12:33 sojacques: that also explains why it works in the repl

12:33 creese: in order to use a multimethod, I would need to have the type as a value in a map

12:33 justin_smith: creese: it can be a key

12:34 a multimethod can dispatch on any function

12:34 creese: it affects overall syntax though

12:34 sojacques: hm, I'll try to see if it's also a String when I run the app using "lein ring server-headless"

12:34 justin_smith: ,(defmulti foo even?)

12:34 clojurebot: #'sandbox/foo

12:34 justin_smith: ,(defmethod foo true [_] :OK)

12:34 clojurebot: #object[clojure.lang.MultiFn 0x103f140 "clojure.lang.MultiFn@103f140"]

12:35 justin_smith: ,(foo 2)

12:35 clojurebot: :OK

12:35 creese: if I define handler as {:tag foo :val func}

12:35 justin_smith: creese: or you can do (defmulti dispatch first)

12:35 creese: then to call func I have to write ((:val f) 1 2 3)

12:36 justin_smith: (defmulti dispatch first) matches your existing representation

12:36 not to say your representation is right, I have no idea

12:38 creese: What about metadata for the type?

12:38 justin_smith: creese: metadata is unreliable from what I have seen

12:38 you could make an actual type with defrecord, you have code in the gist you shared showing how it's done

12:40 creese: Can dispatch from a vector or does it have to be a map?

12:40 justin_smith: creese: like I said above, (defmulti wahtever first)

12:40 that will dispatch based on the first item in a vector

12:40 or list even

12:40 ,(defmulti what-to-do first)

12:40 clojurebot: #'sandbox/what-to-do

12:41 gdutra: Hello, I have defined a matrix: (def matrix (map (fn [x] (into [] (concat (subvec alphabet (.indexOf alphabet x)) (subvec alphabet 0 (.indexOf alphabet x))))) alphabet))

12:41 It should return a vector

12:41 justin_smith: ,(defmethod what-to-do :cat [says] (clojure.string/join " MEOW " says))

12:41 clojurebot: #object[clojure.lang.MultiFn 0x1b891974 "clojure.lang.MultiFn@1b891974"]

12:42 justin_smith: ,(what-to-do [:cat ["hello" "world"]])

12:42 clojurebot: ":cat MEOW [\"hello\" \"world\"]"

12:42 justin_smith: haha, oops!

12:42 gdutra: but when I will use it it says could not cast lazySeq to Ifn

12:42 creese: ok, will try it

12:42 justin_smith: ,(defmethod what-to-do :cat [[_ says]] (clojure.string/join " MEOW " says))

12:42 clojurebot: #object[clojure.lang.MultiFn 0x1b891974 "clojure.lang.MultiFn@1b891974"]

12:42 justin_smith: ,(what-to-do [:cat ["hello" "world"]])

12:42 clojurebot: "hello MEOW world"

12:43 justin_smith: gdutra: map returns a lazyseq

12:43 gdutra: perhaps you want mapv

12:43 gdutra: the "cannot cast lazyseq to ifn" message means you have too many parens somewhere

12:44 ,((range))

12:44 clojurebot: #error {\n :cause "clojure.lang.Iterate cannot be cast to clojure.lang.IFn"\n :via\n [{:type java.lang.ClassCastException\n :message "clojure.lang.Iterate cannot be cast to clojure.lang.IFn"\n :at [sandbox$eval153 invoke "NO_SOURCE_FILE" 0]}]\n :trace\n [[sandbox$eval153 invoke "NO_SOURCE_FILE" 0]\n [clojure.lang.Compiler eval "Compiler.java" 6792]\n [clojure.lang.Compiler eval "Compiler.jav...

12:44 justin_smith: like that

12:44 gdutra: hmmm

12:44 I'll try the mapv

12:44 creese: Can defmacro return a vector?

12:45 justin_smith: creese: defmacro will return a var

12:45 sojacques: justin_smith: I'm sorry I finally understood why it failed in the running server, I was feeding wrong arguments there

12:45 justin_smith: ,(type (defmacro blah [] []))

12:45 clojurebot: clojure.lang.Var

12:45 sojacques: the only time where I don't use core.typed I bite myself

12:45 justin_smith: sojacques: I figured it was something like that, glad you sorted it out

12:45 haha

12:46 sojacques: :) thanks for helping out!

12:46 justin_smith: ,(blah) ; but of course any macro can return a vector

12:46 clojurebot: []

13:45 tmtwd: ls

13:45 lazybot: bin boot dev etc home lib lost+found media opt sys tmp usr

13:48 tmtwd: I running a clojure library - it says to run ' lein repl', is there a way to run a plain lein repl in emacs or do I just use cider-jack-in?

13:48 justin_smith: tmtwd: C-u M-x inferior-lisp<return>lein repl<return>

13:49 but cider-jack-in shouldn't prevent most projects from working, if you already have cider set up

13:52 tmtwd: how do I change the working directory of emacs?

13:52 with cider?

13:52 justin_smith: tmtwd: if your cursor is in a file, cider-jack-in should open a repl in that file's directory

13:53 eg. you could open project.clj then jack in

13:53 tmtwd: okay

15:32 gdutra: How can I extract this map function to a external function?

15:32 (map (fn [k m] (nth (nth matrix (.indexOf (nth matrix 0) m)) (.indexOf (nth matrix 0) k))) cipher message))))

15:37 amalloy: gdutra: (defn whatever [matrix] (fn [k m] ...))

15:37 (map (whatever matrix) cipher message)

15:39 gdutra: ohh thanks

15:39 I was trying something with partial

15:40 amalloy: gdutra: that is a general formula you can follow to convert any closure to a top-level function, if you want

15:40 gdutra: and do (map whatever list1 list2)

15:40 amalloy: define a function that takes the things you want to close over, and returns the closure you were extracting

16:03 justin_smith: amalloy: the reason I was asking if you were around earlier is we got a repeat spammer

16:03 amalloy: i didn't get it. my bouncer only saves like 100 lines of scrollback when i'm amalloy_

16:03 justin_smith: ahh

16:04 amalloy: you can $mail me if i'm not around, of course

16:04 justin_smith: amalloy: it was fraguk, sadly I did not get his host or ip info

16:04 amalloy: yeah, hindsight

16:04 amalloy: c'est la vie

16:26 noncom|2: if i have to create objects to be used with java object methods that are operating on class objects, how do i better do that?

16:26 like: something.setParameter(ParameterOne.class p1)

16:27 justin_smith: ParameterOne.class in java is ParameterOne in clojure

16:27 ,(= String (class "hello"))

16:27 clojurebot: true

16:29 noncom|2: but how do i create a ParameterOne class in clojure?

16:29 (proxe [ISomeInterface] []) will be okay?

16:30 justin_smith: proxy creates an instance of an interface

16:30 noncom|2: uh

16:30 justin_smith: so yeah, if ParamterOne is an interface that will work

16:31 noncom|2: how can i create such interfaces in clojure, not java?

16:31 justin_smith: wait, create a thing implementing an interface, or the interface itself? for the latter there is defprotocol and definterface

16:33 noncom|2: create an interface and then objects implementing it. because i need that a function accepting a Class object as a parameter to distinguish my clojure-created objects correctly, as if they were creted in java

16:33 so

16:33 (definterface ISomeInterface) and then proxy of it would work?

16:33 justin_smith: yeah

16:34 noncom|2: cool!

16:34 justin_smith: another option you could consider is a defrecord, and you can provide the class of the defrecord as the class that method needs to register

16:35 but you would need to implement protocol or interface for the methods it should have...

16:37 arohner: using optimus (https://github.com/magnars/optimus), is it possible to include a URL in a bundle?

16:39 noncom|2: justin_smith: can i specify constructor params for a proxy implementing a definterface ?

16:40 justin_smith: noncom|2: you'll need a defrecord I think, proxies are anonymous singleton classes iirc

16:40 while a defrecord or deftyle has a proper constructor etc.

16:41 noncom|2: eh, but defrecors is immutable...

16:41 in that library there is a fast change of massive state present

16:41 justin_smith: so is proxy iirc

16:41 proxy doesn't even have fields

16:41 noncom|2: then there is no other way than using atoms or refs..

16:42 justin_smith: or deftype

16:42 or gen-class

16:42 noncom|2: in a proxy or defrecord

16:42 :)

16:42 justin_smith: with deftyle you can declare actual mutable fields, with gen-class you can fake them with an atom

16:43 s/deftyle/deftype

16:44 noncom|2: here they do not advice using deftypes mutability: https://clojuredocs.org/clojure.core/deftype

16:44 saying its very unreliable

16:45 well, looks like i have to create that part with java..

16:45 justin_smith: "mutable fields are extremely difficult to use

16:45 correctly, and are present only to facilitate the building of higher

16:45 level constructs"

16:45 noncom|2: the author of that would say the same thing about a mutable java field

16:46 it's not deftype they are calling unreliable, it is mutability

16:46 noncom|2: ok, so also, i have to explicitly qualify a field to be mutable by adding a long keyword to its metadata?

16:46 justin_smith: yes

16:47 noncom|2: better than nothing :)

17:56 nooga: hi, anyone using aleph/gloss? I'm looking for tips on how to construct frames with payload length that's not directly before the payload

20:04 justin_smith: ~gnaborretni |is| ⸘

20:04 clojurebot: Roger.

20:04 justin_smith: ~gnaborretni

20:04 clojurebot: gnaborretni is ⸘

22:18 WickedShell: Has anyone here used clj-serial?

22:18 TimMc: Probably!

22:19 WickedShell: I'm having a specific problem where it's throwing exceptions when I close it, as its not managing closing the listener succesfully at a lower level, which then locks out the COM port till the entire REPL/build is restarted

22:26 TimMc: Maybe you can patch it and send a PR. Does it have an open issue for that?

22:27 WickedShell: Nope, and I have no clue how to patch it yet... I think it's an error with the lower level java library but I really can't tell

22:31 TimMc: Ah, I see.

22:54 creese: Why does "lein run" start in the user namespace? Is there a way to specify this from the project.clj?

22:55 justin_smith: creese: clojure runs from the user namespace. You can specify a :main-ns for the repl to switch to, but I don't see the benefit to running from some other ns

22:55 for the run task specifically, that is

22:57 laggybit: having the REPL start in the user namespace is convenient if you keep debugging stuff in a repl.clj too

22:57 *user.clj rather

22:58 creese: I'm trying to do what leiningen does with "defproject" in a file, but when I eval the macro, it can't find it unless I switch to the namespace the macro is in

Logging service provided by n01se.net