This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-07-21
Channels
- # announcements (1)
- # babashka (13)
- # beginners (85)
- # calva (1)
- # chlorine-clover (16)
- # cider (30)
- # clj-kondo (2)
- # clj-on-windows (5)
- # cljdoc (3)
- # cljs-dev (12)
- # cljsrn (19)
- # clojure (88)
- # clojure-europe (39)
- # clojure-nl (7)
- # clojure-sweden (3)
- # clojure-uk (8)
- # clojurescript (35)
- # core-async (3)
- # data-science (2)
- # datomic (17)
- # defnpodcast (3)
- # deps-new (1)
- # editors (18)
- # emacs (4)
- # events (1)
- # expound (1)
- # figwheel-main (8)
- # fulcro (9)
- # graalvm (2)
- # graalvm-mobile (11)
- # helix (44)
- # jobs (7)
- # lsp (95)
- # luminus (9)
- # malli (6)
- # meander (4)
- # membrane (2)
- # missionary (13)
- # off-topic (98)
- # pathom (2)
- # polylith (4)
- # portal (3)
- # re-frame (6)
- # reagent (27)
- # reitit (3)
- # releases (3)
- # remote-jobs (6)
- # rewrite-clj (1)
- # rum (2)
- # sci (3)
- # shadow-cljs (7)
- # sql (66)
- # tools-deps (80)
- # vim (5)
- # xtdb (3)
I'm doing a project in cljs with reagent and I want to put a view in a folder called "views", if my core namespace is myapp.core
what should the namespace of the views inside that folder be? myapp.views.someview
?
@seancorfield yes that is perfect. Sorry I did not word the question well. I want have Clojure get data, turn the data into a string that looks alot like a powershell script, then run the powershell script.
@wme.weeks OK, so the part you're stuck on is just running Powershell from Java/Clojure once you've produced the script?
Take a look at the clojure.java.shell/sh
function: https://clojuredocs.org/clojure.java.shell/sh
I would expect you can run a command like "powershell" "scriptname"
with that...?
(I don't use Powershell so I've no idea if that would work -- I only use WSL2 on Windows so everything is Linux for me)
Hey. Do any of you participate in any online Hangouts groups (or the like) meetups for Clojure/ClojureScript learning and practice? If so I'd like to participate 🙂
If there isn't one we oughta start one @rbowen
Indeed.
Hello, if looping through my data with a for
is it possible to get the index of which item it is at the moment?
no, but you can prepare you data to carry an index:
(for [[i el] (map-indexed vector data)]
)
Is this a legitimate hack in CLJS that a record could have any method defined by defining them on Object
without creating a protocol first?
(defrecord R1 []
Object
(f1 [this]
(js/console.log "R1.f1")))
(.f1 (map->R1 {})) ;; prints "R1.f1"
This code works in cljs, but not in cljI find this when reading shadow-cljs source code https://github.com/thheller/shadow-cljs/blob/1c1e35616b90d92b306f2909a6bf67a8c84243ee/src/main/shadow/cljs/devtools/client/shared.cljs#L307-L311
Can anyone help me with how I can refer to the original implementation of a function when I use with-redefs
? I want to change the behaviour of a function, but only when the input matches a predicate. Otherwise I want to delegate to the original behaviour.
with-redefs
is not safe to use in application code, and easy to produce race conditions will lose the base definition
Yeah, we don't use it in application code. It's a bit of a hack that we've been using in some debugging tooling. 🙂
I've tried holding on to the original reference with (def orig-myfn (deref #'some-namespace/myfn))
and then calling (orig-myfn ...)
from inside the definition I'm using to replace. But that didn't seem to work.
You’ve got the right idea, just need to do it in a let binding, and close over it in the replacing definition: `(let [old the-var] (with-redefs [the-var (fn […] use or call old)] ….)`
Thanks @ghadi, it still isn't working for me, let me see if I can set up a more minimal working (or not working) example and I'll post it here.
Keep in mind that with-redefs is often a smell that your program is missing an argument
This seems to work too, just as @ghadi suggested:
(let [println-orig (deref #'println)]
(with-redefs [clojure.core/println (fn [s]
(println-orig (str "Hello, " s "!")))]
(println "World")))
So it's probably something I'm doing wrong in the bigger example.(The function that you’re redefining should be passed to the thing that calls it, not directly wired)
@UDC7GA4QG side note: (= foo (deref #'foo)) => true
Yeah, that's a good point. I don't need the deref there.
On the topic of with-redefs
- what am I doing wrong here? I can’t seem to use redef with +/-
user=> (with-redefs [- +] (- 10 20))
-10
user=> (with-redefs [+ -] (+ 10 20))
30
user=> (with-redefs [map reduce] (map + (range 10)))
45 ;; okay
Thanks @ghadi - I looked at the source
for +, -, map, reduce - is there something I can read more about to understand?
There are some :inline annotations (which are not for public use) that replace calls to vars with calls to static methods on clojure.lang.RT
Interesting - I’d have imagined they get bound to later in the execution - so, redef gets a chance to override. But, is this behaviour to be expected? I am still surprised and unclear.
OK, I think some of the issue I was seeing was that I was rebinding a multi-method. And foolishly only bindings one of the arities. That worked when I didn't have to refer to the original function, but doesn't work now. Not sure why. Anyway, using a variable arity function to override seem to do the trick. 🙂
I would categorically say that redeffing clojure.core is undefined behavior @jaju There are other things that confound redef (clojure.core is shipped direct linked), and redeffing clojure.core functions has the potential to break clojure itself
Agree. I’ve never used with-redefs. But I guess there should be a clean denial from Clojure when overriding core, rather than a silent failure. Thanks so much for explaining - I was struggling to identify where I was going wrong! 🙏
Is it safe to inspect the meta
of a var and look for :inline
to help decide that with-redefs will not work?
I am wrapping shell/sh
in a function. Is there a way to pass in optional arguments. My issue is that shell/sh
seems to only take strings outside of any data structure
if I understand you correctly, the solution is to use apply
(apply f [a b c])
and (apply f a [b c])
and (f a b c)
all result in the same function call
without the varargs you end up with a bunch of boilerplate collection building code
or silliness with partial
(I've dealt with this from coworkers who didn't realize apply was varargs)
On that same note, How should I define a function with defn
if I have optional arguments?
(defn optimise {a b & opts])
what should opts be ? a hashmap?
opts ends up being effectively a list
(ins)user=> (defn optimise [a b & opts] (println "opts is" opts))
#'user/optimise
(ins)user=> (optimise 1 2 3 4 5 6)
opts is (3 4 5 6)
nil
If have a list of named optional args is the & opts
method a good one? or should just do (defn optimise [a b opts])
where i just put opts as {}
if there are no optional args?
if you expect key/value pairs using a hash map instead of varargs is usually better
For context am wrapping a script with shell/sh
and there are compulsory and optional arguments. And am thinking what is the best way to approach this
you can have a separate arg list for the case where no opts are provided
(defn foo
([x y] (foo x y {})
([x y opts] ....))
since this is #beginners - a useful idiom to know:
(merge {:a "default-a" :b "default-b"} opts)
merge effectively implements everything you need for merging defaults with provided optionsthe second arg overwrites any keys shared with the first arg
Also worth noting that as of Clojure 1.11 (in alpha right now), if you declare (defn foo [x y & {:as opts}] ...)
then you can call this with either key/value arguments (foo 1 2 :bar 3 :quux 4)
or a hash map (foo 1 2 {:bar 3 :quux 4})
(and even a mix of the two, with the hash map following any key/value arguments (foo 1 2 :bar 3 {:quux 4 :wibble 5})
(over time we will probably see more APIs declared this was, as opposed to [x y opts]
, once we have the flexibility to call them in "human style" -- key/value named arguments -- or in "program style" -- a hash map of arguments; you can already do this with the CLI with -X
and the new -T
options)
Anybody know how to format strings like printf in C? ... you know with the %d arguments...
I only found the [goog.string :as gstring]
which has a format function which lets me do exactly that... but is there something similar in clojure?
https://clojuredocs.org/clojure.core/format. or cl-format
if you really want to go crazy. there’s several pages of docs for that one.
that was easy
dunno I never found it
thanks a bunch!!
Hey this doesn't work in clojurescript... is that true?
Or, yaknow, printf
😝 https://clojuredocs.org/clojure.core/printf
format and printf are both built on java's formatting, if you are using goog.string you don't have java stuff because you are writing clojurescript
Hello, what am I missing about this function?
(defn rapunzel [rpnzls]
([] (rapunzel "rapunzel"))
([rpnzls]
(if (= rpnzls "rapunzel")
(println "let down your hair"))))
I get a StackOverflow xD(defn rapunzel [rpnzls] ;; <<<------- what is this?
([] (rapunzel "rapunzel"))
([rpnzls]
(if (= rpnzls "rapunzel")
(println "let down your hair"))))
Ohh haha
ironically, vector can be used as a function (thus no runtime error due to ([] ....)
), so the code did what you asked it to do 🙂
For a research project I need to perform a long calculation (multiple hours) resulting in a large map (~ 50 million keys). My goal is to do the calculation only once on someone else's very powerful machine and somehow store the resulting value such that I can use the value on my own machine machine without having to wait those long hours ever again.
The direction I went in is to make a second project where I assign the result of the long calculation to a var, AOT compile it and include the resulting jar as a dependency in my research project.
To test this approach I did the following. In my to-be-compiled library project I have a src/lib/core.clj
:
(ns lib.core)
(def x (do (println "calculating...")
:foo))
in my project.clj
(I use Leiningen 2.9.6 on Java 11.0.11 OpenJDK 64-Bit Server VM) I include :aot :all
and indeed, when I lein jar
I see
Compiling lib.core...
calculating...
and I obtain a .jar file. I successfully add it as a dependency in my research project, but when I therein start a REPL and evaluate
(ns research.core
(:require [lib.core]))
to my surprise I again see calculating...
being printed.
If I do not include :aot :all
in the library's project.clj
, upon lein jar
I do not see calculating...
printed, so the :aot :all
does seem to have effect. Seeing calculating...
again when I evaluate the namespace that requires the .jar makes no sense to me: isn't the jar AOT compiled? Am I missing something?
Also open to other ways of reaching my goal of calculating once and having the value available on other machines/REPL restart.When you AOT a namespace, it means that the compiler is going to write bytecode to disk. That bytecode contains the recipe for loading your namespace. It is not writing bytecode that represents the state of the namespace after the load.
@ghadi if it's just a recipe why is it then evaluating the top-level forms/vars? Is this the "just recipe" part also the reason why the code is evaluated, again, when loading the AOT-compiled namespace.
What you want to do is compute your expensive thing, then serialize map to disk using something like EDN, JSON, or Transit.
thanks!
thanks!