This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-08-30
Channels
- # adventofcode (4)
- # aleph (1)
- # announcements (6)
- # babashka (11)
- # beginners (63)
- # calva (73)
- # clj-kondo (9)
- # clj-on-windows (20)
- # cljdoc (8)
- # cljsrn (4)
- # clojure (48)
- # clojure-europe (20)
- # clojure-italy (1)
- # clojure-nl (11)
- # clojure-spec (11)
- # clojure-uk (3)
- # clojurescript (32)
- # cloverage (1)
- # conjure (1)
- # cryogen (5)
- # datomic (83)
- # fulcro (28)
- # graphql (23)
- # gratitude (4)
- # helix (15)
- # honeysql (4)
- # improve-getting-started (14)
- # introduce-yourself (3)
- # jackdaw (5)
- # kaocha (11)
- # leiningen (1)
- # malli (1)
- # meander (5)
- # off-topic (18)
- # pathom (17)
- # pedestal (6)
- # polylith (15)
- # practicalli (1)
- # quil (2)
- # reitit (4)
- # releases (6)
- # shadow-cljs (38)
- # sql (20)
- # testing (6)
- # timbre (5)
- # tools-deps (11)
- # vim (2)
What do people do about having records conform to specs? Since it's generally good practice to use namespaced keywords with specs, but records don't support namespaced keywords on the enumerated fields, the only ways I've seen is either to make a less extensible spec by not using namespaced keywords, or to just not spec the records and prevent them from crossing interface boundaries.
I think those are the big ones
Fair enough. Sometimes I wish I could just define namespaced record fields, but I can see why that'd be a challenge.
@suskeyhose What drives you to use records rather than hash maps?
Performance. I write game engines in my spare time and things like field access time from entities can make the difference between being able to support hundreds of objects at 60 fps to being able to support thousands, which entirely changes the types of games you can make.
And in those sorts of systems, spec brings a lot of value since many of these systems have complex calling contracts that must be upheld and instrumentation and generative testing aid a lot in tracking down errors when you're able to encode those contracts via spec.
Ah, interesting niche. Yes, I can see performance being a good driver for that decision.
I'll also say that yes, game engines is very niche for Clojure development, and for someone who wants to make a very performance-sensitive game they'll have better luck with Unity's new systems, or writing something from scratch in Rust or C++, I prefer Clojure because it makes it easy to write my game code, and I don't make highly performance-sensitive games, but at an engine level I'd like to be able to make as few concessions as possible so that the overhead of being in Clojure takes away the least creative freedom.
And since I'm an engine developer by education and desire, I'm perfectly willing to take on lots of complexity in the engine if I can make writing something atop it simple and unconstrained.
Couldn’t you write a one-way conformer for records to be spec’d? Like (def ->map (s/conformer #(into {} %)))
, then use something like (s/and #(instance? MyRecord %) ->map (s/keys :req-un [….]))
The problem I have with that is then I have to write code that doesn't follow the spec, but follows an implementation detail for performance. Ideally I'd still be able to do the keyword-based lookup.