Fork me on GitHub

so if I understand correctly I have to do something like that :

(s/def ::r8 #{:A :B :C :D :E :F :H :L :HLi})
(s/def ::r16a #{:AF :BC :DE :HL})
(s/def ::ld (s/or :r8 (s/tuple ::r8 ::r8)
                  :r16 (s/tuple ::r16a ::r16a)))

(s/def ::instruction (s/or :ld (s/keys :req [::ld])
                           :EI #{:EI}
                           :NOP #{:NOP}))

(s/conform ::instruction {::ld [:AF :AF]})
;; => [:ld #:gbasm.core{:ld [:r16 [:AF :AF]]}]

(s/conform ::instruction :NOP)
;; => [:NOP :NOP]
Then for the matching I will just have to check the second operand right which will contain the informations I need right ?


@dimitri.tavan Unfortunatly I’m not an expert, so there may be a better way. But checking the conform result sounds right to me if you’re looking to do some control flow. Maybe paired with a multimethod?

Alper Cugun10:12:45

From #braveandtrue:

You can create an instance of this record in three ways:
Is this intentional? Is there a common practice of linting this stuff out?

Lennart Buit11:12:09

defrecords create (java) classes, so one of the constructors (RecordName. …) is actually the interop constructor. It is common practice to not use that (

Alper Cugun12:12:25

That’s cool but why is the -> duplicated?

Lennart Buit12:12:36

I don’t know the exact rationale of inclusion of the ->FooBar constructor, my guess would be that an arrow is ‘more common’ in clojure than a dot


What do you mean duplicated?


I think Lisps have a history of using -> to mean "to". So you'll see things like ->string instead of toString, or a->b instead of aToB . So when creating a record, the constructor function is called ->record which should be read toRecord


You should use ->record or map->record only, the second one is useful if you already have a map.

Iwo Herka11:12:35

What is the preferred way of documenting types of arguments and return value from functions? Docstring?


I'd say yes. It depends how formal you want to be. Doc-string is good for loosely hinting at the correct types, which is often good enough. But clojure Spec is what you would use for formal descriptions of the input and output types when you really want it to be specific and formal. The Spec will show up when you call doc on the function as well.

Lennart Buit11:12:31

You can spec them if you want to

Iwo Herka11:12:33

I'm only asking about informing readers of the code, not type safety. I'm aware of typed clojure.

Lennart Buit11:12:17

(s/fdef inc
  :args (s/cat :x int?)
  :ret  int?)

Lennart Buit11:12:35

it (at least in cursive) shows up in the doc popup

Iwo Herka11:12:19

That's cool, thanks.

Iwo Herka11:12:33

Will fdef scream at me when violating spec?

Lennart Buit11:12:57

only when instrumented, you have to ‘opt in’ to runtime spec checking

Lennart Buit11:12:03

if you want full instrumentation checking :args , :fn and :ret, you’ll have to include something like orchestra ( The default instrument only checks :args


Yes and no, stest/check does full instrumentation, without the need for orchestra.


how do I make map keys in spec-tools data-specs optional by default? I tried

(ns spec-tools.swagger.spec3
  (:require [clojure.spec.alpha :as s]
   [spec-tools.core :as st]
   [ :as ds]))

(s/def ::request-body
    {:keys-spec ds/opt 
     :name ::request-body
     :spec {:description string?
            :content string?
            :required boolean?}}))
but I get an error for
(s/explain ::request-body {:description "three" :ins   "path"})
class spec_tools.data_spec.OptionalKey cannot be cast to class clojure.lang.IFn


@U055NJ5CC It worked. Thanks for the quick reply


"Programming Clojure, 3rd edition". Anyone have an opinion on this book?

Alex Miller (Clojure team)23:12:55

It’s amazing

😆 20

I think it's a good book.


I have both the 2nd and 3rd edition. The 3rd ed includes clojure.spec and the CLI/`deps.edn` stuff so it's nice and up-to-date @glfinn83

👍 4
Akshay C. Gollapalli22:12:26

Hi all, new to the chat, have been playing around with clojure for a while.

Akshay C. Gollapalli22:12:46

Probably a question I should already know the answer to, but when you evaluate a function again, do it's component functions get re-evaluated as well?


No it doesn't


But since symbols point to vars, and vars are mutable, they don't have to be to automatically get updated to pointing to the newly def code


(def a "hello")
; => "hello"
(def a "hi")
; => "hi"

Akshay C. Gollapalli22:12:57

And is there a limit to how deep that goes?


if your function calls other functions resolved by their symbols, they are (with specific exceptions) resolved again on each call, so your function does the right thing if they are redefined


I might be misunderstanding the question though


if your function recieves other functions as arguments (eg. use of partial with a passed function arg) this obviously can't happen


Perhaps you are asking about an inner function like in (defn foo [s] (map #(inc %) s)) ? As in, is the #(inc %) recompiled every time the function foo is called? If so, the answer is no, it is not


@acgollapalli when you write "evaluate a function again" do you mean redefine, or run again?


If you define a function using defn or fn that contains no invocations of macros, then the only code that is executed while compiling that function is inside of the Clojure compiler. No other functions within the definition being compiled are called.

Akshay C. Gollapalli22:12:37

Like lets say I have an atom "a" and fn "b" contains atom "a", if I call a function that includes "b" as one of its arguments, then does b get run again so that we can get the modified version of "a"?

Akshay C. Gollapalli22:12:25

@andy.fingerhut I think that answers my question.


do you mean atom as in clojure.core/atom the mutable state container?


If you define a function that invokes one or more macros, the code within those macro definitions is executed while the compiler is running. invoked by the compiler. You might not be worried about that case right now, but wanted to mention it.