This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-01-08
Channels
- # aleph (1)
- # architecture (4)
- # aws (5)
- # beginners (105)
- # boot (1)
- # boot-dev (72)
- # cider (5)
- # clara (15)
- # cljs-dev (51)
- # cljsrn (5)
- # clojure (155)
- # clojure-austin (3)
- # clojure-dusseldorf (2)
- # clojure-finland (1)
- # clojure-greece (37)
- # clojure-italy (17)
- # clojure-nl (1)
- # clojure-russia (6)
- # clojure-spec (23)
- # clojure-uk (6)
- # clojurescript (7)
- # community-development (1)
- # css (10)
- # cursive (15)
- # datomic (45)
- # defnpodcast (1)
- # duct (97)
- # emacs (5)
- # fulcro (46)
- # hoplon (8)
- # instaparse (25)
- # keechma (11)
- # leiningen (16)
- # off-topic (2)
- # onyx (9)
- # planck (2)
- # re-frame (5)
- # reagent (3)
- # reitit (2)
- # ring (6)
- # shadow-cljs (35)
- # spacemacs (9)
- # specter (9)
- # sql (18)
- # uncomplicate (4)
(disj my-sorted-set element-to-remove) returns the value you describe
as it does for any set, regardless of whether sorted or no.
Have you seen the Clojure cheat sheet? It tries to group functions into categories: https://clojure.org/api/cheatsheet
Clicking the "Source repo" link near the top of that page leads to a page that has other variants of it
The Collections / Sets section has a 'Change' group of functions that contains conj for adding an element, and disj for removing.
Hovering the mouse over a function name should show the doc string, without having to click on it.
I was trying to use the with-redefs
macro to change config while running the tests. However the new configuration was not getting picked up by the functions that were called. Here's a gist of what I was trying to do
(ns original.namespace)
(def config {:a :b})
(defn my-fn []
(do-something config))
(ns different.namespace)
(deftest my-test
(with-redefs [config {:c :d}]
(my-fn)))
@ghadi @noisesmith, apologize by the delay.
@noisesmith I'm using the driver from the maven and the jdbc from cljars.
the message error is org.postgresql.util.PSQLException: Can't infer the SQL type to use for an instance of clojure.lang.PersistentVector. Use setObject() with an explicit Types value to specify the type to use.
this is the model, I'm trying to execute create-item
function
@udit I'm not experienced using with-redefs, but when I try something like the code you show in a REPL, it says it is unable to resolve the Var config in the second namespace. If you do "(with-redefs [original.namespace/config {:c :d}] ...)" in your code, it may work as you hope.
I am trying to catch an exception which occurs in a predicate function I use in a filter. I boiled it down to this snippet:
Why can’t I catch this exception
If you wrap the (filter ...) in a doall, i.e. replace it with (doall (filter ...)), then the exception is caught.
so lazy evaluation does sound like the reason.
The (try (filter ...)) is returning an unevaluated lazy sequence, so no exception has been raised yet. If you type that into a REPL, then the REPL will force the lazy seq returned from the (try ...) expression so it can print the value, and then the exception is thrown.
@andy.fingerhut thank you.
are there any native sparse collections (other than perhaps using a map with indices as keys)?
can anyone tell me why I can’t find anything in the namespace of the library I just published?
@lilactown how are you accessing your namespace?
a common mistake is using in-ns
or ns
to switch to a namespace, without using something like require
that actually loads it first
I think I figured out some of it… I had defined the namespaces in the library as lambda-tools.core
instead of lilactown/lambda-tools.core
you need to require the file (or otherwise cause it to be loaded)
just switching to the ns doesn’t make the code load
user> (require 'lilactown.lambda-tools.core)
nil
user> (lilactown.lambda-tools.core)
CompilerException java.lang.ClassNotFoundException: lilactown.lambda-tools.core, compiling:(*cider-repl demoaws*:45:7)
user> (ns-publics 'lilactown.lambda-tools.core)
Exception No namespace: lilactown.lambda-tools.core found clojure.core/the-ns (core.clj:4032)
user> (ns-publics lilactown.lambda-tools.core)
CompilerException java.lang.ClassNotFoundException: lilactown.lambda-tools.core, compiling:(*cider-repl demoaws*:51:7)
user>
so, (lilactown.lambda-tools.core)
isn’t valid - namespaces are not things you can call
(ns-publics 'lilactown.lambda-tools.core)
- throwing an error is an issue
did you do anything else before require?
eg. calling ns or in-ns ?
because that would make require be a no-op - it does nothing if you don’t specify :reload and you already created the ns
The version on Clojars seems to have (ns lilactown/lambda-tools.core ...)
in it (0.1.2) -- have you pushed your updated version (with a .
instead of /
)?
Here's my REPL session with that
(! 863)-> boot -d lilactown/lambda-tools repl
...
boot.user=> (require 'lilactown.lambda-tools.core)
clojure.lang.ExceptionInfo: Call to clojure.core/ns did not conform to spec:
In: [0] val: lilactown/lambda-tools.core fails spec: :clojure.core.specs.alpha/ns-form at: [:args :name] predicate: simple-symbol?
clojure.lang.Compiler$CompilerException: clojure.lang.ExceptionInfo: Call to clojure.core/ns did not conform to spec:
In: [0] val: lilactown/lambda-tools.core fails spec: :clojure.core.specs.alpha/ns-form at: [:args :name] predicate: simple-symbol?
#:clojure.spec.alpha{:problems [{:path [:args :name], :pred clojure.core/simple-symbol?, :val lilactown/lambda-tools.core, :via [:clojure.core.specs.alpha/ns-form :clojure.core.specs.alpha/ns-form], :in [0]}], :spec #object[clojure.spec.alpha$regex_spec_impl$reify__2436 0x6e98787b "clojure.spec.alpha$regex_spec_impl$reify__2436@6e98787b"], :value (lilactown/lambda-tools.core (:require [clojure.data.json :as json] [clojure.string :as s] [ :as io])), :args (lilactown/lambda-tools.core (:require [clojure.data.json :as json] [clojure.string :as s] [ :as io]))}, compiling:(lilactown/lambda_tools/core.clj:1:1)
because you can't have /
in a ns
declaration.Artifacts -- library names -- are group/artifact
but that does not need to match the actual namespace(s). Namespaces are foo.bar.quux
-- no /
.
The namespace "path" should match your filesystem path under src
with -
in the namespace name replaced by _
in the filesystem path.
So if you have src/lamba_tools/core.clj
that is (ns lambda-tools.core ...)
is it then possible to have my library name be lilactown/lambda-tools
, and in apps that use it require it like lambda-tools.core
?
yes the namespace and the artifact name don’t even have to be related (though it’s nice if they are somehow related)
My bad. Pulling 0.1.3 fixed the problem
(! 865)-> boot -d lilactown/lambda-tools:0.1.3 repl
...
boot.user=> (require 'lambda-tools.core)
java.io.FileNotFoundException: Could not locate lambda_tools/core__init.class or lambda_tools/core.clj on classpath. Please check that namespaces with dashes use underscores in the Clojure file name.
boot.user=> (require 'lilactown.lambda-tools.core)
nil
And that matches your src
path now (with lilactown
in it).I decided I wanted to name the library lilactown/lambda-tools
but have consumers use it in their code as lambda-tools.core
or lambda-tools.middleware
Although foo.core
is the default in new project templates, it's an unfortunate anti-pattern. In your case, src/lilactown/lambda_tools.clj
and (ns lilactown.lambda-tools ...)
would probably be better naming
(and src/lilactown/lambda_tools/middleware.clj
and (ns lilactown.lambda-tools.middleware ...)
to go with that)
Namespaces should be globally unique ideally, so someone could have both your lambda-tools
and some other person's lambda-tools
usable in the same app.
yeah, that makes sense. that’s what my original goal was, but it was annoying to have to fully qualify the namespace on each import
yeah - I agree that .core is and anti-pattern, it adds verbosity without adding to uniqueness in any way
I suspect if Phil (`technomancy`) was creating Leiningen again today, he wouldn't use .core
as a default namespace and he'd enforce the "no single segment namespace" guideline in templates 🙂
if you run $ lein new lilactown/lambda-tools
it already does the right thing today btw
i’m also ripping this code out of an existing project so that made it harder as well
@noisesmith Oh, that's good to know -- no .core
ns in that case?
exactly
Hah, and boot/new
does the same because it reuses a bunch of Leiningen stuff:
(! 867)-> boot -d boot/new new -n seancorfield/test-lib
Generating a project called seancorfield/test-lib based on the 'default' template.
The default template is intended for library projects, not applications.
Mon Jan 08 12:08:45
(sean)-(jobs:0)-(~/clojure)
(! 869)-> tree test-lib
test-lib
|____.gitignore
|____.hgignore
|____build.boot
|____CHANGELOG.md
|____doc
| |____intro.md
|____LICENSE
|____README.md
|____resources
| |____.keep
|____src
| |____seancorfield
| | |____test_lib.clj
|____test
| |____seancorfield
| | |____test_lib_test.clj
I wrote boot/new
and I didn't realize that! 🙂sweet!
(! 870)-> cat test-lib/build.boot
(def project 'seancorfield/test-lib)
(def version "0.1.0-SNAPSHOT")
i am wondering if someone can explain this syntax to me, i'm reading the article at https://www.braveclojure.com/appendix-b/ and it has this code example
(defn whiney-str
[rejects]
{:pre [(set? rejects)]}
(fn [x]
(if (rejects x)
(str "I don't like " x)
(str x))))
(def whiney-strinc (comp (whiney-str #{2}) inc))
(whiney-strinc 1)
; => "I don't like 2"
whiney-strinc
is created with def, not defn, but still called like a function, how does that work?
and also, what is this syntax: (whiney-str #{2})
comp
returns a function, so you are capturing that returned function into a var with def
oh ok, of course, that makes sense
#{2}
is the set containing the value 2
, so (whiney-str #{2})
is calling the function whiney-str
with the argument #{2}
. whiney-str
itself returns a function (fn ..)
, so (whiney-str #{2})
is "baking" the #{2}
into the returned function
ahh ok, that makes sense as well, thank you
@pablore there’s some interesting functions in clojure.set - for example clojure.set/index and clojure.set/project
not sure if any of them do exactly what you want, but might be a start
there’s also group-by
for simple indexing by some mapping function
@pablore Have you looked at zipmap? My main confusion about your question is what you mean by a many-to-many association map.
Some code is better than a thousand words:
(def fruits [{:fruit "apple"}
{:fruit "pear"}])
(def names [{:name "alice"}
{:name "bob"}])
(def assocs [{:fruit "apple" :name "alice"}
{:fruit "apple" :name "bob"}
{:fruit "pear" :name "bob"}])
(??? names fruits assocs) => {"bob" [{:fruit "apple"} {:fruit "pear"}]
"alice" [{:fruit "apple"}]}
(group-by :name assocs)
is pretty close
not sure how to make ???
give exactly the same output without knowing more what constraints fruits
, names
, and assocs
will have
ie. does fruits
only have one key in every map
in the fruits and names maps, there could be more properties like color, last name, etc. The assoc maps only know name and fruit
Sounds like what you want may be similar to a join operation in SQL? clojure.set/join may be able to do what you want.
Maybe what you want would be join-3-way, defined something like this:
(defn join-3-way [x y z]
(clojure.set/join (clojure.set/join (set x) (set z)) (set y)))
@andy.fingerhut aha I knew it was one of those things in clojure.set 😄 I should study that namespace more
Yeah, join is probably one of the fancier functions available in that namespace. I've never used it for anything, but have read its code to learn what it does.
Basically a half a dozen functions in there implement some relational algebra operators on in-memory relations (relation = set of maps, like the relational theory that SQL is based upon).
union difference intersection are common to any sets, and can also be used in operations on relations. project and select are pretty straightforward in what they do. index seems quite specific to relations, and rename seems to be there almost purely as part of the implementation of join.