This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-02-13
Channels
- # announcements (12)
- # babashka (88)
- # beginners (60)
- # biff (10)
- # calva (56)
- # clerk (9)
- # clj-kondo (5)
- # clojure (70)
- # clojure-austin (3)
- # clojure-conj (2)
- # clojure-dev (69)
- # clojure-europe (53)
- # clojure-nl (1)
- # clojure-norway (28)
- # clojure-uk (1)
- # clojurescript (27)
- # copenhagen-clojurians (3)
- # cursive (10)
- # datascript (1)
- # datomic (10)
- # fulcro (3)
- # funcool (1)
- # garden (7)
- # helix (5)
- # holy-lambda (5)
- # hyperfiddle (39)
- # introduce-yourself (6)
- # jobs-discuss (15)
- # lsp (3)
- # malli (5)
- # membrane (19)
- # missionary (1)
- # nrepl (6)
- # off-topic (44)
- # pathom (17)
- # pomegranate (3)
- # react (7)
- # releases (1)
- # shadow-cljs (39)
- # tools-deps (16)
- # xtdb (28)
I am using a multimethod (demulti) that handles a couple of stuff, which for example it takes "string" or "number" and return accordingly. How do I create a method that returns something for everything else not handled? Like a default defmethod
something like (defprotocol PrettyPrintable (pprint [this])) (extend-type String PrettyPrintable (pprint [this] (clojure.pprint/pprint this))) (syntax is probably wrong but you get the idea) instead of (defmulti pprint (fn [obj] (type obj)))
@U02F0C62TC1 aside: type
was enough, instead of (fn [obj] (type obj))
I keep getting a neverending loop of these warnings/messages in console Warning: Every element in a seq should have a unique :key: ([app.strive_forms.views.multi_question_page ....
This is my code tat contains multi_question_page
(defn multi-question-page [{:keys [props]}]
[v-box
:children [
(map-indexed (fn [index field]
^{:key (str "new-" (:id field) index)}
(when (:condition)
[gap-space {:primary-gap (:header-to-question-question-card (:gaps-primary default-values))
:secondary-gap (:header-to-question-question-card (:gaps-mobile-view default-values))}]
[question-card {props}]))
display-fields)
[gap-space {props}]
[action-button {props}]]])
(defn form-swipeable-panel [{:keys [index display-fields selected-language theme-data form-messages current-page hidden-fields
input-data on-submit pre-filled regenerate-display-fields]}]
(let []
(if-not (:is_group field)
[single-question-page {props}]
[multi-question-page {props}])))
(defn question-page [{:keys [props]}]
[v-box
:height "100vh"
:justify :center
:children [
[(r/adapt-react-class SwipeableViews)
{:index @current-page
:onChangeIndex #(reset! current-page %)
:style {:display "flex"
:justify-content "center"}
:springConfig #js{:duration "2s"
:delay "3s"}
:class (form-content-style)}
(map-indexed (fn [index field]
^{:key (str "question-page-" (:id field) index)}
(form-swipeable-panel {:props props}))
display-fields)]
[form-page-footer form-messages]]])
Obviously made code readable by actually replacing the props with "props" and apparently the key I added isnt working. When I open console it keeps lagging too from all the endless messages of the warning1. I would write a much simpler component that tries to isolate the problem as much as possible.
2. Another tip would be to avoid using indices when generating keys for react. if (:id field)
is insufficient, your ids are not actually unique, then you might pre-generate uuids (for example) in your dataset, which are maintained between state changes.
3. I'ts unclear where display-fields
comes from in your example and how it looks like.
Oh it also seems like you are attaching a key to the gap-space
component but not to the question-card
component in your :children
expression. But I'm not a reagent user so I might be wrong.
You are attaching the metadata at read time using ^ it is being attached to the form of the function call, not the result of the call
I am trying to wrap my head around recursion in Clojure for a project, but I stumbled upon a problem when two functions are calling each other, like in this simplified example:
(defn doThis
[times]
(print "Doing this!")
(when (> times 0)
(doThat (- times 1))))
(defn doThat
[times]
(print "Doing that!")
(when (> times 0)
(doThis (- times 1))))
This produces an ‘unresolved symbol’ error for doThat
inside of doThis
. To me the problem seems to be that doThat
is not defined before its usage in doThis
. What can I do to solve this problem?This is what declare
is for, I believe. So, (declare doThat)
above doThis
should let you set it up.
https://clojuredocs.org/clojure.core/declare are a few examples.
You can also define those mutual recursive functions inside defn with letfn: https://clojuredocs.org/clojure.core/letfn
Thats exactly what I was looking for! Thanks for the quick answers and pointing me in the right direction!
Just remember to be cautious about choosing to use mutual recursion.
For plain tail recursion, we can mimic tail call optimization with recur
. There is no such construct for mutual recursion. Quite tricky to know for certain that your input data will always be constrained enough to not blow the stack.
Might be able to solve that with a trampoline, but personally I find that to be a pretty clunky alternative.
I followed the https://www.youtube.com/watch?v=wq6ctyZBb0A tutorial and tried to use it to create my application, but I got stuck on this. I started lein cljsbuild once dev, and then lein figwheel, but nothing is rendered on the page, it reports an error in the console. This is my project.cljs file and console screenshot:
(defproject thats-life "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"
:url " "}
:main thats-life.core
:cljsbuild {:builds [{:id "dev"
:source-paths ["src"]
:figwheel true
:compiler
{:optimizations :none
:output-to "resources/public/javascripts/dev.js"
:output-dir "resources/public/javascripts/cljs-dev/"
:pretty-print true
:source-map true}}]}
:plugins [[lein-cljsbuild "1.1.8"]
[lein-figwheel "0.5.20"]]
:dependencies [[org.clojure/clojure "1.11.1"]
[org.clojure/clojurescript "1.11.60"]
[reagent "1.1.1"]]
:repl-options {:init-ns thats-life.core})
and, this is the index.html file
<html>
<head>
<title>That's Life</title>
</head>
<link rel="stylesheet" type="text/css" href="main.css" media="screen" />
<body>
<div id="game"></div>
<script src=""></script>
<script src="./javascripts/cljs-dev/goog/base.js"></script>
<script src="./javascripts/dev.js"></script>
<script>goog.require('thats_life.core')</script>
</body>
</html>
I have no idea if I need to add a dependency somewhere else, any help is welcome
Changing the subject a tad, if you just want to get on with web programming, this will give you a working Reagent project:
lein new figwheel-main hello-world.core -- +npm-bundle --reagent
I got that from here: https://github.com/bhauman/figwheel-main-template
hthI feel like there is a built in way to do this that I’m missing (I’m probably crazy)?
(defn thing
"Return (function value) if (funcion value) is truthy.
Otherwise return value."
[function value]
(if (function value) (function value)
value))
Thanks folks, some good options.
Does clojure.core
have an absolute value function? I keep finding some conflicting information but I don't see it on ClojureDocs. Not a big deal either way, I'm just looking for clarification. My editor even references clojure.core/abs
when a define my own abs
function.
1.11.1.1224
Ah, it's in an alpha.
(defn abs
{:doc "Returns the absolute value of a.
If a is Long/MIN_VALUE => Long/MIN_VALUE
If a is a double and zero => +0.0
If a is a double and ##Inf or ##-Inf => ##Inf
If a is a double and ##NaN => ##NaN"
:inline-arities #{1}
:inline (fn [a] `(clojure.lang.Numbers/abs ~a))
:added "1.11"}
[a]
(clojure.lang.Numbers/abs a))
Hmm, that's strange. When I call abs
I get a runtime exception with an error "Unable to resolve symbol abs in this context"
Oh, I just figured it out.
The project level Clojure version is 1.10.
Does the str
fn call something on the types passed to it? As in (str (Person. "Jakub"))
, would it call a method on the Person type?
I was expecting defining toString
on Person would do the trick, but it gives me an error.
I know I can define print-method
for when used with println
and the likes, but is there anything like that for str
?
https://gist.github.com/jakub-stastny/ed50811d1459f4376929c248137a00e3
user=> (deftype F [] Object (toString [_] "foo"))
user.F
user=> (str (->F))
"foo"
user=>
The code runs just fine if I call it stringify
. The moment I replace stringify
with toString
, I get: `WARNING: Implicit use of clojure.main with options is deprecated, use -M
Syntax error (IllegalArgumentException) compiling toString at (test.clj:11:20).
No single method: toString of interface: user.Version found for function: toString of protocol: Version`
Interesting.
I see it has something to do with the Object
.
sure, because those inline definitions are grouped with the interface they are part of
so for your Version protocol there is no "toString" function, which is exactly what the error says when you replace stringify with toString
Methods should be supplied for all methods of the desired
protocol(s) and interface(s). You can also define overrides for
methods of Object. Note that a parameter must be supplied to
correspond to the target object ('this' in Java parlance). Thus
methods for interfaces will take one more argument than do the
interface declarations. Note also that recur calls to the method
head should *not* pass the target object, it will be supplied
automatically and can not be substituted.
OK, thanks.
@U0NCTKEV8 how do I extend Version
protocol with Object
? Or am I thinking all wrong?
I know I can't inherit from multiple protocols or at least it doesn't work, having (deftype QID [] Object Version)
.
Each spec consists of a protocol or interface name followed by zero
or more method bodies:
protocol-or-interface-or-Object
(methodName [args*] body)*
I seeee! got it!