Fork me on GitHub
clojure beginner03:12:36

defrecord getBasis behaves differently when used to look up record fields

clojure beginner03:12:49

(defrecord Person [name age company]) (def p1 {:name "foo", :age 27, :company :bar}) (map #(% p1) (keys p1)) ("foo" 27 :bar)user=> (map #(% p1) (Person/getBasis)) (nil nil nil nil)

clojure beginner03:12:08

user=> (map #(class %) (Person/getBasis)) (clojure.lang.Symbol clojure.lang.Symbol clojure.lang.Symbol clojure.lang.Symbol)

clojure beginner03:12:31

getBasis seems to return the symbol but the record lookup doesnt work

clojure beginner03:12:43

I dont wish to use keys on the record instance since the instance might be missing some fields in the record


p1 has keywords for the keys, not symbols.


Also @gayathrik if you're really just getting started, it's worth noting that everyone is in this channel, but #beginners is specifically for a) folks who are just starting out and b) the folks who've opted in to helping beginners, so it's usually the better place for "just getting started" questions...

clojure beginner04:12:33

ok thanks. will post in beginner channel.


I may be bike-shedding here but isn’t the term synchronized instead of serialized? I’m not a native English speaker, so maybe my understanding of serialized is wrong. I associate it more with writing data over a wire or to disk.


it's serialized in the same sense as per I believe


to me that makes perfect sense


ah, that makes sense


serialize: to ensure it happens in the right order?

Alex Miller (Clojure team)16:12:40

synchronization is one way to achieve serialization

Alex Miller (Clojure team)16:12:53

but is the less important aspect


thanks for adapting the name, makes more sense now

👍 4

When I start REBL up, I'm getting an error WARNING: Loading FXML document with JavaFX API of version 8.0.141 by JavaFX runtime of version 8.0.60 - I got a similar error on my other machine which is using a different JDK. Is there a specific JDK I need to be running, or is there a way to load the correct version of JavaFX from my deps.edn so that I don't have to deal with changing JDKs?


@shaun-mahood I ran it without warnings on Windows 10, Leiningen 2.7.1, Java 8.


I haven't, yet, tried it on my Mac, but that's also currently running Java 8.


Got the warning on both mac and linux - linux is on openjdk and the mac has a warning when starting cursive but works otherwise. Might just have to install oracle jdk on the linux one I guess.


Until whatever date you have to start paying Oracle to use it? 😉


Isn't Oracle Java 8 always going to be under the old no-$$ license?


Yeah, although you'll stop getting (security) updates in January (unless you pay for more support, or you're only using it for non-commercial use, based on the wording on Oracle's Java SE support pages). Very strange that they'll offer free updates for Personal Use for a further year... I mean, how many people really use Java for purely non-commercial stuff?


This reminds me, I need to open a JIRA at work to switch us to a supported OpenJDK 8 or move to OpenJDK 11 and get our legacy stuff tested on it!


REBL works perfectly with Oracle Java and no warnings.


is there a sane option to host a public Clojure REPL/evaluator online without safety risks? I think I’m going to try self-hosted CLJS, but if there are JVM options I’d like to know. There is the try-clojure repo, but maybe there are others options right now?


I used clojail back in the day. Depending on the needs, if I had to do something like that today, I'd look at using kubernetes and spinning up a separate instance for each repl.


Certainly has performance implications, but a much nicer security profile.


anecdotally, clojurebot ended up needing to blacklist a lot of things, including anything that creates a var in a namespace


that's just for security, for correctness / trolling related concerns it resets the whole sandbox on a fifteen minute cycle


@noisesmith is this code available?


I think what is run in practice might be stricter than what's configured out of the box with that repo

Alex Miller (Clojure team)20:12:04

(might be newer forks available)


I'm trying to figure out how nav works and not having much luck. From reading the docstring, my assumption was that if I call (clojure.datafy/nav [:a :b :c] nil 0) it should return :a, but it seems like no matter what I try it always returns whatever I pass to v (0 in this case). Am I totally out to lunch with what nav is for, or am I just calling the function wrong?


You are calling it wrong -- it's certainly non-obvious so I sympathize.


The args are coll k v -- in other words, it assumes you are calling it with the already selected collection element (`v`).


I am not certain how REBL calls nav for vectors but I would expect it to either be (d/nav [:a :b :c] 0 :a) or (d/nav [:a :b :c] nil :a)


Certainly for hash maps, it calls (d/nav {:a 1 :b 2 :c 3} :a 1) (and then with :b 2 and then with :c 3).

Alex Miller (Clojure team)21:12:21

I believe it would be like (d/nav [:a :b :c] 0 :a) but don’t have it running atm to check


I'm trying to understand how nav is used. So I should still use find/nth? But nav will potentially have side effects for that pair?

Alex Miller (Clojure team)21:12:20

speaking from rebl, when you have something on the left, then you “select” it, you would nav (with left data and selected key/value), then datafy to get the new focused data

Alex Miller (Clojure team)21:12:10

(->> val (datafy/nav coll key) datafy/datafy)


Yeah, what he said 🙂


is this why “trivial” examples like vectors/maps of scalar values don’t really show what makes datafy/nav useful


my naive understanding of nav rationale is that it enables lazy navigation through data structures, that may or not be “realized” before you nav them. Is there a better rationale or explanation somewhere


java.jdbc produces simple vectors of maps today -- but the new namespace has versions of the query functions that are "compatible" with datafy (i.e., they include metadata with clojure.core.protocols/datafy) which, if you call datafy on them, produce data representations with clojure.core.protocols/nav metadata on them, to do lazy fetching of related data if you call nav on them.

👍 4

thanks, reading your prototype code for this did help my understanding of datafy/nav


Ok, let me test my understading. If I'm in the repl and call (datafy/nav [:a :b [:c [:d :e]]] 0 [:c [:d :e]]) and get the result [:c [:d :e]], then I could call (datafy/datafy *1) and get the datafied result (which I can then nav over again). I've been trying to test if it's working by checking with (meta *1) and keep getting nil, so I might be doing that part wrong as well.


this is kinda what I’m getting at when I say a simplistic example doesn’t really expose the motivation for datafy/nav, i.e. would there ever be a reason to datafy something that’s already data like [:c [:d :e]]? It’s already data


Why would you pass [:c [:d :e]] here (datafy/nav [:a :b [:c [:d :e]]] 0 [:c [:d :e]])?


Based on coll k v, v should be :a (or k should be 2)


I see the motivation in the java.jdbc datafy/nav usage: it’s adorning rows/result sets with info/metadata on how to navigate to related data


Also, you won't get any metadata unless something is adding that metadata.


datafy of a pure Clojure data structure will produce the exact same pure Clojure data structure.


nav of a pure Clojure value will produce that exact same pure Clojure value.


These two functions only "do something" if you pass them something that satisfies the two underlying protocols -- which may well be provided through metadata or a protocol extension.


But the defaults for Object (and nil in the case of Datafiable) do pretty much nothing


seems like you could do some cool discoverable RESTful stuff with datafy/nav


I'd love to hook a hypermedia api up to a clever caching logic engine.


Ok, for some reason I thought that the clojure data structures had support for nav already and just tied myself in knots trying to understand how it worked on the core data structures. I think I am getting a bit of a better idea of how it works , though I'm still not sure what the docstring means when it says e.g. for sequences (pass nil). I think I'm going to go build something against JDBC to figure it out.


For associative collections, you have a natural key to pass. For sequences, you do not.


So if I had used a list instead of a vector then I would call it with coll nil v, right?


The key thing that may be missing from your thinking about this is that you start with an arbitrary "thing" and you call datafy on it to get a "data representation" -- which may include pieces that satisfy the Navigable protocol -- and then you can call nav and datafy on parts of that to navigate through it all.


But Clojure data structures are already data and they are already navigable.


When you datafy an IRef you are implicitly deref'ing it to get at the data representation, for example.


Yeah, I had this idea that nav was kind of a universal navigation function - so I thought that I would be able to call (nav map key) and (nav vector index) and get that data back for further navigation, but then also be able to call (nav database row) and get the datafied row which you built the support for, like an arbitrary zipper or something like that.


I guess I need to think of it more like the ability to deref things arbitrarily once they have support for it. Much clearer (assuming I'm not wrong about that part 🙂 )


With all this nav and datafy going on, isn’t it a shortcoming that Strings and Longs don’t accept metadata?


I was very confused by nav until I realized that it only has a purpose when an element of a coll can itself be expanded by "going down a level". The browser would first enumerate the elements of a collection as usual, without calling nav. Then when the UI button "go right" is clicked, nav is called to expand the element and evaluate it as a coll (if possible), starting the process over again. This is my understanding anyway. So the args to nav are the coll, key and element that have already been enumerated.


@shaun-mahood If you start by calling datafy, and then calling nav, you would be correct.

👍 4

But for Clojure hash map X with key k and associated value v, (datafy X) is just X by definition and (-> X (datafy) (nav k v)) is just v by definition.


What java.jdbc.datafy does is change the behavior for the hash maps that are rows. They become "special" insofar as if you call datafy on them, they become hash maps that know how to lazily fetch related rows (based on some columns being treated as foreign keys).


Again, tho', having datafyd a row, it isn't treated as anything other than data unless you call nav on it.


I guess you could also implement pagination pretty well with this - datafy the first result set so that you can nav to the next (pretty sure Stu mentioned that in the talk so I guess I don't get credit for thinking of it)


Why does nav take a v for associatives? Wouldn't it already be known?


Because nav sits on top of the underlying associative lookup. You do (get coll k) first to get v, and then you call nav on coll, passing k and v to allow it to return an updated value.


Because you go from "thing" to "data representation" of "thing" (via datafy), and then you can do the simple associative lookup in the data representation, not the original thing, and then you use nav to get back to the relevant equivalent part of the "thing", and then you datafy that again to get pure data.

🙏 12
😮 4