This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-02-20
Channels
- # announcements (1)
- # architecture (14)
- # asami (21)
- # babashka (1)
- # beginners (44)
- # biff (6)
- # calva (24)
- # clojure (16)
- # clojure-europe (12)
- # clojurescript (32)
- # cursive (23)
- # datascript (5)
- # honeysql (8)
- # hyperfiddle (1)
- # malli (1)
- # nextjournal (34)
- # nrepl (4)
- # off-topic (64)
- # re-frame (12)
- # reagent (1)
- # releases (2)
- # reveal (41)
- # shadow-cljs (137)
- # spacemacs (4)
- # xtdb (5)
Hey, how difficult do you find updating your applications Java version? Is the process smoothe or do you find a lot of breakage when jumping up versions?
rarely a problem
Java 9 had a number of significant changes from Java 8 - that's probably been the toughest update for most people
I see, so from 9 to 17 is easy?
in my experience: • java8->java9 - few breakages, most solved by bump one library, or add an opt-in dep • java9->java17 - no breakages
Interesting.
We have some legacy code that still has to run on Java 8 for... reasons... and I will say that 8->9 was the biggest update (our app can't run on 9). All our other code that made it to 9, also made it easily to 10, 11, 12, 13, 14, 15, 16, 17 (which is what we're on in production for everything except that legacy app). We went 8 -> 11 -> 17 for those apps.
I just started using Azul Java 17 on my dev machine, up from Azul Java 11. Performance seems the same for a job i do daily, which I consider a relief. (At first I thought there was a 50% performance degradation. Turns out I accidentally installed an x86 JVM instead of ARM. Whew!)
Do you know of any platforms that specialize in hosting for Java/Clojure application?
Heroku has had hosting for clojure apps from the start, but that hasn't updated with support for deps.edn stuff quite yet (though there is a workaround)
@U5NCUG8NR stretch goals for farolero?
I guess I don't understand what the goal would be with something like this. Like clojure's not statically typed, so the pure/impure distinction is less relevant or at least less externally obvious and not visibly viral. Besides the fact that you can just do all this with conditions and arguments, so would it just be like an addon library that has a bunch of effects in it already?
Not necessarily something that has to be built into farolero, but could definitely be built with it. No reason why you couldn't run type inference over Clojure code, either, although the language is dynamically typed
Right, I guess I see that you could do this, and it would be equivalent to the effect system that's being used, but what I was saying is that I don't actually see what there is in Koka that can't be more or less directly translated to farolero code. Like their example on the front page is just
(defn traverse [xs]
(when (seq xs)
(far/signal ::yield (first xs))
(recur (rest xs)))
(defn -main []
(far/handler-bind [::yield (fn [i] (println "yielded" i))]
(traverse [1 2 3])))
And their more complex example in the docs which uses ctl
instead of fun
is this:
(defn traverse [xs]
(when
(and (seq xs)
(far/restart-case (far/signal ::yield (first xs))
(::far/use-value [v] v)))
(recur (rest xs))))
(defn print-elems []
(far/handler-bind [::yield (fn [i]
(println "yielded" i)
(far/use-value (<= i 2)))]
(traverse [1 2 3 4])))
Like the only bits here that could really stand to be made more convenient is to make something that's like cerror
but instead of binding continue
it binds use-value
.
And I'm not sure what adding static types/type inference over this gives you.
Does anyone have a presentation slide tool to recommend? I normally do most things on paper first (sticky notes on a board), then refine into some markdown text documents and then I take all the markdown and force feed it into Keynote manually. It's the final step I take the most issue with at the moment - is there not a better tool than this? 🙂 I've tried RevealJS which I found usable but pretty complex. Any other ideas?
My presentations are often simple so tools which export to reveal are good for my use case
Do you know [Remark](https://remarkjs.com/) ? It's basically a way to make your presentations in markdown, and style them with css. I haven't used it for more than 1 or 2 basic presentations, but so far I like it
Obligatory mention of http://pitch.io ; their product is really good and they're a Clojure shop
Suppose we have a table where rows are possible values of variable A and columns are possible values of variable B. Cells are some actions that need to be taken if the variables A and B both have corresponding values. What would be the best way to represent it in code in such a way so that it's immediately obvious what's going on and it's impossible to just miss a particular combination of values? I remember seeing an ASCII table parser, but I do not want to use that. :D
Do you mean something like this (from the https://github.com/clojure/core.match/wiki/Basic-usage#matching-literals)?
(let [x true
y true
z true]
(match [x y z]
[_ false true] 1
[false true _ ] 2
[_ _ false] 3
[_ _ true] 4
:else 5))
Hm... thinking literally literally... If the a/b pairs and corresponding operations are all known in advance, then, what if...
(def ab->op
{[:a1 :b1] :op-name1
[:a2 :b2] :op-name2
[:a3 :b3] :op-name3
[:a4 :b4] :op-name4
;;;
})
(defmulti exec-op
(fn [a b]
(ab->op [a b])))
(defmethod exec-op :op-name1
[{}]
...)
?What you describe is an execution strategy, not a representation one. The ab->op
map above is missing [:a1 :b2]
, along with other clauses - that wouldn't be known without actually running the code.
My goal is to grasp what's up, without running anything.
The perfect scenario would allow even showing it to a non-programmer and making them understand it without delving into Clojure details.
> The ab->op
map above is missing [:a1 :b2]
Oops, sorry about the confusing notation. I meant it to be a total map of all a/b values, (with the assumption that it is a pre-computed table with all mappings known in advance). :op-name
would be some human-readable / descriptive name for what to do for a given a/b pair.
In my head, such an ab->op table is the human-language explanation.
I'm not sure any more what you actually seek.
I was simply doubting that tables are all there is to it. :) Seems like I was doubting without a good reason.
A ab->op
map might be exhaustive indeed, but it's a 1D structure representing an inherently 2D entity. It might contain all the information, but it's not obvious.
Compare e.g. a table 100x100 in Excel with such a map of 10000 entries.
We have a place where we don't use our fancy case macro, and instead use a multimethod, and then have a top-level doseq over the state machine states asserting that the multimethods dispatch table contains all of the states
> but it's a 1D structure representing an inherently 2D entity
Yup, sad limitation. I think it's really a cube though... there are 3 dimensions [a, b, op]
. It's a job for an APL :)
> a table 100x100 in Excel with such a map of 10000 entries Implicitly I hoped it was something smaller, say 10a x 10b x 1op at most.
Realistically, it's even smaller. Well, usually. But it's still easy to miss 1 case out of 100. Or keep staring at it for a minute before you find it.
> Compare e.g. a table 100x100 in Excel with such a map of 10000 entries. Now I'm having a very bad thought... what if the a/b/op table is stored as a table in a DB and read as configuration?
Case won't ensure you have all the possibilities, but if you get a possibility that is handled it will throw
maybe a macro + some clever formatting
'(match
a (0 1 2 3)
b
((0 true false false false)
(1 false true false false)
(2 false false true false)
(3 false false false true)))
I can already imagine myself hitting Ctrl+Alt+L and cursing. :D But yeah, it looks nice.
Or doseq over two lists (a and b) executing multimethod throwing on :default value.
The main downside is that it won't be obvious what's going on. All the possible values and combinations will be scattered quite a bit.
Our billing system at work has a big state machine inside it, and from that state machine we have some custom versions of case that do exhaustiveness checking
We have a lot of predicates defined on states for the machine, and they use the custom case implementations and throw exceptions at macro expansion time if a state isn't handled
Do you mean something like this (from the https://github.com/clojure/core.match/wiki/Basic-usage#matching-literals)?
(let [x true
y true
z true]
(match [x y z]
[_ false true] 1
[false true _ ] 2
[_ _ false] 3
[_ _ true] 4
:else 5))
Something like that, yes. But regular match
doesn't make it obvious what the domains are and doesn't make it obvious that all the combinations are handled (assuming there's no catch-all :else
).
> doesn't make it obvious what the domains are and doesn't make it obvious that all the combinations are handled
I see. Can this gap be closed by defining a spec? (a https://clojuredocs.org/clojure.spec.alpha/multi-spec perhaps?) ... scratch that. This does not address the "immediately obvious, and exhaustive check" requirement.
separate your data model and execution model
Your data is
[{:a A :b B :action t} ...]
Then just index it conveniently
My first thought was a map of maps, where the inner maps get generated with a zipmap
So, for instance:
(def b-vals ["one" "two" "three"])
(def a-data
{:first-a [op-f1 op-f2 op-f3]
:second-a [op-s1 op-s2 op-s3]
:third-a [op-t1 op-t2 op-t3]})
;; messy code to converts the above vector rows into maps
(def op-table (into {} (map (fn [[k v]] [k (zipmap b-values v)]) a-data)))
that can be generated from all the values of a/b so you're guaranteed to not miss anything
I don't think I follow that at all.
How can it be generated given that a map of {:a A, :b B, :action t}
is something that a user has to write, because the action t
is not magically known?
So far, the solutions by @lilactown and @quoll seem to be the most visually obvious - because a conceptual table is still represented as a visual table.
Also, found this, which is quite similar: https://github.com/semperos/rankle/blob/master/src/com/semperos/rankle/util.clj#L90-L120
My initial assertion was that I might be missing something in terms of representation - maybe tables aren't the only choice when it comes to clarity.
Hm... thinking literally literally... If the a/b pairs and corresponding operations are all known in advance, then, what if...
(def ab->op
{[:a1 :b1] :op-name1
[:a2 :b2] :op-name2
[:a3 :b3] :op-name3
[:a4 :b4] :op-name4
;;;
})
(defmulti exec-op
(fn [a b]
(ab->op [a b])))
(defmethod exec-op :op-name1
[{}]
...)
?