Fork me on GitHub

Does case not support values from other namespaces? This snippet is printing out thing2 :

(ns some-ns)

(def value 12)

(ns my-ns
  (:require [some-ns :as sn]))

(case 12
  sn/value "thing1"
  12 "thing2"


Must be a literal


You are checking if 12 is the same as the literal symbol sn/value


That’s cool. So it’s not just calling = for me?


It’s easy enough to fix, but the behavior is surprising. Thank you.


You can think of case as treating the tests as quoted

Alex Miller (Clojure team)01:03:47

Just as a general piece of advice, if you see something surprising, your first step should be (doc case), which explains all this


Yeah, I did end up looking at the docs and found this as well. I was just baffled that I’ve been using Clojure for this long and apparently have never run into this before. But I think most of the time when I’m using case it’s for matching on keywords and most of the other times I just stick to cond


It is often surprising when Clojure's behavior on a construct differs from an apparently "identical" construct in a different language. for is probably the most common difference that trips people up. case is on the list too tho'...


Yeah, that’s true. I assume the rationale for case behaving like this is the “constant dispatch time” as mentioned in the docs, no? Or is there another reason for it?


Compile-time constant, yes.

Alex Miller (Clojure team)02:03:36

yes, Clojure does a lot of work to restructure these cases into a TABLESWITCH bytecode on the jvm which is constant time lookup (which requires constants)

👍 8

I seem to recall a 2x2 grid of the four clojure state options (atom, ref, agent, var) in the official docs, does anyone remember where it’s located?

Alex Miller (Clojure team)15:03:34

I don't think that's in the reference docs

Alex Miller (Clojure team)15:03:37

I do know what you're talking about - the axes are coordinated/uncoordinated and sync/async

Alex Miller (Clojure team)15:03:56

sync/uncoord = var, atom


Need some advice. I have 2 very long-running processes (30 min - 1 hour and 2-4 days). I am currently using callbacks, but I am wondering if there's a better way, considering computing resource usage. Anyone have any experience with this and can give me feedback? Thanks. I should note that I am running this code in Datomic Cloud, but it is not related to database processes.


Using callbacks how? (It's hard for me to suggest you an alternative, because neither what you're doing nor the issue with it are clear to me)


The long-running processes are using callbacks to return the result to the API consumer.


Why not return the values normally, as the result of calling a function ?


The API consumer is customer-facing and needs to reply with "pending" or something like that before returning the actual result. I am thinking of using channels for this.


I would use a database for that. Make yourself a "jobs" or "tasks" table with state and result columns, and query that.


Good idea! Thanks @U06GS6P1N


I think I saw it in cemerick's oreilly book


What is the difference between .File. and ??


second is a function so you can use in the context of map for example

👍 4
Alex Miller (Clojure team)16:03:42

file is a coercion function built on an open protocol

👍 4
Alex Miller (Clojure team)16:03:50

so that includes Strings (paths), Files, URLs, URIs

Alex Miller (Clojure team)16:03:09

and whatever else you install (should be extended to the newer Path too)


I changed the former to the latter and it broke our build pipeline. When I played with it in the repl the results seemed the same to me so I am curious as to what happened.


I’m not 100% familiar with the whole system. But changing the former to the latter caused the CI build to fail. But changing it back caused it to work.


I thought they had the same result

Alex Miller (Clojure team)16:03:55

(jio/file "string") literally just calls (File. "string")

Alex Miller (Clojure team)17:03:21

they differ in behavior on nil

Alex Miller (Clojure team)17:03:33

(File throws, file returns nil)

Alex Miller (Clojure team)17:03:13

I assume when CI failed, it probably produced some information


Yea I get file not found etc

Alex Miller (Clojure team)17:03:44

dunno, doesn't make sense to me


That’s why I came here after getting it working again. Because to me it should be the same behaviour.

Alex Miller (Clojure team)17:03:09

without more info, not sure I can help


Seems like the issue was caused by code I was unaware of in the deployment/testing process. Asynchronous file creation/deletion will do it :)

Eduardo Mata16:03:21

I noticed the use of ! in some source codes. Why is this meant for? I know is for documentation purposes but I guess I have heard few opinions such as: when we are interacting with Databases or external services. Is that true?


I use it for any public function that performs a side-effect


historically it means "this has a side effect", but the usage is inconsistent


lacking ! doesn't mean it's pure, but having it is a pretty good sign something is impure


Usually anything you want to tag with "tread with caution" is a good candidate.


see also io! - meant to be called inside code that isn't safe to run in a transaction (AKA impure / stateful code)


user=> (doc io!)
([& body])
  If an io! block occurs in a transaction, throws an
  IllegalStateException, else runs body in an implicit do. If the
  first expression in body is a literal string, will use that as the
  exception message.


I think it was supposed to be used with clojure's mutable-like things. Some people extend it to external state also though.


if you write to a file inside a ref transaction, you are asking for a bad time, io! can help prevent that


same for external non-idempotent API calls


but then again, in practice we don't use refs as much as was originally imagined, and swap! doesn't error on io!, so here we are

Chris Lester20:03:18

Does anyone know how to spec a map that looks like { : key { :<uuid value> { :a "val" :c "val" :d "val"} :<uuid_n> {...other similar maps}}}? Not sure how to get spec to validate/generate a dynamic key with the value as a map.

Alex Miller (Clojure team)20:03:06

(s/map-of keyword? (s/map-of keyword (s/map-of keyword? string?)))

Chris Lester20:03:51

Thx alex, that works. Had only seen s/coll-of used in any spec guides and hadn't run across s/map-of (or s/vector-of, etc).

Chris Lester20:03:07

nvm, found it in the main guide lol. Missed it.