Fork me on GitHub
#clojure
<
2017-02-26
>
qqq02:02:15

touch = update time stamp of a file; does clojure have a builtin for touching a file, or do I need to make a sytem call to call the touch command ?

imborge02:02:07

I don't think it has

qqq02:02:18

clojure.java.shell/sh it is then

qqq02:02:50

how do I convert a java.util.Collections to a list or a vector?

qqq02:02:04

so in particular, I have an object of type Enumeration<String> (from Java)

qqq02:02:20

and I want to convert it to a list of strings or vector of strings

qqq03:02:23

eumeration-seq

paulocuneo03:02:13

qqq: yeah that you should work! For trivial parsing im use to do just. "a b c".split("\\s+") in java.

paulocuneo03:02:37

for non trivial i suggest taking a look, https://github.com/Engelberg/instaparse

qqq03:02:02

why are we talking about parsing?

qqq03:02:24

the context of my question was actually http servelets, doGet, and reading out arguments (not using ring, doing stuff in java apis)

paulocuneo03:02:53

sorry, i missed that, and just thought you splitting a string, java docs for enumeration encourage to use Iterable/Iterator

qqq03:02:18

I should have provided more context:

qqq03:02:33

which returns Enumeration<String> which I then have to enumeration-seq it in clojure

paulocuneo03:02:24

Enumeration? i thought that was deprecated. If the collections implements Iterable , you can do: (seq coll)

qqq03:02:43

I'm using Java 7 still

qqq03:02:46

are you using Java 8?

paulocuneo03:02:01

Enumeration is from like java 1

qqq03:02:18

yeah, but you're claiming it's deprecated

qqq03:02:25

and if you're on 8 while I'm on 7, it may be because it was deprecated in 8

paulocuneo03:02:27

its not, but is more common to use Iterables from java 5 forward

qqq04:02:17

when using webservers in clojure, can I directly reply with edn, or do I have to do clojure dta -> edn -> wrap it in a singleton json string ?

qqq04:02:31

how does transit and edn compare for client/server communicating?

dvingo04:02:48

this is a good overview

dvingo04:02:53

the short answer is to use transit

qqq04:02:02

yeah, the 10x-20x stuff convinced me

qqq04:02:18

http://cognitect.github.io/transit-clj/ mentions:

Usage: (writer out type)
       (writer out type {:keys [handlers]})
Creates a writer over the provided destination `out` using
the specified format, one of: :msgpack, :json or :json-verbose.

An optional opts map may be passed. Supported options are:

:handlers - a map of types to WriteHandler instances, they are merged
with the default-handlers and then with the default handlers
provided by transit-java.
is there any preference between msgpack, json, and json-verbose ?

urbank09:02:29

Not a strictly clojure question, but is it correct to say that (-> col (map f) (filter g)) is more efficient if the map and filter functions are lazy?

mpenet09:02:08

map and filter are lazy, f isn't

mpenet09:02:25

(lazy as in potentially chunked etc etc, because.. clojure)

urbank09:02:55

Yes, I meant map and filter. So my assumption is that it's closer to O(N) than it would be if map and filter were strict

mpenet09:02:16

nowadays you're better of using transducers when you have to chain map/filter & co, when you're looking to optimise things at least

urbank09:02:24

So transducers basically solve the problem of intermediate collections, so that the number of passes doesn't go up with the number of filter/map/reduce... you want to apply, right?

urbank09:02:15

So that it's more similar to a very specialized for loop

urbank09:02:26

and not a series of for loops

urbank09:02:21

Which I suppose is something like what the haskell compiler does

mpenet09:02:28

you still get chunkiness depending on how the seq was produced, but you at least skip intermediary seq instance creation

mpenet09:02:05

but depending on how you realize them (via sequence or into) you can make it totally eager

mpenet09:02:24

ex via (into (empty xs) xform xs)

mpenet09:02:03

depends on range in that case for chunkiness, but sequence respect lazyness of the underlying seq compared to into

