Fork me on GitHub
#clojure
<
2020-04-12
>
pinkfrog02:04:26

what is the x in the xrel for ?

g7s05:04:59

It should have no meaning I guess. In the same manner someone uses x as a variable name the author here used xrel to indicate that it is a relation also (in the relational model sense)

g7s05:04:48

For example clojure.set/join has a yrel also indicating another relation that will perform the join against

sogaiu03:04:07

don't know but set.clj also has things like join that have a yrel too

seancorfield04:04:54

I sort of assumed it was cross-relation but I have no basis for that. I find clojure.set to be a strange mix of simple, obvious stuff and weird stuff I'm not sure about...

pinkfrog06:04:36

I kinda feel (/ num) gives 1/num weird.

pinkfrog06:04:13

for example, (/ num (repeat k divisor)) . when k = 0, things got broken.

pinkfrog06:04:33

(apply / num (repeat k divisor)) I mean.

pinkfrog06:04:22

the normal case gives num/(divosor)^k . when k > 0, and when k ==0, the value is 1/num, not num/(divisor)^0.

pinkfrog06:04:36

where is that function ?

didibus06:04:31

Sorry I mean quot, but also I might have read your problem wrong

didibus06:04:56

Ya, your code doesn't do divisor^k

didibus06:04:10

It's more like multiple / one after the other

andy.fingerhut06:04:58

I understand what you are saying @i but I think this is simply a case where you have an edge case in the number of parameters, and a use case that exercises that edge, that gives you different results than you wish. I have no personal knowledge of existing Clojure code that relies upon the current behavior of (/ n) , but if there are 0 occurrences of such code I would be very surprised. Backwards compatibility is a good thing for Clojure, if there are such use cases today.

andy.fingerhut06:04:29

If you want a function that calculates num / (divisor)^k then I would recommend something more like (/ num (apply * (repeat k divisor)))

andy.fingerhut07:04:44

Neither your original code nor my suggested replacement are good for k < 0, of course, nor for non-integer values of k, so my suggestion only covers one additional value that yours did not (i.e. k=0). Not sure what kind of generality you are looking for, though.

didibus07:04:14

I'd recommend using a power function if you want power most probably

pinkfrog07:04:35

i have another question regarding consistency. for example, conj accepts varidiac arguments, but conj! does not.

pinkfrog07:04:59

why to allow such significant in-consistency in the core lib?

didibus07:04:48

Maintainance burden I think

didibus07:04:08

It also gets hard to create consistency, lots of thinking required, and easy to introduce inconsistency even if you spend a lot of time making sure you don't

andy.fingerhut07:04:02

There is an open ticket suggesting making conj! variadic, but has not been addressed (and might never be). Such things are nice to have, and similar things have been changed in Clojure in the past, so it is possible it might be changed in future Clojure version.

andy.fingerhut07:04:22

I believe this is the issue in JIRA that is relevant: https://clojure.atlassian.net/projects/CLJ/issues/CLJ-1103

andy.fingerhut07:04:01

The transient functions are far and few between, and used in far fewer places in typical code than the persistent versions.

andy.fingerhut07:04:14

So yes, a few people might notice, but most never would.

andy.fingerhut07:04:49

If you wish, you can vote on issues you wish to be changed here on http://ask.clojure.org -- votes do not guarantee anything will be done, but high-voted issues tend to get addressed (as in fixed with a change, or declined) sooner than issue that no one votes on.

pinkfrog07:04:00

thanks for that info.

pinkfrog07:04:36

on the other hand, this makes me think: for such transient stuff, I may resort to java libraries more, such as java.util.stack

Setzer2208:04:53

A question about transients: I have a grid data structure represented as a vector of vectors, and I find myself updating it quite frequently. I would like to use transients to make the tight loops faster (and avoid unnecessary allocations!), but since it's a nested structure, I'm a bit confused. Should I recursively convert all the inner vectors into transients, then the outer vector, and then recursively convert everything back to persistent?

Jim Newton09:04:24

