This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-07-11
Channels
- # aleph (3)
- # beginners (42)
- # cider (219)
- # cljs-dev (39)
- # cljsjs (19)
- # cljsrn (3)
- # clojure (97)
- # clojure-canada (12)
- # clojure-dev (14)
- # clojure-italy (5)
- # clojure-nl (4)
- # clojure-russia (1)
- # clojure-spec (3)
- # clojure-uk (140)
- # clojurescript (52)
- # clojutre (2)
- # cursive (2)
- # datomic (29)
- # docs (1)
- # duct (13)
- # emacs (19)
- # fulcro (8)
- # funcool (2)
- # graphql (26)
- # hyperfiddle (1)
- # luminus (9)
- # nyc (7)
- # off-topic (26)
- # om (21)
- # onyx (19)
- # overtone (1)
- # pedestal (4)
- # re-frame (10)
- # reagent (109)
- # ring (5)
- # rum (15)
- # shadow-cljs (120)
- # spacemacs (22)
- # specter (7)
- # vim (10)
https://gist.github.com/ghadishayban/0ac41e81d4df02ff176c22d16ee8b972 A helper called reify-SAM that helps Clojure code participate in "functional interfaces" AKA the Java 8 lambda interfaces AKA "Single abstract method" classes
(import 'java.util.function.Predicate)
(reify-SAM Predicate
[v]
(even? v))
It allows you to omit the name of the single method you're implementing, as Java does.@ghadi I have something similar using MethodHandles in ike.cljj. https://github.com/ajoberstar/ike.cljj/blob/master/src/main/clojure/ike/cljj/function.clj
would love to have some info at https://dev.clojure.org/jira/browse/CLJ-2365
How would I dynamically load a namespace and return the list of all the functions declared in it?
That works
I need to make sure ns is loaded first though
perhaps (doto ns-sym require ns-publics)
also ns-publics returns a hash-map of all publics, not just functions
and in practice, most consumers want something more like the keys (symbols) or vals (vars) of the ns-publics map
yes, depending what you mean by “private project”
if it’s in a private Maven repo, then use: https://clojure.org/reference/deps_and_cli#_maven_authenticated_repos
Hi, is there a way to make zipmap
force creation of APersistentArrayMap
(`array-map`) so that order is retained? It looks like depending on size sometimes it makes a hashmap instead.
i need to output a file based on a spec, so, for instance column 1 needs to be where column1 needs to be...
There are alternate map implementations that can remember the order that insertions occurred, but there is no way to make a function like zipmap return such a map.
i still wouldn't rely on that. don't worry about overhead, make it correct first. Is this like a csv that is transformed and then re-output?
As the last step after transformation, you can reorder the maps (which represent rows, associatively) by doing this:
Yeah, array-map is 'fragile' in the sense that you can create one, but if you then assoc one more key into it, the return value could be a hash map that no longer has the ordering of the input map.
(let [column-order [:col1 :col2 :col3 :name :whatever]]
(map row column-order)) ;;;;; row is a hashmap
(the terminology is confusing because we're talking about hash maps and the clojure.core/map function)
the map in question, i'm slurping from an edn file and it's called :fields
.... with a key/value for field type.
i think @ghadi was saying just read the data into a map and when you emit it have a vector that dictates the order of the fields. the map never has order. your emitter has an order given to it to dictate in which order to ask the map for values
Well, some types of map data structures preserve order of one kind or another (e.g. sorted-map, ordering-map), but the EDN reader cannot be made to use those without creating your own modified versions of those readers, AFAIK.
so in practice, unless you want to do those kinds of surgery, a data structure that is sequential is better to use than a map when order is important to you.
So in clojure.spec
docs, it talks about how spec maps are only concerned with membership (https://clojure.org/about/spec#_sets_maps_are_about_membership_that_s_it). Then how can we handle cases where the values of certain keys depend on the values of other keys? I am validating input on the edge of my app and I am having a difficult time putting my requirements into spec logic. On updates I receive an id
and name
key. The name
needs to either not exist yet (be unique) or match the current name
associated with the id
in the database. Any ideas on how I could implement this only in spec? Is multi-key validation outside of the scope of spec? Obviously you could attach a predicate to the map itself, but according to the docs I shouldn't be dealing with the values of keys in a map spec. Thanks
as you say, you can do cross-key validation by attaching predicates s/and
to the map. In that case it's not violating the tenet around "maps are sets of keys".
@ghadi thanks. ok, so pretty much any validation that depends on existing state (e.g. in a database) should be done outside of spec as a separate step.
how would one destructure this? `(def foo {[0 0] {:size 85, :used 64, :avail 21, :used-pct 75}})` ` (let [{[x y] {:keys [size used avail used-pct]}} foo] [x y size])`
sorry...
(def foo
{[0 0] {:size 85, :used 64, :avail 21, :used-pct 75}})
(let [{[x y] {:keys [size used avail used-pct]}} foo]
[x y size])
you can't destructure a key in a map like that
if there were two keys in the map, how would it know which one to destructure?
if you call seq (and are certain there isn't a second k/v) you could destructure that though
i was trying to avoid doing first/rest and destructuring those, just for the sake of brevity
I'm not talking about using first/rest
something like this:
(def foo
{[0 0] {:size 85, :used 64, :avail 21, :used-pct 75}})
(let [[[[x y] {:keys [size used avail used-pct]}]] (seq foo)]
[x y size])
right
it might be more meaningful to have something like {:index [0 0] :value {...}}
conveying what that key/value pair actually intends to describe
that definitely simplifies destructuring, but makes getting the values via coordinates a bit goofier
right, I don't know your domain
i think maybe i'll just stop going overboard on the destructring when it doesn't fit well
it's not like multiple destructure calls are more expensive than a single nested one on one line
(well not in a way that's likely to be significant at least?)
be sure you aren't gaming the "lines of code" metric by making one line too complex
i like to use it when it's reasonably readable mainly for the information it gives me in the function signature
I am calling some Java code via interop
(defn- add-image-to-page
[doc pdf-image]
(let [image (PDImageXObject/createFromByteArray doc pdf-image nil)]
; code omitted for clarity
(with-open [stream (PDPageContentStream. doc page)]
(.drawImage stream image x y scaled-width scaled-height))))
; Calling function here
(with-open [doc (PDDocument.)]
(run! #(add-image-to-page doc %) images)
This one works fine, however if I move line with creating image into the function passed to run!
it blows with IllegalArgumentException
on .drawImage
(defn- add-image-to-page
"Adds image as a page to the document object"
[doc image]
; Code omitted
(with-open [stream (PDPageContentStream. doc page)]
(.drawImage stream image x y scaled-width scaled-height))))
; Calling function here
(with-open [doc (PDDocument.)]
(run! #(add-image-to-page doc (PDImageXObject/createFromByteArray doc % nil)) images)
I am really getting desperate on this one. I tried to print all arguments passed into the drawImage
and they are the same for both functions, also the code is same except creating image line. so what could be wrong here?it's a vector of byte arrays
Like I said, everything is the same except the line (PDImageXObject/createFromByteArray doc pdf-image nil)
moved from add-image-to-page
directly to the run!
what is happening is because you moved image out of the function, you are losing type inference on it, so the compiler is turning the call to drawImage in to a reflective call, and the reflective call is failing for whatever reason (clojure.lang.Reflect is picking the wrong method likely)
warning on reflection will show you the difference, type hinting image should fix it
@hiredman nice, that really helped 🙂
thanks, didin't know about this issue
I’m writing an ebook parser in clojure. Once unzipped ebooks are plain HTML. However, the problem is that the HTML is mostly flat, like this (in enlive)
(def ebook
[{:class "indent" :content "ignore"}
{:class "indent" :content "ignore"}
{:class "START HERE" :content "Key Lessons"}
{:class "indent" :content "ignore"}
{:class "indent1" :content "ignore"}
{:class "bl" :content "key lesson 1"}
{:class "bl" :content "key lesson 2"}
{:class "indent1" :content "ignore"}])
I’m want to structure that data so that a header
contains the children
writing a range and filter query like:
(query ebook {:from #(= "START HERE" (:class %))
:filter #(= "bl" (:class %))
:to some?})
that should return
=> {:class "START HERE"
:content "Key Lessons"
:children [{:class "indent" :content "key lesson 1"}
{:class "indent" :content "key lesson 2"}
{:class "indent1" :content "key lesson 3"}]
}
Now I feel like I’ve implemented something like this a million times. Is there a library (even non-clojure) and query syntax to take unstructured data and give it structure. I’m aware I could use spec but spec likes to check everything and the inconsistencies in ebook make it hard to spec all of it out. So I’m looking for something that just finds what matches and goes from there.Take a look at #specter
theoretically yes, but the problem is specs objective is spec things, in other words, to identify what they are. I’m looking for something that is more like a search, a query, that infers relationships through sequence.
you are taking a flat structure and turning it into tree, which is parsing, the difference is you are parsing a stream of datastructures and not a stream of characters
(require '[clojure.spec.alpha :as s]
'[clojure.pprint :as pp])
(def ebook
[{:class "indent" :content "ignore"}
{:class "indent" :content "ignore"}
{:class "START HERE" :content "Key Lessons"}
{:class "indent" :content "ignore"}
{:class "indent1" :content "ignore"}
{:class "bl" :content "key lesson 1"}
{:class "bl" :content "key lesson 2"}
{:class "indent3" :content "ignore"}])
(s/def
::ebook-tree
(s/and
(s/cat
:ignore (s/* (s/and map? #(= "ignore" (:content %))))
:start (s/and map? #(= (:class %) "START HERE"))
:body (s/* (s/alt
:ignore (s/and map? #(= "ignore" (:content %)))
:item (s/and map? #(= "bl" (:class %)))))
:end (s/and map? #(= "indent3" (:class %))))
(s/conformer
(fn [{:keys [start body]}]
(assoc start :children (for [[tag item] body
:when (not= tag :ignore)]
item))))))
(pp/pprint
(s/conform ::ebook-tree ebook))