I am trying to access a "defrecord" from another ns and I get an error.
I am able to access a declared "def" and an declared constructor but not the "defredord".
This is the code:
(ns myapp.model)
(defrecord Person [fname lname])
(defn make-person [fname lname]
(->Person fname lname))
(def p1 (make-person "John" "Doe"))
(ns ibercode.core
(:require [myapp.model :as model]))
;;OK
(def p2 (model/make-person "John" "Doe"))
;;OK
(prn model/p1)
;;clojure.lang.Compiler$CompilerException: java.lang.RuntimeException: No
;;such namespace: ->model, compiling:
(def p3 (->model/Person "John" "Doe"))
Thanks
R.
You misunderstood ->. It is not syntax, but simply a naming convention.
The name of the constructor function is ->Person, so qualified, it is model/->Person.
Related
I'm currently implementing multiple types with the same protocol as the basis and would like to reduce the number of files one would need to include in the namespace in order to use them. To give an example:
basetype.clj
(defprotocol Base
(do-something [obj]))
(deftype Basetype [obj]
...
Base
(do-something [obj] something-something))
second_type.clj
(ns project.second-type
(:use project.basetype))
(deftype DifferentType [obj]
...
Base
(do-something [obj] something-slightly-different))
What I did achieve is that everything built for Basetype also works with DifferentType. However, I'd like to access the function do-something simply by including second_type.clj in a namespace instead of including both. Is there a way to achieve this?
as i mentioned in my comment, you should be able to reexport any values from any namespace.
you could make up simple function like this:
(defn reexport [from-ns name]
(ns-unmap *ns* name)
(intern *ns* name #(ns-resolve from-ns name)))
(reexport 'project.basetype 'do-something)
or to reexport all the values from the given ns:
(defn reexport-all [from-ns]
(run! (partial reexport from-ns) (map first (ns-publics from-ns))))
(reexport-all 'project.basetype)
in repl:
user> (ns x)
nil
x> (defn f [v] (inc v))
#'x/f
x> (ns y)
nil
y> (user/reexport 'x 'f)
#'y/f
y> (in-ns 'user)
#namespace[user]
user> (y/f 10)
11
user> (in-ns 'y)
#namespace[y]
y> (defn f2 [v] (dec v))
#'y/f2
y> (ns z)
nil
z> (user/reexport-all 'y)
nil
z> (in-ns 'user)
#namespace[user]
user> (z/f 1)
2
user> (z/f2 1)
0
(map (fn [x]
(let [username (or (:f_username x) nil)
sites_names (SITES-NAMES username)
x (assoc x :sites sites_names)]
x)) my-rows)
In the code above: SITES-NAMES gives me an arity exception. However
if I call it (SITES-NAMES "theuser") it works. Why is this the case
if username evaluates as an example to "theuser".
I don't know why this is happening, but here are a few tips:
1) Make your anonymous function a top-level function, as such:
(defn add-site [site-names {:keys [f-username] :as x}]
(assoc x :sites (get site-names f-username)))
Notice how I name the vars, refer to https://github.com/bbatsov/clojure-style-guide for more info on naming and other neat stuff.
2) Now you can change your call to map with
(map (partial add-site site-names) my-rows)
This lets you play around with the add-site function at the REPL like so:
user> (add-site {"hector" "www.hector.com"} {:f-username "hector"})
;; => {:f-username "hector", :sites "www.hector.com"}
You might want to read this as well:
https://stuartsierra.com/2015/08/10/clojure-donts-redundant-map
The following works in the repl:
(defprotocol MyProtocol
(foo [this]))
(deftype A []
MyProtocol
(foo [this] "a"))
(deftype B []
MyProtocol
(foo [this] "b"))
(deftype C []
MyProtocol
(foo [this] (str (foo (A.)) (foo (B.)))))
When I try to move each instance to a separate file to reduce coupling, then I get the following error on C: "Unable to resolve symbol: foo in this context"
Sample layout:
;; my_protocol.clj
(ns my-protocol)
(defprotocol MyProtocol
(foo [this]))
;; type_a.clj
(ns type-a
(:require my-protocol :refer [MyProtocol])
(deftype A []
MyProtocol
(foo [this] "a"))
;; type_b.clj
(ns type-b
(:require my-protocol :refer [MyProtocol])
(deftype B []
MyProtocol
(foo [this] "b"))
;; type_c.clj
(ns type-c
(:import [type_a A]
[type_b B])
(:require my-protocol :refer [MyProtocol])
(deftype C []
MyProtocol
(foo [this] (str (foo (A.)) (foo (B.)))))
(ns type-a
(:require my-protocol :refer [MyProtocol])
You refer to the protocol, but never to foo, so when you attempt to call foo the compiler doesn't know what you mean. Instead write:
(ns type-a
(:require my-protocol :refer [MyProtocol foo])
I encountered something like this in a program:
(defonce foo nil)
(alter-var-root #'foo (constantly 4))
Since the code above uses constantly, is there any reason to prefer it to a simple def, like below?
(def foo 4)
Is it just to make it more consistent with the defonce, or there are downsides to using def?
(ns banana)
(defonce foo nil)
(ns user)
(use 'banana)
foo ;=> nil
(alter-var-root #'foo (constantly 42))
foo ;=> 42
(def foo 50)
CompilerException java.lang.IllegalStateException: foo already refers to: #'banana/foo in namespace: user
I have this piece of code:
(ns com.example.main)
(gen-class
:name com.example.main.CTest
:methods [ [foo [] "[B"]])
(defn -foo [this]
(byte-array [(byte 1) (byte 2)]))
(gen-interface
:name com.example.main.ITest
:methods [ [foo [] "[B"]])
It creates the foo method in class CTest correctly, with return type byte[]. However, the same thing creates a method with return type [B in the ITest interface. How do I do this correctly? Is it a bug in Clojure?
Thanks, David
I don't know if some other solution is preferred, but this works:
(gen-interface
:name com.example.main.ITest
:methods [[foo [] #=(java.lang.Class/forName "[B")]])