help understanding java.lang.IllegalStateException I have a main file named core.clj which had several function definitions in it. I'm trying to move those function definitions to another file which does not reference core.clj at all. When I try to load that file, I get the error:

2. Unhandled clojure.lang.Compiler$CompilerException
   Error compiling src/clojure_rte/rte_tester.clj at (1:1)
   #:clojure.error{:phase :compile-syntax-check,
                   :line 1,
                   :column 1,
                   :source
                   "/Users/jimka/Repos/clojure-rte/src/clojure_rte/rte_tester.clj"}
             Compiler.java: 7647  clojure.lang.Compiler/load
                      REPL:    1  clojure-rte.core-test/eval30126
                      REPL:    1  clojure-rte.core-test/eval30126
             Compiler.java: 7176  clojure.lang.Compiler/eval
...stuff omitted..

1. Caused by java.lang.IllegalStateException
   random-test already refers to: #'clojure-rte.core/random-test in
   namespace: clojure-rte.rte-tester
I don't understand why I get a symbol conflict, when I'm not even using nor referencing the ns clojure-rte.core

hindol09:04:50

Did you restart your REPL? In a running REPL, symbols are not unset automatically. Also, are you using a different namespace for the other file?

Jim Newton09:04:02

yes both files have a different name space.

Jim Newton09:04:51

delaying the question of repl for the moment. Am I allowed to the the same function name in two different name spaces as long as the name spaces are independent from each other? Seems logical, otherwise namespaces would be useless. right?

Jim Newton09:04:33

re: restarting the repl, no I haven't restarted it yet. I actually don't know how to restart the cider repl.

hindol09:04:55

Yes, and you can do that even when one namespace depends on another.

Jim Newton09:04:10

in CL/slime there's a function slime-restart-inferior-lisp, I don't find such a cider function

hindol09:04:17

Only things from clojure.core are available without a namespace prefix.

Jim Newton09:04:05

yes, that's how I understand it as well. But the error message seems to say otherwise.

hindol09:04:06

So, if you wanted to redefine clojure.core.map you first have to exclude importing map from clojure.core. Otherwise, it is absolutely fine.

hindol09:04:56

Did you start the REPL or did CIDER start it? If the latter, you can disconnect and jack-in again.

Jim Newton09:04:57

Here is my namespace definition in rte_tester.clj

(ns clojure-rte.rte-tester
  (:require [clojure-rte.tester :refer [ random-test]]
            ;; [clojure-rte.core :refer []]
            ))

Jim Newton09:04:50

BTW what does ns do if such a namespace already exists? does it delete the old one, or just extend it? maybe I need to delete the ns before re-loading the file?

hindol09:04:21

Okay, you should not use :refer most of the times. Somehow a symbol named random-test is already present in the clojure-rte.rte-tester namespace.

hindol09:04:18

:refer is usually a bad practice. Use a short alias for the namespace instead. [clojure-rte.tester :as tester] for example.

hindol09:04:54

Then the symbol from the tester namespace is available as tester/<symbol>.

Jim Newton09:04:33

can I remove that symbol from tester?

hindol09:04:27

You can :rename. Not sure if something can be excluded.

hindol09:04:20

I have only seen :exclude used w.r.t. Clojure core.

Jim Newton09:04:56

Isn't this a problem all beginners have? Where should the process be documented? I saw someone recently say "Yea you're right, this process seems to be missing from the documentation"

hindol09:04:01

But if you import without :refer, probably you won't have to exclude.

hindol09:04:55

I faced the same issue initially. Documentation only makes sense when you are past a stage.

Ben Sless11:04:36

@U010VP3UY9X you can unmap a symbol from a ns:

