defrecord Class Not Found Exception - clojure

I have two files knapsack.clj and core.clj.
There is defrecord Item in knapsack.clj. I want to use it in core.clj but it is giving me error in cider-repl of java.lang.ClassNotFoundException: discrete-optimization.knapsack.Item even though i have require for the knapsack namespace.
Code is here :
;; ---- knapsack.clj ---------
(ns discrete-optimization.knapsack)
;; Item record has weight and value of the Item
(defrecord Item
[weight value])
;; ---- core.clj --------
(ns discrete-optimization.core
(:require [discrete-optimization.knapsack :as KS])
(:import [discrete-optimization.knapsack Item]))
;; doing some knapsack in here.. :)
(and
(= 5 (KS/knapsack-value 5 [(Item. 3 5)]))
(= 5 (KS/knapsack-value 5 [(Item. 3 3) (Item. 2 2)])))
My clojure version is 1.5.1
Solution :
For portable solution :
use ->KS/item when referring to item outside of namespace.

While the answer from xsc is not wrong, my preference is to use the constructor functions that are generated from defrecord and avoiding the Java constructor and Java import -isms. This is likely to be more portable over time/platforms.
;; ---- knapsack.clj ---------
(ns discrete-optimization.knapsack)
;; Item record has weight and value of the Item
(defrecord Item
[weight value])
;; The ->Item constructor is generated automatically
;; ---- core.clj --------
(ns discrete-optimization.core
(:require [discrete-optimization.knapsack :as KS]))
;; doing some knapsack in here.. :)
(and
(= 5 (KS/knapsack-value 5 [(KS/->Item 3 5)]))
(= 5 (KS/knapsack-value 5 [(KS/->Item 3 3) (KS/->Item 2 2)])))

:import references a Java class - and when creating package/class names for those the Clojure compiler converts dashes to underscores. This might thus work:
(:import [discrete_optimization.knapsack Item])

Related

How do you use an existing vector of predicates with :post conditions in Clojure?