urbank09:02:04

Right, very nice. It always bothered me that I need to do multiple full passes on a collection when doing something very specific

mpenet09:02:26

in most case it's not that important tbh, but sometimes it helps

urbank09:02:53

Yeah, I know. It still irks me (which perhaps is more my fault 🙂 ). And there have been a few times where it was a problem

pwrflx11:02:49

hi! what should I do in cider after editing project.clj with a new dependency? restart emacs and do a cider-jack-in or is there some better solution?

andrea.crotti12:02:47

@pwrflx you never need to restart Emacs 😉

andrea.crotti12:02:00

M-x cider-restart is enough

istvan17:02:23

hey guys I am trying to iterate over a vector and create a channel with all of its elements, what is the best way of doing that in a let block?

istvan17:02:36

;(let [names [:a :b: :c]] (doseq [chan-name names] (let [cn (name chan-name)] (def cn (chan)))))

istvan17:02:23

this looks so convoluted

joshjones17:02:31

(let [c (chan)
      v [1 2 3]]
  (a/onto-chan c v)
  c)

istvan17:02:50

joshjones i am trying to dynamically create 3 channels

istvan17:02:03

(doall (for [x ["a" "b" "c"]] (eval `(def ~(symbol x) 666))))

istvan17:02:20

(doseq [x ["a" "b" "c"]]
  (intern *ns* (symbol x) 666))

istvan17:02:30

just found it on SO

joshjones17:02:22

this does exactly that, unless you are not saying correctly what it means to "dynamically create 3 channels":

(defn get-chan
  [v]
  (let [c (chan 1 (map name))]
    (a/onto-chan c v)
    c))

(let [c (get-chan [:a :b :c])]
  (<!! c))

joshjones17:02:28

you can def there if you want, but why would you want to?

joshjones17:02:14

creating global state from a function is allowed, but usually a bad idea and unnecessary @istvan

pwrflx18:02:13

is there a way to show parameter info in CIDER? eg show the documentation of the parameter I'm about to enter for the current function call.. I mean something that is similar to CTRL+P in IDEA

dpsutton18:02:00

can you explain what you mean about documentation of the parameter?

dpsutton18:02:24

for instance, in CIDER, it uses eldoc to show the signature of a function as you type and will bold the parameter that you are currently on

dpsutton18:02:44

but there is no convention that lumps documentation about parameters that i know of in clojure

pwrflx18:02:09

@dpsutton : ah ok! then eldoc is what I need! 😄 I've seen it on the modeline of some youtube tutorials but never cared to install.. I'll look into it! thanks!

istvan18:02:21

joshjones this is exactly what i want:

istvan18:02:24

plugflow.main=> (doseq [x ["a" "b" "c"]] (intern *ns* (symbol x) (chan)))
nil
plugflow.main=> a
#object[clojure.core.async.impl.channels.ManyToManyChannel 0x35aab37b "clojure.core.async.impl.channels.ManyToManyChannel@35aab37b"]
plugflow.main=> b
#object[clojure.core.async.impl.channels.ManyToManyChannel 0x271ce487 "clojure.core.async.impl.channels.ManyToManyChannel@271ce487"]
plugflow.main=> c
#object[clojure.core.async.impl.channels.ManyToManyChannel 0x6011ced2 "clojure.core.async.impl.channels.ManyToManyChannel@6011ced2"]

istvan18:02:49

create 3 channels using the names a b and c

istvan18:02:49

a b and c coming from a configuration file

istvan18:02:26

it does not need to be global, it can live in my (let [] )

istvan18:02:52

is this what your code does too?

dpsutton18:02:58

if it's not global, but only in the let binding, what do you care what they are named?

dpsutton18:02:53

and i don't mean that in a rude way, but if they exist inside of your let binding, why can't you just refer to them with whatever name you like?

istvan18:02:15

because i do not know them in advance

istvan18:02:51

users can use different names they like

dpsutton18:02:01

but it's running in your code, right?

dpsutton18:02:34

can you post a snippet of where you're using them?

dpsutton18:02:47

i just can't imagine a scenario where the name of a variable should be relevant

dpsutton18:02:27

but if you need to take three channels in from a consumer of your code, why not make a function that takes three channels as input?

dpsutton18:02:34

or perhaps let them make a map of channels

istvan18:02:52

because my customer uses N channels

istvan18:02:12

and because my customer names the channels as she wishes

dpsutton18:02:42

and you want to go on the convention that the var name of the channel is how they are bound?

istvan18:02:57

it is going to be customer_name-chan

istvan18:02:06

for example user-chan

istvan18:02:26

and later in the code i create a thread which reads it

istvan18:02:48

i will show you the code when it is done, not yet 🙂

dpsutton18:02:05

and you are searching through the ns-vars that are already interned to see which chans are created?

seancorfield18:02:30

(this sounds like you should use a map of names to channels — not actual named vars)

dpsutton18:02:45

yeah. my point is that the interned vars are just a map

dpsutton18:02:51

so why not create your own map and use that

istvan18:02:29

seancorfield would you mind giving me an example, i always learn from those

istvan18:02:31

you would use {:name1 (chan) :name2 (chan) } ?

joshjones18:02:42

@istvan so, the customer gives you a channel name, call it "xyz". You have a global atom that maps "xyz" and all other names to a channel

joshjones18:02:43

(def chan-map (atom {}))
(defn add-chan
  [m n]
  (swap! m assoc n (chan)))

(add-chan chan-map "xyz")

joshjones18:02:00

to add a lot:

(run! #(add-chan chan-map %) ["chan-name1" "xyz" "abc"])

istvan18:02:47

alright i am going to try this

dpsutton18:02:49

if your code breaks because they name their chan something then you have bad code

dpsutton18:02:03

further, what if they haven't named the var anything at all really

dpsutton18:02:16

(call-your-code (chan 1))

dpsutton18:02:22

would have no pleasant name at all

dpsutton18:02:45

i really think your structure of recovering logic flow of your program from variable names is a bad first attempt

istvan18:02:03

dpsutton absolutely, great point

dpsutton18:02:24

maybe setup a contract of something like this?

dpsutton18:02:55

{:company-name "company xyz"
 :channel-type :reporting
:channel (chan 1)
}

dpsutton18:02:09

take in a map with all of the information that you need

dpsutton18:02:14

and note that this offers no security

istvan18:02:13

alright i give it a try

istvan19:02:28

thank you guys, i just rewrote the code using a map for the channels and it works! 🙂

joshjones20:02:26

@istvan you will be happy that you did it this way, or rather, you will never know the unhappiness you saved yourself by doing it this way 😉

istvan20:02:28

i already hit a roadblock with my first solution 😄

istvan20:02:17

since clojure keywords are lookup functions you can just use the keyword and lookup pretty easily something in a map

joshjones20:02:40

this is one reason why keywords are the most common types of keys in maps. if you use a string as a key though, you can also easily do (get map' str-key), to avoid converting between str<->keywords. but yes, keywords work well

keymone20:02:54

are there convenient clojure wrappers for java.lang.Process?

hlolli21:02:09

(let [a 1 b 2]
  (let [{:keys [a b]} {:a 3}]
    [a b]))
=> [3 nil]
is there any way to destructure conditional let. So redefine local bindings if the key exist in a map otherwise nothing? So that it would return [3 2]?

mfikes21:02:39

@hlolli My first inclination to solve your problem is to throw an :or {b b} in there.

mfikes21:02:10

(let [a 1 b 2]
   (let [{:keys [a b] :or {b b}} {:a 3}]
     [a b]))

hlolli21:02:53

bingo! @mfikes thanks! (This calles for a macro, want to do this with lots of keys 🙂)

keymone21:02:38

@mfikes yes, but that’s for shell commands that exit immediately, i need one for long-running processes that can deal with pipes etc