Fork me on GitHub
#clojure
<
2016-11-28
>
kzeidler01:11:20

(all-ns) returns a sequence of Namespace objects, e.g. "#object[clojure.lang.Namespace 0x3e44f2a5 "http://clojure.java.io"]. Is there a way to simply extract the string portion of the object?

kzeidler01:11:24

More generally I'm curious what generic methods are available for inspecting data of type #object – are there others besides (meta obj)?

csm01:11:06

#object is just how the printer represents the object to you, a clojure.lang.Namespace is just a Java object

csm01:11:44

though you could do (map #(.getName %) (all-ns))

kzeidler01:11:11

Hmm. That gives me "(clojure.core/map (fn* [p1__35809__35810__auto__] (.getName p1__35809__35810__auto__)) (clojure.core/all-ns))"

csm01:11:29

well, what you should be getting is a lazy seq of symbols

kzeidler01:11:49

Though (.getName (first (all-ns))) does work

kzeidler01:11:58

Which is helpful. Thanks!

kzeidler01:11:53

Update: resolving (all-ns) a seq works, i.e. (map #(.getName %) (seq (all-ns)))

underplank03:11:43

Hi all, Anybody got tips on making http requests to a unix socket file?

underplank03:11:40

ie in curl you do curl —unix-socket /var/run/docker.sock

underplank03:11:01

I’ve worked out how to do it in python. but not sure how in clojure

lmergen03:11:23

@underplank well, im not sure whether that would be possible at all using the current setup of http client libraries. i think this should be doable writing a clj-http interceptor, though

underplank03:11:28

@lmergen hmm.. I havent heard of interceptors before. Do you have a link to more information about them and what they can do?

kzeidler03:11:39

Do Namespace objects (as returned by clojure.lang.Namespace) implement any of the other methods defined on the Java "Class" API, or just .getName?

lmergen03:11:49

@underplank an interceptor is nothing more like a middleware pattern that some libraries use -- clj-http happens to use them.

lmergen03:11:00

other popular libraries that use interceptors are pedestal and yada

lmergen03:11:05

basically, it allows a third party to 'intercept' certain parts of execution of a library, allowing for very flexible extensibility of libraries, and/or separation of concerns

underplank03:11:17

hmm.. ok i’ll have a look at it. thanks for the pointers.

lmergen03:11:01

however, i'm not sure whether clj-http's interceptors are actually modeled well enough to support what you want; i see they have a 'response interceptor', but what you actually need sounds a lot more like a 'request interceptor'

cmath04:11:33

with assoc, I can do (assoc m :a 1 😛 2 :c 3); is there a way to do (assoc-in m [:a :b] 1 [:c :d] 2 [:e :f] 3) ?

cmath04:11:39

What is the rationale ?

bbloom04:11:37

cmath just use -> and multiple assoc-in calls

bbloom04:11:12

the rationale is probably just “we didn’t do it, and there hasn’t been a compiling need to yet either"

cmath04:11:24

@bbloom: actually, just implemented my-assoc-in

bbloom04:11:37

well then there you go 🙂

Alex Miller (Clojure team)04:11:54

There is an enhancement ticket for it somewhere

bbloom04:11:57

s/compiling/compelling

Alex Miller (Clojure team)04:11:11

Although it brings up some interesting questions

cmath04:11:24

like what if one path makes another path invalid

dominicm11:11:29

Admittedly, I thought they could do more

kzeidler14:11:15

Is there no built-in function that returns the current ns? Any representation would do (object, string, symbol...)

kzeidler14:11:15

I can import a library if necessary, I just haven't found a solid way yet to do this by any means

acron14:11:44

@kzeidler Does the *ns* binding do what you need?

kzeidler14:11:54

@acron Quite nicely! Thanks, I guess the astericks threw my search strategy off

fabrao15:11:02

Hello all, is there anyone that worked with Meltdown?

gregnwosu15:11:28

hello can anyone tell me how i would create a new instance of a Memory Stream given

object MemoryStream {
  protected val currentBlockId = new AtomicInteger(0)
  protected val memoryStreamId = new AtomicInteger(0)

  def apply[A : Encoder](implicit sqlContext: SQLContext): MemoryStream[A] =
    new MemoryStream[A](memoryStreamId.getAndIncrement(), sqlContext)
}

tdantas15:11:40

do you guys use record to represent your business domain objects or just a map ? I’m using records to represent my domain objects and don’t know if it is appropriated ! any objections/thoughts ? User / Account / Tasks / Jobs are some of my records. and each one implements his own protocol ( in OO would be the business methods )

tdantas15:11:03

( too much OO thinking on that ? ^^ )

Alex Miller (Clojure team)15:11:29

records are good for that. generally, you probably don’t want/need a protocol for each record though, so I’d say don’t start in that direction. just write functions.

Alex Miller (Clojure team)15:11:41

use protocols when you need class-based polymorphism

kah0ona16:11:32

Bit of a novice question maybe, but... I use @weavejester 's aws library to download a zipfile off AWS S3. Now i have an S3ObjectInputStream, but how can I write this to a .zip file on disk?

kah0ona16:11:55

it's not a text file, so a normal slurp doesn't make sense right?

kah0ona16:11:16

wonder what's idiomatic or do i have to juggle with java streams?

wotbrew16:11:43

@kah0ona it is idiomatic to use java streams via the namespace which is included in clojure itself.

wotbrew16:11:55

You can open an output stream on a file via io/output-stream, wrap that in a java.util.zip.GZIPOutputStream, and then use io/copy to copy the bytes from the input stream to the output stream. Look at the with-open macro to make sure your streams get closed correctly

kah0ona16:11:28

aha ok thanks

tdantas16:11:53

the hassle of using record, on my point of view, is that from every database query I have to map the result to the record. @alexmiller is it normal that , the mapping or should I use maps on that cases ?

Alex Miller (Clojure team)16:11:42

if you don’t need a record, then a map is perfectly fine too

tdantas16:11:58

good, so my point is, why use record then ?

Alex Miller (Clojure team)16:11:45

well, I co-wrote Clojure Applied and the first chapter is about exactly this. not sure I can fully cover it in chat :)

tdantas16:11:41

cool, buying it now 🙂

Alex Miller (Clojure team)16:11:50

it’s on sale right now at 40% off the ebook

tdantas16:11:09

pragprog right ?

Alex Miller (Clojure team)16:11:18

yeah, use code turkeysale2016

jrheard16:11:19

@oliv let us know if it answers your question - i’ve been programming toy projects in clojure for five years and to my eternal shame i still have not yet written a single record or protocol, i just use maps and functions

Alex Miller (Clojure team)16:11:53

records are faster and more memory efficient in some ways (but have tradeoffs in others). records give you a known type, which is useful for polymorphic dispatch (if you need it).

jrheard16:11:16

i guess i just don’t often need polymorphic dispatch, or at least i haven’t so far - i’m sure it’ll come up one of these days

jrheard16:11:29

none of my projects have gotten much past 1k LOC fwiw

tdantas16:11:18

I’m handling websockets events and I’m using defmulti/defmethod to dispatch properly the message to be handled

tdantas16:11:49

I’m using maps and the dispatch function is the event type field

jrheard16:11:07

yeah, that’s a common pattern, i’ve done something similar a few times

jrheard16:11:32

i can see how records/protocols would fit in in that situation

fellshard16:11:44

The extensibility factor is great, too.

Alex Miller (Clojure team)16:11:04

dispatching with protocols on records types will be faster than multimethods on maps

jrheard16:11:19

that’s probably what i’ve been missing - since i only work on my own tiny projects, the extensibility factor isn’t always super apparent

jrheard16:11:33

guess i need to work on a larger codebase one of these days 🙂

Alex Miller (Clojure team)16:11:45

either of those approaches is extensible, so no real difference there

tdantas16:11:56

> i can see how records/protocols would fit in in that situation I can’t yet @jrheard 😞

tdantas16:11:07

but I’m on my journey to learn that

jrheard16:11:56

i think you’d have each websocket event be a different type of record, and each record type would implement your IWebsocketEvent protocol’s handle-event function (i’m sure that these names are bad and that pros would use better names)

jrheard16:11:14

but i think that’s the general shape of it, if i understand the world correctly

tdantas16:11:24

cool ! I see

Alex Miller (Clojure team)16:11:43

then you just invoke handle-event with your event and it will choose the implementation based on the type

tdantas16:11:44

I just have to create the record based on the event type field and call the handle-event function

tdantas16:11:50

that is implemented on my records

tdantas16:11:55

using defprotocol

Alex Miller (Clojure team)16:11:29

the JVM is highly optimized to do type-based dispatch (b/c Java) and this taps into that

tdantas16:11:03

that is awesome ! will change from defmulti to records + protocol

Alex Miller (Clojure team)16:11:05

multimethods require you to a) invoke the dispatch function (class), then b) find the best matching method and c) invoke the method. so they are slower

