Fork me on GitHub
#beginners
<
2018-01-09
>
justinlee03:01:33

A while a go folks here said that I should be able to import macros using plain old :require and :refer instead of :require-macros and :refer. But I canā€™t seem to be able to import the go macro from cljs.core.async this way. The compiler canā€™t find the cljs.core.async.macros namespace and it canā€™t find go inside the cljs.core.async namespace. What am I doing wrong here?

madstap13:01:54

Are you on the newest version of core async?

justinlee16:01:01

@U0J9LVB6G Iā€™m just using whatever comes with cljs 1.9.946. I didnā€™t realize this was a new(ish) thing

jgh04:01:12

so im messing with clj-pgp a bit and i can get it to decrypt a fileā€¦all of the metadata around the decryption seems as expected, but the data component is just giving me this: :data #object["[B" 0x12f08f92 "[B@12f08f92"]. I assume thatā€™s some kind of pointer, how do I access it?

jgh04:01:12

oh i see, itā€™s a byte array and I can use (String. data) for turning it into a string

jgh04:01:20

or i can use slurp, apparently. neat.

noisesmith17:01:17

@jgh when using String with a byte-array itā€™s a good idea to provide the encoding option - often ā€œUTF-8ā€ but not always

noisesmith17:01:57

penguin.tracking=> (def s "hello, šŸ¶")
#'penguin.tracking/s
penguin.tracking=> (String. (.getBytes s) "UTF-8")
"hello, šŸ¶"
penguin.tracking=> (String. (.getBytes s) "UTF-16")
"ę”„ę±¬ę¼¬āƒ°é¾ļæ½"

jgh17:01:37

good to know for the future. In this case I control the data source so can keep it utf8, but yeah if itā€™s random user data thatā€™s good to keep in mind.

noisesmith17:01:07

even if you know itā€™s UTF-8 itā€™s good practice to provide the argument explicitly to the String constructor - Iā€™m not sure thatā€™s the default

jgh17:01:28

would you advise using String over slurp for something like this?

noisesmith17:01:54

slurp also takes an encoding argument, but String is more direct if what you have is an array of bytes

noisesmith17:01:06

providing the optional encoding arg to getBytes to show the other way this can go wrong

penguin.tracking=> (String. (.getBytes s "UTF-16") "UTF-16")
"hello, šŸ¶"
penguin.tracking=> (String. (.getBytes s "UTF-16") "UTF-8")
"ļæ½ļæ½hello, ļæ½=ļæ½6"

jgh18:01:35

ok, thanks for the tips..iā€™ll clarify my code with the specifier.

dadair18:01:24

I'm trying to write some macros to help with spec-ing a graph-like data-structure I work with. The current macro returns a spec expecting certain types of children nodes:

(s/def :node.children/name-mapped
  #(= (keys %) (->> % vals (map :name) (map keyword))))

(defmacro typed-children
  "Returns a spec requiring children of a specific type."
  [node-type]
  `(s/and (s/map-of keyword? ~node-type)
          :node.children/name-mapped))

(defmacro maybe-typed-children
  "Returns a spec allowing either an empty children map, or a map of specific node types."
  [& node-types]
  `(s/or :empty :node.children/empty
         :has-children
         (s/or ~@(flatten
                  (for [t# node-types]
                    [(keyword "child.type" (name t#)) (typed-children t#)])))))
if I macroexpand-1 (maybe-typed-children :node/a :node/b) I get:
(clojure.spec.alpha/or
 :empty :node.children/empty
 :has-children (clojure.spec.alpha/or
                :child.type/a #object[clojure.spec.alpha$and_spec_impl$reify__875 0x7267466d "clojure.spec.alpha$and_spec_impl$reify__875@7267466d"]
                :child.type/b #object[clojure.spec.alpha$and_spec_impl$reify__875 0x10b897ec "clojure.spec.alpha$and_spec_impl$reify__875@10b897ec"]))
and when I try to use the macro I get an exception: Can't embed object in code, maybe print-dup not defined: clojure.spec.alpha$and_spec_impl$reify__875@d0f4161 Can anyone point out what I'm doing wrong in my maybe-typed-children macro?

dadair18:01:58

clearly the objects for each key in the or are the culprit, but not exactly sure how to get the desired spec from within the ~@(flatten ..)

dadair18:01:38

Basically, the desired output would be (s/or :empty .. :has-children (s/or :child/a (typed-children :node/a) :child/b (typed-children :node/b)))

hansw22:01:17

I have this coll: [ {:key "foo" :some 1} {:key "bar" :some 2} ] and want to turn it into: {"foo" {:key "foo" :some 1} "bar" {:key "bar" :some 1}}. What would the idiomatic way to do that be?

noisesmith22:01:02

thatā€™s very similar to what (group-by :key coll) would return

noisesmith22:01:32

though group-by doesnā€™t assume the keys are unique, so each value is in a vector to make room for others

hansw22:01:26

i am sure there are no duplicate keys beforehand šŸ™‚

justinlee22:01:51

does a double colon in front of a keyword have significance or is it just a convention?

justinlee22:01:18

sorry, nevermind i found a reference

noisesmith22:01:35

for those following along at home, it either namespaces the keyword to the current namespace, or some alias defined in the current namespace

justinlee22:01:49

I saw it in the context of rum. I assume the reason to do this is because its being fed to a macro and by namespacing the keyword it may help avoid some kind of naming clash

noisesmith22:01:55

itā€™s often used for tokens that are only useful when compared to themselves

noisesmith22:01:25

(similar to how gensyms are used but less gibberish if it leaks out)