Fork me on GitHub
#clojure
<
2020-07-12
>
noisesmith00:07:24

name + arg count

Takis_01:07:15

Hello,is there something wrong with this code?

Takis_01:07:30

(defn <- [e1 e2] {"lt" [e1 e2]}) (defn <_ [e1 e2] (<- e1 e2))

Takis_01:07:46

is something wrong with the names of the functions?

Takis_01:07:29

i run it , it works and when i re-run it i get a stack overflow,invoke static ,with that name of the function,maybe its something class related i use local repo with lein install i don't know,thank you

andy.fingerhut01:07:19

It may be that the <- is being internally munged into some other name where both of those characters are being turned into others that are legal in JVM class names, and the - is turned into _, so perhaps both <- and <_ turn into the same name in the underlying JVM classes.

andy.fingerhut01:07:19

But I do not get any stack overflow error when I try to call those functions in a REPL, so I am not able to reproduce the problem you are seeing.

andy.fingerhut01:07:44

Clojure or ClojureScript? Version? Do you have a reproducible test case using a minimal setup?

Takis_01:07:10

i will try that now , i use [org.clojure/clojure "1.10.1"] jdk 14

Takis_01:07:35

looks like the problem happens only when the one call the other, else they both work

Takis_01:07:33

i will retry tomorrow its so late here thank you for your help 🙂

andy.fingerhut01:07:35

Sure. It is easiest for someone to help if you can make a short test sequence that exhibits the problem, and they can try it on their system, and if you and they get different results, try to determine what the difference is in your setups that leads to the difference in behavior.

noisesmith01:07:39

yeah, I think avoiding any functions that would munge to one another (see clojure.core/munge) is best policy

ins)user=> (munge '<-)
_LT__
(cmd)user=> (munge '<_)
_LT__
*fixed

noisesmith01:07:22

I bet its the self calls which break due to munging of the self call when compiled

Takis_01:07:04

yes when one call another happens ,thank you i didn't know that i will check it tomorrow

namenu07:07:44

Is there a non-intrusive way to show some progress of my map function? I want to know how many items from my collection have been processed, like 123/1000, without changing my mapping function nor using map-indexed.

jsn09:07:17

You understand that map processes things one at a time and doesn't know the count (or even if the collection is finite), and that map produces a lazy sequence (so if the map's caller doesn't access any part of it, that part will not ever be processed at all), right?

namenu09:07:05

Yes I know. I think I need some verbosity for debugging/monitoring perspective.

namenu09:07:21

I was wondering if there is any library (maybe macros) for this kind of requirement.

jsn09:07:11

Not that I'm aware of; but my point is that it seems impossible to do without either modifying map's behavior or your function

jsn10:07:42

(defn map1-with-progress [f coll]
  (let [cnt (count coll)
        done (atom 0)
        progress-fn
        (fn [v]
          (swap! done inc)
          (println @done "/" cnt)
          v)]
    (map (comp progress-fn f) coll)))
(something like this comes to mind)

👍 3
namenu10:07:19

It reminds me a transducer

jsn10:07:32

yeah, a stateful transducer can probably be used

nick10:07:58

First time trying to run lein repl on Heroku. Pretty standard Luminus stack. It works fine locally:

lein repl
nREPL server started on port 42939 on host 127.0.0.1 - 
REPL-y 0.4.4, nREPL 0.8.0-alpha5
Clojure 1.10.1
OpenJDK 64-Bit Server VM 11.0.6+10-post-Debian-1deb10u1
    Docs: (doc function-name-here)
          (find-doc "part-of-name-here")
  Source: (source function-name-here)
 Javadoc: (javadoc java-object-or-class-here)
    Exit: Control+D or (exit) or (quit)
 Results: Stored in vars *1, *2, *3, an exception in *e

user=> 
But not on Heroku:
heroku run lein repl --app foo-app
 ›   Warning: heroku update available from 7.41.1 to 7.42.3.
Running lein repl on ⬢ foo-app... up, run.9192 (Hobby)
Downloading Leiningen to /app/.lein/self-installs/leiningen-2.9.1-standalone.jar now...
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   637  100   637    0     0   4615      0 --:--:-- --:--:-- --:--:--  4615
100 13.9M  100 13.9M    0     0  27.3M      0 --:--:-- --:--:-- --:--:-- 27.3M
Retrieving lein-shadow/lein-shadow/0.2.0/lein-shadow-0.2.0.pom from clojars
(truncated)
Retrieving ring/ring-mock/0.4.0/ring-mock-0.4.0.jar from clojars
nREPL server started on port 43521 on host 127.0.0.1 - 
nick@tower  app git:(master) 
It's like launching it in detached mod(still listed in heroku ps list of running dynos) and instantly exits it. Anything that you may suggest trying to fix it?

folcon13:07:14

Did you manage to get this working?

nick13:07:58

Hi folcon not yet :(

folcon13:07:57

Hmm, might have some time later tonight / tomorrow night if you want a hand debugging?

nick13:07:03

Thanks a lot! Actually I'm moving away my project from Heroku(for some other reason). So there's no need in this anymore

folcon14:07:56

Oh, no problem 😃...

emccue10:07:40

(import java.util.List)
=> java.util.List
(definterface A
  (a [^List a])
  (a [^Integer a]))
=> dev.mccue.class_system.A
(reify A
  (a [^List a])
  (a [^Integer a]))
Syntax error (ClassNotFoundException) compiling reify* at (C:\Users\Ethan\AppData\Local\Temp\form-init10044805717733694756.clj:1:1).
java.lang.List

emccue10:07:51

interesting error to say the least

emccue10:07:37

Where might it be getting java.lang.List from?

p-himik10:07:43

Another interesting thing:

user=> (definterface A
  (a [^java.util.List a])
  (a [^Integer a]))
user.A
user=> (reify A
  (a [^java.util.List a])
  (a [^Integer a]))
Syntax error (IllegalArgumentException) compiling reify* at (REPL:1:1).
Can't define method not in interfaces: a

emccue10:07:17

@rickmoynihan Maybe i am missing some context - but you can just use a normal map with a namespaced keyword

rickmoynihan06:07:32

Yes, this is what I’m doing, but with a record.

emccue10:07:33

{::instance library-stuff}

emccue10:07:38

and just have the practice that you don't dive into keys namespaced by your.company.subpackage.whatever outside of the module you have them in

emccue10:07:54

just like python's __field

emccue10:07:28

and it should be pretty easy to enforce because noone wants to write out the whole path of a namespace

emccue11:07:08

then just do the good ol' "namespace function as object methods" trick

emccue11:07:47

and bam, you've newtype'd the thing without needing an actual nominal type

emccue11:07:44

and you can use stuff like this to discourage leaks even more https://github.com/vlaaad/blanket

emccue11:07:15

you only need a deftype/reify for protocols that can't be extended by metadata

vlaaad11:07:16

oh, I made this

emccue11:07:42

and if you need deftype it is similar

emccue11:07:59

just have a inner field for wrapping the library data structure

vlaaad11:07:21

another alternative is react's approach: using a name like __SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED

emccue11:07:29

same deal that fields you just consider to be namespace only within your team

emccue11:07:21

which i will admit to doing twice yesterday

emccue11:07:24

(definterface ClassInstance
  (internalUseOnlyGetInstanceInfo []))

emccue11:07:41

(keyword (str *ns*)
           (str "internalOnlyMarkerThatTheClassCameFromMe-"
                (name (:name class))
                "😍"
                (class-identity class))))

emccue11:07:29

though i might not reasonably need the second one

lunik114:07:26

Is anybody aware of a clojure library that like priority map allows a map to be sorted by key, but will also alow an ordering on keys to be defined in the case that the two values in a map are the same?

andy.fingerhut15:07:49

So perhaps like a multiset is, versus a set, you are hoping to use a 'multi-priority-map'?

andy.fingerhut15:07:02

I haven't heard of one of those implemented already, that I can recall off hand.

andy.fingerhut15:07:58

Although I might not yet be entirely clear on what you are asking for. Have you tried out simple REPL examples with this library to see if it might do what you hope? https://github.com/clojure/data.priority-map

andy.fingerhut15:07:35

I believe in that library, the keys must all be unique in a single priority map, but more than one key can have the same value, like in a normal Clojure map.

andy.fingerhut15:07:42

The key/value pairs are sorted by value, not key.

andy.fingerhut15:07:22

I believe that if multiple key/value pairs have the same value, their relative order is arbitrary, i.e. you as a user of the library do not have a way to control the relative order of key/value pairs with the same value

lunik115:07:50

yeah that is the problem I have, although thinking about it more I do not need to add any keys at a later time

lunik115:07:59

so just a map with an explicit order would do

lunik115:07:20

I guess i could use array-map for that so long as they are small?

the2bears16:07:14

I wouldn't rely on an explicit order unless it's part of the map's contract. Implementations can change.

lunik116:07:30

https://clojure.org/reference/data_structures states that array maps will maintain key order

👍 3
andy.fingerhut16:07:58

If you call array-map to create a map explicitly, it will maintain order regardless of size. If you ever take such a value and conj or assoc a new key onto it, the return value might be a hash map with a different order.

andy.fingerhut16:07:11

But as long as you do not need updated versions that maintain order, array-map works.

andy.fingerhut16:07:23

Alex Miller has a patch for Clojure in one place that takes advantage of that fact.

andy.fingerhut16:07:55

They do not have to be small for that to work

andy.fingerhut16:07:32

People recommend/warn against it so often for good reason, though -- all it takes is one operation on that array-map, and the return value is not guaranteed to maintain the order.

lunik116:07:34

the keeping it small comment was more to do with performance as array maps have O(N) lookup as I understand it? looks like there is https://github.com/flatland/ordered too. thanks for the warnings on maintaining order!

andy.fingerhut17:07:04

Yes, they do have O(N) lookup

andy.fingerhut17:07:34

ordered has 'O(1)' lookup as well as guaranteeing it maintains insertion order.

👍 3
Bravi17:07:16

Hi everyone. I’m trying to figure out the logic to a little app I’m working on. The app is actually broader than this, but I’ve got a little chunk of the logic cut out from it, that I need to figure out how to do. So there’s this little functionality where users answer some questions and get points per question answered. And this is somewhat what points system looks like:

(def points-system [{:points 1 :threshold 5}
                    {:points 3 :threshold 10}
                    {:points 7}])
So first 5 correct answers will get 1 point to the user per answer. Then the next 10 answers will give 3 points per answer. And after that, it’s 7 points per answer. Now the functionality I’m working on is that from the database I get the number of questions answered correctly, i.e. 100. And I need to calculate points basically. At the moment I have the following, which works fine, but I was wondering if there is a way to avoid using atom
(def points-system [{:points 1 :threshold 5}
                    {:points 2 :threshold 10}
                    {:points 7}])


(defn calculate-points [total-answers]
  (let [state                      (atom {:total-answers total-answers
                                          :total-points  0})
        threshold-points-handler   (butlast points-system)
        consecutive-points-handler (last points-system)]
    (doseq [handler threshold-points-handler]
      (swap! state assoc
             :total-answers (- (:total-answers @state)
                               (:threshold handler))

             :total-points (+ (:total-points @state)
                              (* (:threshold handler) (:points handler)))))

    (while (> (:total-answers @state) 0)
      (swap! state assoc
             :total-points (+ (:total-points @state)
                              (:points consecutive-points-handler))
             :total-answers (dec (:total-answers @state))))
    (println @state)))


(defn -main [& args]
  (-> 100 calculate-points println))

Bravi17:07:34

maybe the first two bits, but the last bit I think is more of recur . but I would still need to retain some sort of state, isn’t that correct?

phronmophobic17:07:25

you could use either loop/recur or reduce

phronmophobic17:07:52

both allow you to iterate over a sequence and accumulate state

Bravi18:07:58

ok I got to this point and I think I’m quite happy with this

(defn apply-threshold-points
  [point-handlers state]
  (reduce (fn [acc {:keys [threshold points]}]
            (assoc state
                   :total-answers (- (:total-answers acc) threshold)
                   :total-points (+ (:total-points acc) (* points threshold))))
          ;; state to operate on
          state
          ;; vector of threshold point handlers
          point-handlers))


(defn apply-static-points
  [point-handler state]
  (loop [point-handler point-handler
         state         state]
    (if (> (:total-answers state) 0)
      (recur point-handler (-> state
                               (update :total-answers dec)
                               (update :total-points + (:points point-handler))))
      state)))


(defn calculate-points [total-answers]
  (let [threshold-points-handlers  (butlast points-system)
        consecutive-points-handler (last points-system)]
    (->> {:total-answers total-answers :total-points 0}
         (apply-threshold-points threshold-points-handlers)
         (apply-static-points consecutive-points-handler))))
now I just need to rename stuff, to make it more readable 😄

jsn18:07:09

I'm having trouble following your code, is this basically what you are trying to do:

(def points-system [{:points 1 :threshold 5}
                    {:points 3 :threshold 10}
                    {:points 7}])

(defn calc [n]
  (loop [n n
         [{:keys [points threshold]} & points-system] points-system
         score 0]
      (if (<= n (or threshold n))
        (+ score (* n points))
        (recur (- n threshold) points-system (+ score (* points threshold))))))
?

noisesmith20:07:09

by the way, using deref inside swap! is not thread safe, you should be using the value that's passed to the swapping function

noisesmith20:07:55

(here it's a likely non issue as it doesn't even need to be an atom and only one thread, but it's a thing to look out for)

respatialized21:07:08

what's the best way to debug slow startup time for a clojure program? from what I can tell, the delays all occur before any of the instrumentation I'm putting into my program to attempt to identify potential causes. Is there a way to instrument/view more of the compiler/classpath phase?

phronmophobic21:07:56

http://clojure-goes-fast.com has some general tips, http://clojure-goes-fast.com/blog/clojures-slow-start/ . what have you tried to investigate the startup time?

andy.fingerhut23:07:15

I believe some slow startup cases have been analyzed to a root cause of having a (def some-name expression) where expression was opening sockets, e.g. database connections.

noisesmith01:07:07

as for the classpath phase, that's something your tooling calculates, not clojure, and every tool has some method of exporting and reusing the cp without recalculating it

noisesmith01:07:27

it should never be a factor outside dev environments

ghadi21:07:09

look at your dependencies and slash them mercilessly