tdantas16:11:21

yeah , right !

Alex Miller (Clojure team)16:11:36

if interested in more info along those lines

tdantas16:11:59

gosh I really like the clojure community !

tdantas16:11:01

thank you guys !

cmath17:11:05

Is there a channel here for spectrum? The project trying to check at compile time, portion of spec?

tdantas17:11:04

@alexmiller and @jrheard that is how I’m doing

(defn fetch-record [msg]
  (let [type (msg "type")]
    (case type
      "message" (map->Message msg)
      "reply" (map->Reply msg)
      "upload" (map->Upload msg))))


(defn on-message [msg]
  (let [record (fetch-record msg)]
    (handle-message record)))

tdantas17:11:24

is it correct the idea of fetch-record to create the record ?

Alex Miller (Clojure team)17:11:04

is there any way you can simply construct msg as a record in the first place?

Alex Miller (Clojure team)17:11:02

as you have it written, this is a closed system as the case encodes the valid message types. replacing that with a multimethod would make it an open system where new message types could be added later.

tdantas17:11:02

the on-message is the callback from my websocket , I’m receiving the raw message there

tdantas17:11:18

cool ! agree !

tdantas17:11:30

so I could use multimethod to create the record

Alex Miller (Clojure team)17:11:42

yeah, just (defmulti on-message [msg] #(get % “type”)) or something like that

Alex Miller (Clojure team)17:11:49

then add defmethods for each type that returns the record

Alex Miller (Clojure team)17:11:40

(defmethod on-message “message” [msg] (map->Message msg))

tdantas17:11:39

yeah, just refactored to exactly that

tdantas17:11:44

thanks for your time @alexmiller

juhoteperi17:11:53

Is there any Socket REPL clients yet? Besides Tubular?

roelofw18:11:01

What is the best way to read json from a external api , Use slurp or use clj-http.client ?

kokos18:11:45

how would one match a " in a string?

(re-matches #"\"(.*)\"" "this is a \"quoted text\"") 
i've tried to
(re-pattern "\"(.*)\"")
but it still doesn't work

bfabry18:11:21

haha, oh java

bfabry18:11:35

java string escaping + regex character escaping

bfabry18:11:36

I think I'd use a character class:

boot.user=> (re-find #"[\"]" "\"")
"\""

fellshard18:11:03

Your initial one works

fellshard18:11:14

But it's implicitly anchoring to the beginning of the string

baptiste-from-paris18:11:28

Hello guys, I'd like to write a spec that validates that validates that if one specific key is present, an other one should not be in the map example:

{:id 1234, :name "Baptiste", :surname "Newbie"}
If :name is present, my spec should validate that :surnameis not

fellshard18:11:48

Try #".*\"(.*)\"" to prove that to yourself

baptiste-from-paris18:11:49

I looked at or but could not find a way to make it work

dpsutton18:11:22

why would it implicitly anchor to the beginning of the string?

fellshard18:11:43

Dunno, let's look up the docs on re-matches

fellshard18:11:10

re-seq does return it

fellshard18:11:11

re-matches tests whether the entire string matches the pattern; re-find searches for matches in the string for the pattern.

dpsutton18:11:12

ah. very interesting to know. thanks

kokos18:11:51

@fellshard actually my example does work, here's the full problem, text to be parsed: 100.100.101.200 - - [28/Nov/2016:12:32:48 -0500] "GET /pro/p/0004f26b0ff8 HTTP/1.1" 404 5 "-" "FDM 3.x" "-" want to pull the IP, the timestamp and the request, they are apache log stats, unfortunately can't use [apache-log-parser "0.1.0"] as i don't know the access log format. i need to pull the IP, timestamp, request and the response code, this is what i'm using

(re-matches #"([^ ]*).*\\[(.*)\\].*\"(.*)\".*([0-9]*).*" line)
but it returns nil , tried to double/triple escape " but no luck

dpsutton18:11:22

maybe approach as a awk script? split on spaces and then capture by "column"

kokos18:11:33

@dpsutton sounds like a pain when a simple regex would suffice

dpsutton18:11:48

i thought this problem arose because the regex was annoying?

fellshard18:11:50

Have you tried temporarily replacing the string-capture portion with wildcard to see if that is the root cause?

fellshard18:11:07

I can actually see that regex getting greedy at the end and grabbing all the way from "GET ... to ..."-" "

fellshard18:11:20

Picking 3 as the integer group and then leaving

fellshard18:11:27

or even empty string

fellshard18:11:58

Too much freedom, needs more precision on where you're using wildcards and where you're using whitespace...

fellshard18:11:07

Or word boundaries, etc.

kokos18:11:37

i've replaced " with and doesn't work, seems to be a problem with my regex not "` , thank you all, will sort my buggy regex

roelofw18:11:12

Wierd, I requird cheshire like this in my repl : `(:require '[cheshire.core :refer :all]) => nil `

roelofw18:11:20

so it seems to be loaded

roelofw18:11:06

then I do (parse-string ..... ) and I see this error message :

Unable to resolve symbol: parse-string  

roelofw18:11:20

what did I do wrong here ?

bfabry19:11:22

at the repl you need to use the require function, not the :require keyword from the ns form

bfabry19:11:07

the reason you didn't get an error is because keywords are functions that take collections and try to look themselves up in the collection

bfabry19:11:26

I wonder if with clj 1.9 you may eventually get an error because a list collection is not associative...

roelofw19:11:41

I use cli 1.8

roelofw19:11:51

so for that one I cannot help you

bfabry19:11:48

yeah I just checked with my version of 1.9 and it's not currently an error. doesn't mean it won't eventually be though

bfabry19:11:10

although.... keywords being functions is probably implemented in java, so maybe not doable/easy

roelofw19:11:53

Next problem with parsing :

(parse-string(client/get ""))
ClassCastException clojure.lang.PersistentArrayMap cannot be cast to java.lang.String  cheshire.core/parse-string (core.clj:206)

(parsed-seq(client/get ""))
ClassCastException clojure.lang.PersistentArrayMap cannot be cast to java.io.Reader  cheshire.core/parsed-seq (core.clj:310) 

roelofw19:11:11

I try to parse a json response from a external api

bfabry19:11:24

client/get is returning a response that isn't what either parse-string or parsed-seq requires. I would look at the output of client/get and figure out how you need to modify it to suit the requirements of parse-string

roelofw19:11:31

oke, I make a lpaste for it. It's a big reponse. you can find it here: http://lpaste.net/347571

roelofw19:11:01

I need the body part and expecially later the artObjects part

bfabry19:11:01

then you need to call :body on the response to client/get before you pass it to parse-string

roelofw19:11:24

so (:body (client-get ...... ) ?

bfabry19:11:32

(:body (client/get

roelofw19:11:32

yep, then I see this :

{"elapsedMilliseconds" 52,
 "count" 4736,
 "artObjects" [{"longTitle" "Portretten van Giuliano en Francesco Giamberti da Sangallo, Piero di Cosimo, 1482 - 1485",
                "hasImage" true,
                "principalOrFirstMaker" "Piero di Cosimo",
                "id" "nl-SK-C-1368",
                "headerImage" {"guid" "76249f29-b230-41ac-aa38-1dcb8476b614",
                               "offsetPercentageX" 50,
                               "offsetPercentageY" 50,
                               "width" 1919,
                               "height" 459,  

roelofw19:11:41

This is a part of the big file

roelofw19:11:02

I hope I can get get all the id's of the paintings

roelofw19:11:28

I think I need to get the artObjects out of it and then use a map

bfabry19:11:15

@roelofw have you gone through clojure for the brave and true and some of the clojure koans?

roelofw19:11:23

yep. I did some 60 exercises from 4clojures and all the clojure koans

bfabry19:11:55

ok cool. it's just pulling parts of a map out, mapping over internal parts of a map etc are all covered in those sources

roelofw19:11:43

Then I need to get into it again

roelofw19:11:02

I cannot make it work to get only the artObjects part

bfabry19:11:43

mm. I think you probably want:

(-> (client/get ...)
  :body
  parse-string
  (get "artObjects")
  (->> (map #(get % "id"))))

bfabry19:11:28

that last bit is probably trickier than necessary and would maybe be better assigning the result of (get "artObjects") to an intermediate variable

roelofw19:11:37

oke, I see this output :

(get "artObjects"(parse-string(:body (client/get ""))))
=> nil 

roelofw19:11:09

and that looks not good to me

roelofw19:11:43

and in your code I see the ids

bfabry19:11:46

the get function takes the map as the first argument

roelofw19:11:58

oke, so I still need to make the map function

tom19:11:55

@roelofw one thing I do with cheshire is parse for keywords. Personal preference, but I find keywords to be more versatile. Then (-> (get ...) (parse-string true) :body :artObjects) is a second way to make it work.

slipset19:11:58

Is it correct that there is no doc-string for defmethod, only on defmulti?

slipset19:11:32

and if so, am I the only one missing the possibility to document the defmethods?

bfabry19:11:08

so long as there's no dynamic maps on the input I agree with tom on keywords

tom19:11:24

Creates and installs a new method of multimethod associated with dispatch-value.

bfabry19:11:04

s/dynamic maps/dynamic keys/

slipset19:11:07

@tom: I also looked at the source, but it didn’t really tell me that much, hence my question.

tom19:11:22

yea, it's pretty terse

slipset19:11:30

I guess the &fn-tail is an indication that there might not be a docstring.

slipset19:11:09

if you look at the corresponding defmacro for defmulti, docstring is mentioned, and handled.

tom19:11:27

Oh I see what you're saying. Defmethod has a docstring, but not defmethod.

slipset19:11:21

Thinking a bit further, it’d be kind of hard to do, since doc would then have to take a dispatch value to be able to show the right documentation.

slipset19:11:41

or (doc my-multi-fn) would have to show docs for all known defmethods with their corresponding dispatch value

Alex Miller (Clojure team)19:11:36

Defmethods don't have docstrings

slipset19:11:22

@alexmiller: thanks for confirming (and by waiting a bit, you let me figure out at least one reason why it is so)

jgh20:11:02

hi guys, im getting a pretty confusing error message trying to load a clj file in the lein repl:

CompilerException java.lang.Exception: Found lib name 'datomic-schema.schema' containing period with prefix '[datomic.api :as d]'.  lib names inside prefix lists must not contain periods
The offending code looks like this:
(ns stickar.auth-setup
    (:require [[datomic.api :as d]
               [datomic-schema.schema :refer :all]
               [stickar.common :as c]]))
Any thoughts on what I'm screwing up here?

jr20:11:58

you need to unwrap that first vector in :require

jr20:11:14

(:require [lib1 :as a] [lib2 :as b])

jgh20:11:54

Ah, oops. Thanks.

leontalbot20:11:39

Hi! could you help me translate this java code

leontalbot20:11:14

renderer.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator("{0}", NumberFormat.getInstance())) ;
into clojure?

leontalbot20:11:48

(.setBaseItemLabelGenerator renderer (StandardCategoryItemLabelGenerator. "{0}" (.getInstance (NumberFormat.))))

jr20:11:04

looks like NumberFormat.getInstance() is a static method

jr20:11:21

(NumberFormat/getInstance) is the appropriate way to call that

jgh20:11:14

jr's got us noobs

jr20:11:47

I get distracted when cljs is compiling 😛

roelofw21:11:45

someone who can help me with a problem in the beginners channel

fiddlerwoaroof23:11:16

What's a good library for authenticating users of a web application against facebook and/or google?

jgh23:11:08

clauth maybe

fiddlerwoaroof23:11:45

Hmm, that doesn't look maintained

jgh23:11:57

lmk if you find a decent one, i need one as well and was looking at clauth but havent really dug into it too much yet