(.unmap *ns* 'foo)
That should work

Ben Sless11:04:11

(it's also a bit of a hack accessing the namespace object's methods)

andy.fingerhut12:04:24

If your code can be made public, others could try to reproduce it, and/or look at a more complete state of what you are trying to do, with less guessing.

andy.fingerhut12:04:40

I realize that might not be possible depending upon the project you are working on.

andy.fingerhut12:04:09

Also, again, good to see if the issue occurs in a fresh REPL started from the terminal, rather than from CIDER. Even with CIDER, using some mechanism (I do not know, since I do not use CIDER myself) to ensure that a current JVM is stopped, and a new JVM started, could help eliminate problems that can occur if there is an existing set of namespaces, and you are moving functions from one namespace to another.

andy.fingerhut12:04:38

Yes, it is certainly possible to remove the namespaces from an existing running JVM, and then create new occurrences of those namespaces with the same names.

andy.fingerhut12:04:32

You are definitely allowed to have the same symbol name in two different namespaces, for two different functions (or whatever values the names refer to, integers, collections, etc. -- it doesn't have to be functions).

andy.fingerhut12:04:46

But if namespace B does (:require [A :refer [some-name]]) then it is a name conflict to have something named some-name in namespace B as well, because the :refer [some-name] means "inside of namespace B, I want to be able to use the symbol some-name to name the thing called some-name inside of namespace A".

hindol16:04:36

I forgot to mention, you can mark a symbol as private and it won't be imported when some other namespace imports this namespace.

(defn ^:private f ...)
(def ^:private x ...)

ryan echternacht14:04:15

Macro question: I have a macro that is designed to work like ->, except if it encounters a map it does some special work. If I’m working with raw maps, it’s fine, but if I pass in a symbol bound to a map, it doesn’t do the special work. What do I need to do to change this? NOTE: this is designed to work with reagent, which is why I mapv the results

(defmacro macro-> [node & forms]
  (let [forms-rewritten# (mapv
                          (fn [form]
                            (if (map? form)
                              `(special-work ~form)
                              form))
                          forms)]
    `(-> ~node
         [email protected]#)))
(macro-> node {:a "a"}) works fine but (def my-map {:a "a"}) (macro-> node my-map) doesn’t I want those 2 ^ to work the same

Ben Sless15:04:43

Is the symbol bound by a def or in a let?

ryan echternacht15:04:56

I can see use cases for both

Ben Sless15:04:22

yeah, but one is easy and the other is hard 🙃

Ben Sless15:04:06

for let bindings I have some ideas, but they're still theoretical

emccue14:04:54

well, you just need to accept some runtime cost

emccue14:04:44

and do the map check at runtime as part of your macroexpanded code

emccue14:04:29

(if (map? form)
  `(special-work ~form)
  form))

emccue14:04:31

would go to

emccue14:04:47

`(if (map? ~form)
  (special-work ~form)
  ~form))

emccue14:04:53

kinda the only way

emccue14:04:16

(that probably wouldn't work as is, you'll need to do some more thinking and maybe manually expand a tad more)

emccue14:04:33

(you might need to rewrite what the -> macro does, but that shouldn't be that bad)

coby17:04:53

has anyone else run into a problem with rlwrap while trying to run the clj CLI in a containerized Clojure app? This GH issue is not Clojure-related but it seems to describe the same underlying Docker issue (which was "fixed" by...not using rlwrap 😞) https://github.com/Raku/docker/issues/3

hiredman17:04:16

Use clojure not clj

seancorfield17:04:31

Which was the "fix" in the issue: not using rlwrap 🙂

coby18:04:34

Yeah, I've used that bandaid...it just sucks because clj is a much better UX. Not having arrow keys is a total productivity killer, for example. So just thought I'd cast out to see if anyone found a better solution. Thanks!

Alex Miller (Clojure team)18:04:56

if there is a fix that can be applied to rlwrap, happy to do so in the clj tool

coby18:04:57

Thanks @alexmiller, I'll poke around in Docker a bit today

borkdude19:04:26

Any reason why one example fails at read time and the other one "works"?

user=> #{#() #()}
Syntax error reading source at (REPL:1:11).
Duplicate key: (fn* [] ())
user=> #{#(-> %) #(-> %)}
#{#object[user$eval5$fn__143 0x7aead3af "[email protected]"] #object[user$eval5$fn__6 0x7c1c5936 "[email protected]"]}
The latter example also fails in babashka unlike in Clojure, but I want to know what's the expected behavior here

dominicm19:04:27

{(rand) 1 (rand) 2} is the same. It's because there's some checks in the reader. I've taken it to mean that you should probably not put non literal indexes into literal syntax.

Cameron19:04:57

I'm messing around with it now and so far it looks like the second doesn't pass reading because, unlike #() which reads to the list (fn* [] ()) twice, which will count as equal, #(-> %) is going to have an argument, which on read will be gensymmed into having a unique name each time and, thus, the two lists will not count as equal ( #{(fn* [p1__9062#] (-> p1__9062#)) (fn* [p1__9061#] (-> p1__9061#))} as a random example of me calling read on this)

andy.fingerhut19:04:01

@borkdude probably because of the read results?

user=> (read-string "#()")
(fn* [] ())
user=> (read-string "#()")
(fn* [] ())
user=> (read-string "#(-> %)")
(fn* [p1__195#] (-> p1__195#))
user=> (read-string "#(-> %)")
(fn* [p1__198#] (-> p1__198#))
user=> (read-string "#(-> %)")
(fn* [p1__201#] (-> p1__201#))

andy.fingerhut19:04:09

Going for that level of compatibility between multiple Clojure implementations seems like a bit of a stretch to me, unless you actually find some subtle bug that affects other behavior as a result.

borkdude19:04:12

would it be an error in babashka not to accept this?

andy.fingerhut19:04:08

I haven't thought about it for more than half a minute, but it seems reasonable to leave that behavior in an implementation, and if someone files a bug report, see if it was an experiment they did toying around, or actual production code. If it was production code, push back a little more and see if they know how fragile it is 🙂

andy.fingerhut19:04:35

They can always use (set [expr1 expr2]) instead of #{expr1 expr2} if they want it to "work", where I put that in scare quotes because, well, I think maybe they should be scared if the difference is that important 🙂

👍 4
borkdude20:04:27

yeah, so now it's up to @ivangalbans to respond to this 🙂

ivangalbans20:04:01

I have changed my script and it works very well. Thanks a lot @borkdude, @andy.fingerhut

ivangalbans20:04:20

this difference is not important in my use case 👍

didibus20:04:27

The bigger question is why does the second not work in babashka? Does the reader expand things differently? Could that affect the behavior in other places as well compared to Clojure?

borkdude20:04:53

@didibus bb uses edamame and edamame always expands function literals to the form:

$ bb -e "'#(-> %)"
(fn* [%1] (-> %1))
so it doesn't use gensym'ed symbols for those

didibus20:04:15

Hum, interesting, I wonder why Clojure uses gensym then, if it's just an implementation artifact, or is the choice of gensym deliberate. Like can this cause shadowing to happen? Are there good reasons not to want to shadow %1? I would only think of nested #() but those aren't allowed anyways. And I feel choosing to call something % or %n is other context just feels wrong anyways.

borkdude20:04:10

@didibus Last time I asked Alex, he said this way of expanding doesn't result in any problems. He also said they were doing something similar for spec2.

👍 4
borkdude22:04:39

In normal JVM Clojure when executing a script, is there a way of detecting whether you're being called with a main argument -m foo or just executing as a script file?

(defn -main [& args]
  (println "args" args))

(when ... ;; we're running as a script
  (apply -main *command-line-args*))

Risque23:04:10

I have an uberjar key in my project.clj, like so: :uberjar { :env { :foo "bar" :foo2 "bar2" } } but upon running lein uberjar, my app isn't using the keys from uberjar but from the :dev {:profiles {:env ...}}. How do I fix this?

phronmophobic23:04:05

@prikshet21,I can’t find :env documented in stock lein. are you using a plugin?

Risque10:04:23

No I'm not. without having the :env, I get null pointer exception on Heroku when using them, even though the config vars are set there.

seancorfield23:04:38

@prikshet21 I don't use Leiningen so I don't really understand what you're trying to do there but I would not expect the JAR file produced by Leiningen to use anything from project.clj -- it's a standalone application and it runs in its own JVM context, not Leiningen's.