Given that :post takes a form that gets evaluated later (e.g. {:post [(= 10 %)]}). How could one dynamically pass a 'pre-made' vector of functions to :post?
For example:
(def my-post-validator
[prediate1 predicate2 predicate3])
(defn foo [x]
{:post my-post-validator}
x)
this throws a syntax error
Don't know how to create ISeq from: clojure.lang.Symbol
With my fuzzy understanding, it's because defn is a macro, and the thing that allows the % syntax in :post is that it's quoted internally..?
I thought maybe I then use a macro to pass a 'literal' of what I wanted evaluated
(defmacro my-post-cond [spec]
'[(assert spec %) (predicate2 %) (predicate n)])
example:
(defn foo [x]
{:post (my-post-cond :what/ever)}
x)
However, this attempt gives the error:
Can't take value of a macro
Is there a way to pass a vector of things to :post rather than having to define it inline?
You can't pass a vector of predefined predicates, but you can combine multiple predicates under a single name and use that name in :post:
(defn my-post-cond [spec val]
(and
;; Not sure if this is exactly what you want,
;; given that `val` becomes an assert message.
(assert spec val)
(predicate2 val)
;; You used `n` - I assume it was supposed to be `%`.
(predicate val)))
(defn foo [x]
{:post [(my-post-cond :what/ever %)]}
x)
I started off as a fan of pre- and post-conditions, but I've changed over the years.
For simple things, I prefer to use Plumatic Schema to not only test inputs & outputs, but to document them as well.
For more complicated tests & verifications, I just put in an explicit assert or similar. I also wrote a helper function in the Tupelo library to reduce repetition, etc when debugging or verifying return values:
(ns tst.demo.core
(:use tupelo.core tupelo.test))
(defn oddly
"Transforms its input. Throws if result is not odd"
[x]
(let [answer (-> x (* 3) (+ 2))]
(with-result answer
(newline)
(println :given x)
(assert (odd? answer))
(println :returning answer))))
(dotest
(is= 5 (oddly 1))
(throws? (oddly 2)))
with result
------------------------------------
Clojure 1.10.3 Java 11.0.11
------------------------------------
Testing tst.demo.core
:given 1
:returning 5
:given 2
Ran 2 tests containing 2 assertions.
0 failures, 0 errors.
Passed all tests
So with either the println or assert, the returned value is easy to see. If it fails the assert, an Exception is thrown as normal.

shortest Clojure static typing

what is the literal simplest, shortest way to typecheck a clojure function. The regular ann form is pretty short:
(ann bar [Number -> Number])
(defn bar [b]
(+ 2 (foo b)))
But can we (with a macro or something) make it look smaller, like:
(defn bar [b : Number -> Number]
(+ 2 (foo b)))
Thanks for your advice!
I think Plumatic Schema is the best. See also this blog post.
Here is an example:
(ns tst.demo.core
(:use tupelo.core tupelo.test)
(:require [schema.core :as s]))
(s/defn add2 :- s/Num ; "superclass" for any number
[a :- s/Int ; must be an integer type
b :- Double] ; Must be a java.lang.Double
(+ a b))
(dotest
(throws? (add2 1 2))
(throws? (add2 1.0 2))
(is= 3.0 (add2 1 2.0)))
I also have some predefined "types" in addition to the basic ones. For example, tupelo.schema/Keymap is any map with keyword keys. Pair is any vector or sequence of length=2, etc.
Update
Please also see my Clojure template project. In particular,
the file test/clj/_bootstrap.clj exists for the sole purpose of enabling Plumatic Schema type checks when you type lein test (they are disabled by default, so there is no cost in production).
Strictly speaking, this is spec checking and not static typing, but you may want to check out Guardrails (a fork of Ghostwheel, which is unmaintained) which aims to tackle some of the problems static typing does and more:
(>defn ranged-rand
[start end]
[int? int? | #(< start end)
=> int? | #(>= % start) #(< % end)]
(+ start (long (rand (- end start)))))

Using prn or println within a list comprehension for debugging [duplicate]

This question already has answers here:
Why isn't my code printing like it should?
(3 answers)
Closed 2 years ago.
(defn f1 []
(for [a [1 2]]
a))
;user=>(f1)
;(1 2)
(defn f2 []
(for [a [1 2]]
(prn a)))
;user=>(f2)
;1
;2
;(nil nil)
(defn f3 []
(for [a [1 2]]
(prn a))
'something-else)
;user=>(f3)
;something-else
Why does f3 not print 1 and 2 before printing 'something-else?
i.e. I expected and had assumed (wrongly) it would print the following:
; 1
; 2
; something-else
Came across this when using a for with a lot of code inside it and this played havoc with
my attempt to use prn statements to trace the value of variables while debugging.
i.e. prn and println do not print out. I think it's only when the for block is not the
final form in its enclosing form, but i'm still not sure what's going on.
The point being that a side-effect such as prn or println, should not require to be in return value position for it to fire. So there's something deeper with list comprehensions that I don't understand.
A notion as I write this - maybe in f3 the list comprehension is simply never evaluated, due to laziness? ... oh [censored].
Yes, that is indeed it:
(defn f4 []
(doall
(for [a [1 2]]
(prn a)))
'something-else)
user=> (f4)
;1
;2
;something-else
So, even though mostly solved, I will still post this question to consolidate the learning - would anyone care to post some examples of their own gotchas re. laziness.
As you have documented here, the macro for is lazy, and doesn't execute until it has to. You can force it by wrapping it in a (vec ...) form or a doall.
For debugging purposes especially, I like to use spyx and forv from the Tupelo library to avoid all of these gotchas:
(ns tst.demo.core
(:use tupelo.core tupelo.test))
(defn f5 []
(forv [a [1 2]]
(spyx a))
(spy :returning :something-else))
(dotest
(spyx (f5)))
With result:
-------------------------------
Clojure 1.10.1 Java 14
-------------------------------
Testing tst.demo.core
a => 1
a => 2
:returning => :something-else
(f5) => :something-else
Ran 2 tests containing 1 assertions.
0 failures, 0 errors.
So you can see printed nicely:
the labeled value of a at each step of the forv loop.
the return value of the function with a custom label
the explicit value of the function call (f5)
nothing anywhere is lazy
spy, spyx, et al always return the value printed for further use
a convenient unit test via is= confirms the output value.
There is a nice template project that you can clone to get you started quickly.
You may also be interested in with-result, or just doseq. Don't forget the Clojure CheatSheet.

Trying to read data from a text file and populating a list of integers

So, upfront, I'm super new at Clojure so this question may seem basic. I hava a txt file with 1 line that has a set number of intergers separated by a space. I need to read that data and populate a list so I can sort it later. I'm not asking how to do the sort, I need help populating the list with the string from the txt file.
My initial thought is to read the entire line of ints as one string, then split the string with a delimiter, and populate the list with the returned data, but I cant figure out how to do that in clojure. Any guidance is appreciated
Here is one way to do it, using some helper functions. Be sure to also bookmark:
The Clojure CheatSheet
Brave Clojure
Getting Clojure
(ns tst.demo.core
(:use demo.core tupelo.core tupelo.test)
(:require
[schema.core :as s]
[clojure.string :as str]))
(dotest
(let [filename "/tmp/dummy.txt"]
(spit filename "1 2 3 4 5")
(let-spy
[in-str (slurp filename)
nums-str (str/split in-str #"\W+")
nums (mapv #(Integer/parseInt %) nums-str)]
)))
with result:
-------------------------------
Clojure 1.10.0 Java 12
-------------------------------
Testing tst.demo.core
in-str => "1 2 3 4 5"
nums-str => ["1" "2" "3" "4" "5"]
nums => [1 2 3 4 5]

Clojure UUID - Having trouble creating IDs for defrecords

All I'm trying to do is create an auto-generated UUID for clojure defrecord's when they are created. I've tried the following:
(ns myns
(:require [clj-uuid :as uuid])
(defrecord Thing [thing-id name])
(defn create-thing
[name]
(map->Thing {:thing-id (uuid/v1)
:name name}))
Followed by:
(repeat 5 (create-thing "bob"))
But I get the same UUID created for every Thing I create. Help would be appreciated!
I'm suspicious about using a dedicated lib for this, given how easy it is to do via interop using the built in UUID class that comes with the jvm.
(ns myns
(:import (java.util UUID)))
(defrecord Thing [thing-id name])
(defn create-thing
[name]
(map->Thing {:thing-id (UUID/randomUUID)
:name name}))
;; using repeatedly instead of repeat generates new values,
;; instead of reusing the initial value
(repeatedly 5 #(create-thing "bob"))