Fork me on GitHub
#clojure
<
2020-03-25
>
stephenmhopper01:03:34

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"
  "default")

hiredman01:03:36

Must be a literal

hiredman01:03:04

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

stephenmhopper01:03:23

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

stephenmhopper01:03:46

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

hiredman01:03:19

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

stephenmhopper01:03:33

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

seancorfield01:03:24

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'...

stephenmhopper02:03:15

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?

seancorfield02:03:05

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
arohner15:03:16

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

hadils15:03:15

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.

val_waeselynck19:03:13

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)

hadils20:03:22

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

val_waeselynck00:03:03

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

hadils00:03:55

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.

val_waeselynck00:03:25

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

hadils00:03:50

Good idea! Thanks @U06GS6P1N

j0ni16:03:28

I think I saw it in cemerick's oreilly book

grounded_sage16:03:07

What is the difference between .File. and ??

delaguardo16:03:15

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)

grounded_sage16:03:11

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.

grounded_sage16:03:34

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.

grounded_sage16:03:45

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

grounded_sage17:03:20

Yea I get file not found etc

Alex Miller (Clojure team)17:03:44

dunno, doesn't make sense to me

grounded_sage17:03:44

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

grounded_sage10:03:10

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?

grounded_sage16:03:26

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

noisesmith16:03:36

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

noisesmith16:03:03

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

hindol16:03:12

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

noisesmith16:03:44

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

noisesmith16:03:44

user=> (doc io!)
-------------------------
clojure.core/io!
([& body])
Macro
  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.
nil

dominicm17:03:55

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

noisesmith17:03:55

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

noisesmith17:03:10

same for external non-idempotent API calls

noisesmith17:03:03

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.