Fork me on GitHub
Chris K00:05:27

When I declare an atom variable in clojure, why do I have to deref it to get just the value? If I don't deref it, I can still see the value, but in like a more complex and verbose structure

Chris K00:05:48

BUt also when I'm using it inside the 'swap!' function, I don't deref I'm not sure why is that


swap! is a function, that takes a place, and puts a new content in it


so you need to pass a "place" for it to make sense


@foo generally (not just for atoms) takes a thing that can have a value and gets the value out of it

Breno Duque Estrada00:05:39

Atom is a data structure that holds the value "inside" them to control the consistency, concurrency, etc


atoms don't need to be "variables", they are first class data and it's easy to pass it / hold it etc. which is clumsier with variables

Breno Duque Estrada00:05:38

Swap! receives a function that will be executed inside the atom


it supplies a return value that replaces the content of the atom


it's doesn't lock or scope the atom per se

Chris K00:05:42

oh.. I see thxs I think I understand better


@sunchaesk for a more concrete example - when I do (def g (partial map f)) the var f is captured, and I implicitly use the value not the container itself


this leads to weird behavior - if I change f later, I need to remember to change g


there's an "opposite" to @, which is #', that lets me capture the var itself instead of the contents (def g (partial map #'f))


in fact, @#'foo is the same as foo if foo is a var


atoms are meant to be changed by application code at runtime, so it's easy to get the container, and an extra step to get what's inside - that's expected to happen as late as possible


vars are meant to be changed by a developer while working on one's code, so it's easy to get the contents, and an extra step to get the container


each one makes the "expected" use simpler

Chris K00:05:52

yeah that makes much mor sense now

Chris K00:05:05

thxs a lot


in fact, an atom is often in a var - though you can also use them first class as an arg to something that uses them / captures them


there's a great Rich Hickey talk about place oriented vs. value oriented programming


atom is explicitly meant to be a "place"


I thought it was supposed to represent an identity. the main difference being that places (on their own) don’t follow the epochal time model.


are java.util.HashMap or java.util.Date instances identities?


that’s a good point


i guess atom is really just supposed to be a reference type


with sane semantics


yeah - what I tried to get at was that its fundamental utility was to be a location, and the reason we prefer it over alternatives (which I didn't get into), is the sane behavior under concurrency


if I'm using identity or place here incorrectly I do want to know though


I guess it is a place, but the fact that it’s bundled with a recipe for change and perception is important (which distinguishes it from many other places)


but that's opt in - if you use reset! you get none of that safety, and only as much as you'd have with a var, or a thread safe mutable hash-map


thread safety is still important, but yea. I think I jumped the gun to say it wasn’t a place for some reason


if you have a document describing what makes something an identify vs. place I'd be interested, I'm not totally sure when I'd use the term identity


(outside eg. what kind of equality I expect to be used)


Hum... I don't think an identity is the same as a place. Like a place is just what it says, a place where you put things and grab things from.


identities don’t have to be places eg.

(def people-by-id
  {"1230u1203912" {:name "Bob"}
   "129u9cnu1209u12" {:name "Bob"}})


here, you have two people, with different identities, but their identity isn’t tied to a place


Ya, exactly. An identity is just an identifier for something. The only place where there's a connection is that a thing that changes cannot be identified by its form, since its form changes over time


well, i think the identity is the logical connection of values over time


It can be, but a place is also an identity


maybe it's sort of a trio: identity / place / value - your identities are value based, you can also have place based identities (standard object identity)


it’s nice to have a reification of that logical identity (an identifier)


The things in the place is a great way to identify things


well, any unique value can be used as an identifier


Well, not a great way


A bad way lol


But I mean, a place can be an indentifier for the things at that place


I nerd sniped myself into rewatching the value of values, it's a good talk


because places are unique. unfortunately, they can’t be copied which is annoying


I watched it earlier today during lunch


I don't really know if Clojure offers a better concept of identity for things that change form over time then a place?


you can use any* identifier that’s unique


I mean, if you call = on an atom, that's the only way to get true - is if it points to the same place


Right, atoms don't carry a stable Id with them, so they are effectively identified by place no?


yes, but they’re not the only* option


What are the others? Record and deftypes?


well, the other reference types


vars, refs, and atoms


agents, volatiles


Wouldn't all of their identity be their memory location? Aka, their place?


vars are usually looked at in terms of their owning structure and name


but yeah, the others are just identity based


but you can use a guid as an identifier in clojure


sure - not on the language level, but on the level of convention right?


and instead of getting its current value from memory (like atoms), you could get its current value from the disk or the network


I mean, without me creating my own. Are there any construct on Clojure who can model changing values whose identity is not based on a place?


they are usually looked up by the identity of their ns, (which is looked up by name) plus their name


though technically in bytecode they just get looked up by place, that's not the semantics we usually engage with


I also have no idea how refs work


since they use mvcc, I’m not sure whether that counts as having multiple places


Hum, I don't think the lookup matters as much as the equality.


I think it's more that mvcc coordinates the update of their contents, but the contents stay in one place


Are two vars equal because they have the same name?


@U0K064KQV when I use vars, I am explicitly asking for an ns by symbol, and I am explciitly looking for one name in that ns by symbol, if that goes out of sync (eg. because recreated the ns out from under me), I will experience that as a bug in my code and fix it by redoing the original lookup by recompiling


we very rarely even check var equality, they implicitly deref


Right, but that's a place, albeit not a memory address, but it's the same thing, it's just an address in the namespace map


@U0K064KQV, i’m not sure what you’re getting at. logically, identifiers don’t have to be places. I’m not sure if identifiers are only implemented as places in “clojure” (does using java libs count? what’s wrong with using a library?).


The way I see it it's like: {:a 10} and {:a 10} are the same thing because they have the same value. So no matter what place you put them in, they are the same thing


@U0K064KQV it's not a place, because it's looked up by tokens that we assign meanings to, not by location in memory


(in terms of program logic at least - of course in bytecode most of these things become places...)


and from a technical perspective, the jvm is allowed to move stuff around in memory. the OS is also allowed to move stuff around in memory without telling us too


But if you want to model something that changes like: {:a 10} and {:a 20} now what? If you say these are both the :amount-of-money-in-my-bank-account


So one way is to agree on a place where we will put the amount of money in my bank account


And now we can say, whatever is in that place must be the :amount-of-money-in-my-bank-account


or to arrange ot look it up by a known identifier


I'm not talking about how we find it, just about it's identity


in c we would be using places explicitly for everything but primitives, but we have other conventions in our language semantics that aren't place oriented


In this approach the identity is now the place it is in


as far as my program is concerned clojure.core/+ is an identity, despite the fact that reloading clojure.core could change its place


you can use places for identity, but you don’t have to.


and that identity is based on the symbols I use to look it up


Ya I know, I'm just saying that one way to create an identity for something that changes. The other way is to put a tag on the thing


But if the tag is not on the thing, then in my view it is still then that the place is the identity


not all places are identities


Ok, so maybe I've lost everyone :p


places can be identifiers, but they don’t have to be


Let's take atom again. It is the place of the atom that tells me what the value inside it refers too


(def my-money (atom 10))


my-money is a place


atoms are an example of using a place as an identity


but there are are also examples of places that aren’t identities


Ya ya agree

🍻 4

I guess my point is, I don't think there are any standard construct in Clojure that are basically a stable Id + a mutable section


Bundled together


The stable id is normally implicitly the place where we put the mutable section


there’s enough stuff in clojure, that I can’t say for sure


but I think vars might be a counter example to taht


like when do (def foo 42)


I think it might create an actual new place


It depends what you want to model? Like 42 is 42 because of its value, not because it is found in foo


i’m not talking about 42, I’m talking my.namespace/foo


But if foo is something that changes value over time, and 42 is supposed to be a foo and not the value 42, then foo would be the identity as well no?


foo’s value is currently 42, but it might change to -42


The symbol itself?


Or the var it points too?


the var it points to


Hum.. ya I thought the var was a bit similar to an atom, just not thread safe


I would say my.namespace/foo ’s identifier is my.namespace/foo, not whatever its memory address is


I know two symbols of same name and namespace arn't equal


I don't know how equality of vars work


Def does intern the var


So okay maybe you guys are right about Vars


> This means that, unless they have been unmap-ed, Var objects are stable references and need not be looked up every time. It also means that namespaces constitute a global environment in which, as described in Evaluation, the compiler attempts to resolve all free symbols as Vars.


also, outside of -128...127 for integral types, numbers are never places, only values


I guess you could consider an interned var to be a combination of a stable id, the symbol's namespace+name and the possibility changing value contained in the Var


Given a var, can you find it's symbol though?


I think that's my criteria for if identity is a place or not 😝. If you take the thing and move it somewhere else, can you still know what's its identity? If you can't, then the place was acting as the identity, and having lost the knowledge of where the thing was, so have you lost its identity. If you can, then the identity is within the thing itself, and not based on where it was.


given a var, you can find its symbol


=> (.sym #'+)


Okay, did not know that. So I guess vars carry their identity on them


So they are not place oriented :p


not only that - standard idiomatic language constructs find them by that name


Ya, but I honestly don't really see that as being different. If I said, ok, this function will always be at memory location xyz. Or, okay this function will always be at key xyz in namespace map


the difference is that one of those is the normal path for finding a var, and the other is a rare special case


It still feels like we're doing place oriented programming. Because now everything relies on this implicit agreement and knowledge of where things are going to be and what each thing at each place is supposed to represent


And if someone messes up, and doesn't put the right thing in the right place, everything breaks


i agree that vars are still place oriented. “any time new values overwrite old values, you’re doing PLOP”.


but hopefully, your whole program isn’t all about places


True, also I think places that are at least consistent throughout the whole execution are much less brittle and easier to deal with. And most idiomatic Clojure never changes the value of a Var after the first time it is defined


until you ask it to (ns-unmap) use a tool that does that for you (ns/refresh)


clojure has "two sets of rule" - for dev vs. runtime, and I think that's an important quality


one of those rules are a very strong convention and not rules per se, but luckily the conventions are strong enough

💯 4

Going by Are We There Yet, a name for something that changes in atomic successions and is perceivable by others without stopping anyone is what I'd call an identity. And in order to make something (with computers) that represents an identity, then we need values. An identity is a label we (humans) give to a sequence of causally-related values. Which means values are the more primitive thing. Whereas with a mutable datastructure, all you have is a place, it's neither an identity (in the sense described above), nor a value.


from, > Objects complect state, identity, and value. while we would like to represent identities using references that obey the epochal time model, objects can still be used to represent identities (although this is ill advised).


and just because you can use an atom to represent an identity. you could also misuse it to represent something besides an identity. so a construct that follows the epochal time model does not imply that the construct must represent an identity

💯 4
Chris K00:05:10

Nice I will check this out

ryan echternacht01:05:22

@sunchaesk that talk is what brought me to clojure. It’s REALLY good

Chris K05:05:54

yeah I've heard others saying that this talk is great. I'll make sure to check it out


If you prefer reading to watching/listening, transcripts of many talks available here. Also good for searching for key words later if you want to find something you remember only one word or two of:

Chris K08:05:58

Thxs for the transcript @andy.fingerhut

Chris K08:05:18

I also had a question about functional programming while watching the talk by Rich Hickey Value of Values He said that one thing people are pleased about is that you can share the values freely without having to worry I get the part that talks about how you don't have to worry because the value is immutable, but I don't understand why it is only functional programming that allows you to share data freely and not same between OOP and FP


Do you mean why does OOP not use immutables, or what is it about OOP that makes sharing hard compared to FP, or something else


(this is a tangent I'm about to get on, not an answer to your question) Personally, I don't think mutability vs immutability should be baked into the definition of OOP -- it mostly is, but to me its mutable as a historical detail, not because it has to be. To me, a language with data and functions tightly bundled, and all the other aspects of OOP, but where each function returned a new, updated object, instead of updating some living piece of memory somewhere, would still be OOP -- it is the object that's important (and fortunately I could maybe even argue that in any flame war this sparks, since its right in the name). But of course, then we're just talking about language, instead of the ideas behind them, and what ideas the language should refer to -- and when people say OOP, they are referring to programming built on mutation. And why wouldn't they? I know of no real immutable OOP, although I've done a lot of experimentation there myself


Anyways, in my personal language, imperative programming is what I call a language that expresses its change as side effects, and declarative programming one that expresses it as a fresh return value of some data (thereby having the data only represent, or describe, what will become a change), and they're a much lower level property than being, say, 'OOP'

Chris K09:05:04

Right yeah I think what you said is more accurate definition of these paradigms


@zdot101 I'd suggest that even in Clojure (or more extreme, even in scheme or forth) functions and data are tightly coupled - it's just that strategically, less work is put into proliferating data types and more into proliferating the number of functions on the small set of data types

👍 4

Ah, but I said tightly bundled . Granted, I'm trying to think now of a more rigorous definition to differentiate the two, but I think the main difference is I was referring to was not their coupling (although bundling itself couples), but to the fact that they are an atomic unit; when you deal with objects, you don't get them separate. Of course, as you dig into that, it gets trickier -- being 'together' has less meaning as you zoom in and get more rigorous, and a more fitting way of explaining that sort of thing is that they are still individual things, but with a different set of relationships drawn between them than, say, functions and data in Clojure.


I think there’s a fair argument to be made that Erlang is an example of an immutable OOP.


(If anyone says “Scala,” I’m gonna flip this table.)


This is really interesting. It annoys me to no end (and I really believe it harms the chances of getting anyone to understand) when people use the terms OOP and, equally, FP in daily use.




Good example is anyone, ever , saying “look, in FP we have map/reduce and for loops are bad”. It’s just bizarre to think that was ever a real point. Luckily, today all languages have it either in the language or via libraries so we’re past that, but still.


And... for people writing testable code, doing a larger and larger part of their code as pure functions have been standard thinking in corporate Java land for a long time now.


So... there are lots of interesting discussions to be had, but not hidden behind “FP” and “OOP”.


Last part of the rant - I really like Eric Normands podcasts (hmm, long time now?). He is good at the nuances and degrees but also at times falls for the easy trap of saying “ it in OOP it’s like this”.

Kris C13:05:09

👋 I’m here! What’d I miss?


Chris K stole your name, but is dyslexic


I think that's it cap


Is the clojre.core/inst? simply checking if its argument is an instance of a Java object (assuming I am on the JVM). Just wanted to confirm my assumption. I looked at the source code but was no wiser 😞


from my reading it checks to see if the argument satisfies Inst a protocol. and (-> Inst :impls keys) lists java.util.Date and java.time.Instant as two implementers of this protocol


And others may choose to extend the Inst protocol to other types in their programs, or for time-related types they create.


I am not clear if all java objects satisfy the Inst protocol. If it is just specific Java classes (or other types) I guess I can test them as I make use of them in applications I write. But then curious as to why any type would implement the Inst protocol if its quite selective.


the protocol doesn't care, and it's not generically possible to say "what are all the implementors of this protocol?"


if you're checking for specific java classes, use (instance? java.util.Date x)


You can check all of the JVM classes the implement the Inst protocol at this moment using the technique that dpsutton showed, true?

Alex Miller (Clojure team)16:05:50

this doesn't cover metadata protocol extensions


dunno what that technique was


@jr0cket inst? seems more useful for predicates with clojure.spec


(-> Inst :impls keys) from several mins ago


(it is antithetical to protocols to have to check a type, then use the protocol)


inst? doesn't tell you anything about what you can do with the object, except call inst-ms on it


I am not saying you want to dig into the internals that expression uses in lots of production code. Just if you are curious and doing some poking around/debugging at the REPL, wanting to know what is going on.


I am looking at predicates with clojure.spec right now, but it the value of a type an instance is still to click. I assume its so that you can satisfy the predicte, it seems highly generic though


but most date/time needs in app code are broader than grabbing unix epoch millis


Ah, i missed the (-> Inst :impls keys) code from dpsutton, as it wasnt highlighted... 🙂


its very useful, thanks


that doesn't tell you reifies or things that directly extend the protocol


just out-of-band stuff like using extend-*


(it will not show reify / deftype / defrecord extensions of that protocol)


understood. It is at best a partial list of JVM classes that implement the protocol.


it is a complete list of out-of-band extensions


which may be supertypes of compatible classes


(also undocumented and may go away with a version change)


(like if you extended a protocol to CharSequence, you'd automatically get String)


I have a much better context as to where this fits in (although still need some hammock time around the why aspect). Thanks all.


generally, i do not recommend using inst? like this: (if (inst? x) then else)


there is a spec generator hooked into the inst? predicate, and it returns a generator of java.util.Dates


clj -A:convenient
Clojure 1.10.2-alpha1
user=> (require '[clojure.spec.alpha :as s])
user=> (require '[clojure.spec.gen.alpha :as gen])
user=> (s/gen inst?)
#clojure.test.check.generators.Generator{:gen #object[clojure.test.check.generators$such_that$fn__558 0x78d6447a "clojure.test.check.generators$such_that$fn__558@78d6447a"]}
user=> (gen/generate *1)
#inst "1970-01-03T09:07:10.724-00:00"
user=> (class *1)

Wilson Velez20:05:12

which is the easiest way to format a js/Date?

Wilson Velez20:05:30

I did it using moment.js (.format (moment %) date-format)


I’d avoid moment.js since its API is mutable. for a js lib I prefer date-fns, but there might be good cljs libs too (haven’t had chance to try them out yet)


there are also a few functions in goog DateTime, but not a proper formatter

Wilson Velez14:05:00

thanks @UPH6EL9DH and @U051SS2EU, I’ll take a look

Wilson Velez20:05:30

I did it using moment.js (.format (moment %) date-format)


Hi I have this vector

[{:key "document_env", :value "teste"} {:key "document_env2", :value "teste2"}]
How can I transform into a map like this:
{"document_env" "teste" "document_env2""teste2"}


There are multiple ways to do it, but this is one:

user=> (def d1 [{:key "document_env", :value "teste"} {:key "document_env2", :value "teste2"}])
user=> (into {} (map (juxt :key :value) d1))
{"document_env" "teste", "document_env2" "teste2"}


This is another:

user=> (into {} (for [m d1] [(:key m) (:value m)]))
{"document_env" "teste", "document_env2" "teste2"}


Thanks a lot @andy.fingerhut! Didn’t know this function: juxt 🙂


NP. juxt is certainly not necessary to achieve the result, of course, but sometimes nice to see multiple ways to do the same thing.