Skip to content

Instantly share code, notes, and snippets.

@olange
Last active November 7, 2022 17:37
Show Gist options
  • Save olange/6434191 to your computer and use it in GitHub Desktop.
Save olange/6434191 to your computer and use it in GitHub Desktop.
Answer to @puredanger's tweet: about the «trouble» I had first using type hints and records in Clojure.
(ns accounting.factory.transaction
(:require [accounting.model.transaction :as transaction]
[accounting.model.document :as document]
[accounting.model.movement :as movement])
(:import [accounting.model.transaction Transaction]
[accounting.model.document Document]
[org.joda.time LocalDate]))
(defn create-exchange-difference
^Transaction
[^LocalDate date amount-bc debit credit description]
(transaction/create date (.id (document/exchange-difference))
(movement/EXD-D debit amount-bc description)
(movement/EXD-C credit amount-bc description)))
(ns accounting.model.document)
(defrecord Document
[id description])
(defn opening-balance
^Document []
(->Document ::OPENING-BALANCE "(Opening Balance Sheet)"))
(defn exchange-difference
^Document []
(->Document ::EXCHANGE-DIFFERENCE
"(Exchange differences · Calculated by the accounting system)"))
(ns accounting.model.movement
(:require [...])
(:import (accounting.model.amount_with_currency AmountWithCurrency)
(accounting.model.forex ExchangeRate)))
(defrecord Movement
[effect
specialty
account
^AmountWithCurrency amount-ac
^ExchangeRate fx-rate
^AmountWithCurrency amount-bc
description])
[...]
(defn- create-exchange-difference
^Movement
[effect account amount-bc description]
(effect/assert-valid-effect effect)
(amountWC/assert-valid-amount amount-bc)
(assert/not-nil account)
(assert/not-nil description)
(->Movement effect ::specialty/exchange-difference
account nil nil amount-bc description))
(def EXD-C
(partial create-exchange-difference ::effect/crediting))
(def EXD-D
(partial create-exchange-difference ::effect/debiting))
(ns accounting.model.transaction
(:require [...])
(:import (accounting.model.amount_with_currency AmountWithCurrency)
(accounting.model.document Document)
(accounting.model.movement Movement)
(org.joda.time LocalDate)))
(defrecord Transaction
[^LocalDate date document movements])
(defn create
^Transaction
[^LocalDate date document & movements]
(acc-date/assert-valid-accounting-date date)
(assert-has-movement-records movements)
(->Transaction date document (set movements)))
@olange
Copy link
Author

olange commented Sep 4, 2013

When compiling the project from scratch, the following :require clauses:

(:require [accounting.model.transaction :as transaction]
             [accounting.model.document    :as document]
             [accounting.model.movement    :as movement])

... implied that I also did import these classes:

  (:import  [accounting.model.transaction Transaction]
               [accounting.model.document    Document]
               [org.joda.time                LocalDate]))

... otherwise the compiler would throw an exception:

Unable to resolve classname: Document, compiling:(accounting/factory/transaction.clj:45:28)

Why had I to force the importation of these three classes?
and why does the compiler not need to (:import [accounting.model.movement Movement]), which is also in the :require clause?

To be able to run tests, I first inserted :import of the classes the compiler needed in the top calling sources. Then I understood I had to force the loading of the classes with :import. I felt unsure, yet started to sprinkle those around, each time the compiler would complain. While using these classes, I noticed the compiler would propagate the type and that very few type hints are required (they seem to be appropriate around constructors). Now I'm not sure 1) it was correct and 2) that I haven't forgotten one.

I'd be happy to know the good practices of importing source that declare records and use type hints with these records:

  • should I do that?
  • if so, should I systematically import all classes?
  • if not, should I use (:genclass) instead?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment