Fork me on GitHub
#clojure
<
2017-07-27
>
josh_tackett01:07:07

I know this is a clojure channel but maybe someone will know the answer. I'm trying to ssh into a server, run a shell script, and the disconnect from the server and have the script continue to run

norman02:07:30

ssh + nohup?

qqq03:07:54

#off-topic 🙂

gonewest81803:07:41

tmux or screen

hmaurer11:07:35

Hello! I am reading clojure.core’s source cdoe and the beginning confuses me. Could someone explain this out?

;during bootstrap we don't have destructuring let, loop or fn, will redefine later
(def
  ^{:macro true
    :added "1.0"}
  let (fn* let [&form &env & decl] (cons 'let* decl)))

hmaurer12:07:11

@U61HA86AG what is the difference with fn? Also, why is let defined as a macro? I thought it was a special form

sundarj12:07:45

likewise, let is a macro that calls out to the special form let*

hmaurer12:07:17

@U61HA86AG ah, I see. So special forms are always followed by a *, but for easy of use there is a non-starred version

hmaurer12:07:31

Follow up question: what is the use of adding a name to an anonymous function?

hmaurer12:07:36

e.g. (fn foo [x] ...)

hmaurer12:07:04

ah nevermind, got it, stack traces 🙂

sundarj12:07:02

and the non-starred version is more than just convenience, it also lets you do e.g. (doc let)

hmaurer12:07:54

@U61HA86AG when I do (doc let) it says let is a special form, but in reality it’s a macro which expands to a special form. I assume there is some magic going on here; where is it?

sundarj12:07:43

well if you look here https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L193 it uses let, but defmacro hasn't been defined yet

sundarj12:07:20

think the first let is a barebones version

sundarj12:07:48

yeah, so the first let only has the functionality needed to bootstrap the rest of clojure, and then later on it gets the rest of its functionality via defmacro

hmaurer12:07:58

interesting

hmaurer12:07:05

thanks for explaining this out @U61HA86AG 🙂

sundarj12:07:16

no problem! any time

hmaurer11:07:40

there are a number of those declarations

hmaurer12:07:52

Is there a std lib function to pick a number of keys out of a map? e.g. Map -> [Key] -> Map

bronsa12:07:31

select-keys

hmaurer12:07:28

@bronsa thanks! I really miss a Hoogle-like tool for Clojure 😞 https://www.haskell.org/hoogle/

souenzzo21:07:29

will be possible with spec 😉

kurt-o-sys13:07:06

I'm trying to use transducers... The original code:

(->> m 
     (map :my-key)
     (map #(clojure.edn/read-string %)) )

kurt-o-sys13:07:07

translating to transducers:

(let [xf (comp (map :my-key)
                (map #(clojure.edn/read-string %))))]
  (transduce xf concat m)
This gives a stackoverflow error...

kurt-o-sys13:07:13

oh wait... it's not the same.

kurt-o-sys13:07:04

concat gives that stackoverflowerror...

kurt-o-sys13:07:36

funny... I read that last week. stupid me 😛

kurt-o-sys14:07:44

well, actually it's (flatten (into [] xf m) I was after.

rarous14:07:30

@kurt-o-sys or second map should be mapcat 🙂

misha15:07:13

is there something builtin or better for this?

(defn least-common-ancestor [path1 path2]
  (let [i (min (count path1) (count path2))]
    (reduce
      (fn [p idx]
        (let [v1 (nth path1 idx)
              v2 (nth path2 idx)]
          (if (= v1 v2)
            (conj p v1)
            (reduced p))))
      [], (range i))))

(least-common-ancestor
  [:a :b :c]
  [:a :b :d])
=> [:a :b]

rauh15:07:44

@misha (take-while some? (map (fn [a b] (when (= a b) a)) [0 1 2] [0 1 3]))

the-kenny15:07:06

This one has much better runtime performance, mostly stemming from the omission of nth

rauh15:07:54

Well you could avoid one nth call here if you use reduce-kv and you can guarantee it's a vec

misha15:07:43

not worth it. on the other hand, count being > 10 is highly unlikely (in my case).

rauh15:07:11

Yeah then the map version will be quicker. Reduce is often slower for smallish input

rauh15:07:33

And if you want to avoid the intermediate sequence: (sequence (comp (map #(when (= %1 %2) %1) ) (take-while some?)) [0 1 2] [0 1 3])

misha15:07:19

@rauh on such small inputs it is not worth it:

(time  (dotimes [n 1000]    (take-while some? (map (fn [a b] (when (= a b) a)) [0 1 2] [0 1 3]))))
"Elapsed time: 1.166446 msecs"
(time  (dotimes [n 1000]    (sequence (comp (map #(when (= %1 %2) %1) ) (take-while some?))   [0 1 2] [0 1 3])))
"Elapsed time: 7.258858 msecs"

rauh15:07:30

@misha Don't forget a doall 🙂

misha15:07:23

(time  (dotimes [n 1000]    (doall (take-while
"Elapsed time: 3.356031 msecs"

misha15:07:22

omg what am I doing right now?

noisesmith17:07:10

if you want to measure calculation time (or run for side effects) and don’t need the result, use dorun instead of doall

noisesmith17:07:45

also, sequence is not typically more efficient than regular lazy ops in most cases iirc

cpmcdaniel20:07:44

So this is fun: when using postwalk, map entries are just vectors (so map-entry? returns false), so there is no way to distinguish a map entry from a map value that is a vector… Anyone else run into this?

cpmcdaniel20:07:40

I suppose a map key could also be a vector, which adds a 3rd case of ambiguity

seancorfield20:07:53

@cpmcdaniel It's a known issue in JIRA...

cpmcdaniel20:07:23

@seancorfield say no more, and thank you

seancorfield20:07:03

(go vote for it!)

cpmcdaniel20:07:38

ah, prewalk works for my use case

cpmcdaniel20:07:04

(and I voted)

noisesmith20:07:54

if I am implementing something that is meant to be used in place of a function, is it enough to implement IFn or should I implement AFn too?

hiredman20:07:51

it sort of depends on how you are implementing it, AFn is an abstract class so dealing with it from clojure is kind of a pain, but from java that is where I would start

noisesmith20:07:10

OK - this is clojure code, so I hope I’m safe ignoring AFn

hiredman20:07:17

AFn provides defaults for a lot of things like the applyTo machinery and such

hiredman20:07:43

I often will implement IFn and just particular invoke arity that I expect to be used

hiredman20:07:58

but such an object will not always behave like a function

hiredman20:07:30

I think apply won't work, and you will get some weird brokeness with more than 20 args, and maybe fn? will return false

noisesmith20:07:46

yeah - this is a macro implementing generally something you recommended earlier (making a record that can be called like a function but unlike a lexical closure you can also look at the data in its keys) - trying to make it a convenient to use replacement for code that uses partials extensively

noisesmith20:07:38

I just verified I implemented things properly to make apply work for over 20 args

noisesmith20:07:01

but returning false for fn? is acceptable

hiredman20:07:29

I think you can fix that too, if I recall fn? checks some marker interface

noisesmith20:07:48

instance? clojure.lang.Fn

noisesmith20:07:16

easy enough to extend that, it has no methods

noisesmith20:07:27

thanks - I think this will be a handy little one macro lib, just need a snappy marketable name

tbaldridge20:07:54

@noisesmith big note: you probably want ifn? if you want to check if something is a function. fn? does something different (and is normally wrong, imo).

noisesmith21:07:15

@tbaldridge so if I am making something that is a drop in replacement for a function returned from partial, would it be a bad idea to make fn? return true from someone else’s check?

noisesmith21:07:33

I guess that’s a style issue

tbaldridge21:07:32

nah, just code against IFn, and then ifn? will return true, which is what most people should be using

noisesmith21:07:44

@tbaldridge on thing though, in my code, checking ifn? would lead to surprising results here

=> (ifn? :hi)
true

noisesmith21:07:09

that could be a sign of doing other things wrong I guess…

ghadi21:07:19

that doesn't surprise me, a keyword is a function

ghadi21:07:22

I suppose the fn? stole the good name early, but had the wrong semantics

tbaldridge21:07:58

yeah fn? really means "something that was created with (fn ...)"

hiredman21:07:41

fn? was added when trampoline was added

hiredman21:07:55

continue-trampolining?

noisesmith21:07:59

yeah, I guess the answer of (defmulti foo first) (fn? foo) can be a guide there

ghadi21:07:31

----------------------------------------------- Sooooooooo who here has played with tools.deps.alpha and what do they think? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

dpsutton21:07:03

i looked at the version compare and it seems like it will return 1.1 > 1.9

dpsutton21:07:30

but i don't know how to crank it up since it's based on the pom file rather than a project file

hiredman21:07:37

10541c0254973ce045305499d4b5622073ede622 (is the trampoline commit fyi)

dpsutton21:07:42

i'm not a java guy

dpsutton21:07:57

it also specifies its own deps in the new edn format. does that make it "self-hosted"?

ghadi21:07:48

@dpsutton if you have mvn installed you can crank it up using the commands in the README. Use of mvn/pom is a one-time thing at setup. (It will probably be handled by the package manager when this stuff filters over there)

dpsutton21:07:06

thanks. i'll get that going tonight

dpsutton21:07:49

yeah i wanted to play with it and do a PR for

;; TODO - choose better
(defn- choose-coord
  [coord1 coord2]
  (if coord1
    (if coord2
      (let [v1 (:version coord1)
            v2 (:version coord2)]
        (if (pos? (compare (str v1) (str v2)))
          coord1
          coord2))
      coord1)
    coord2))

ghadi21:07:01

once you have it installed, you can use it in a project folder (using $PWD/deps.edn) or globally (using $HOME/.clojure/deps.edn)

ghadi21:07:41

The version comparison seems intentionally naive, no need to poke fun at that yet 😃

dpsutton21:07:57

oh i know. i wasn't doing it in the notion of sniping

ghadi21:07:57

If you specify versions explicitly you won't invoke that code

dpsutton21:07:13

but let alex and others figure out the hard stuff and I could help out with the easy solved stuff

hmaurer21:07:24

I would like to write a function (if possible with the stdlib) to check if a map “matches” a pattern. More specifically, I would like to describe a map in terms of another map with the same structure, whose values can either be ints/bools/strings or regexs. If the value are ints/bools/strings they they should be compared for equality with the target map, and if they are regexs they should match

dpsutton21:07:34

i meant "take this off their plate" not like "i can't believe they coded this"

ghadi21:07:16

i know 😃 I wonder what lein and boot do

ghadi21:07:07

that might be useful from the same library that tools.deps already uses

ghadi19:07:53

^ that GenericVersionScheme already proved useful

ghadi19:07:19

you can't override the broken spec.alpha reference from 0.1.94 to 0.1.123 right now, because the comparator is busted

hmaurer21:07:55

e.g.

{:first-name "john"
 :last-name #".*"}
should match
{:first-name "john"
 :last-name "doe"}

hmaurer21:07:07

it should work for deeply nested maps

hmaurer21:07:24

(I would use it to write tests checking the expected output of an API)

hiredman21:07:31

there are a few options

hiredman21:07:37

(for the map thing)

hmaurer21:07:45

mmh yes specs would work but it seems a bit overkill for what I need

hiredman21:07:01

you could just take two maps, the first being the shape and the second being the data and recurse through them

hmaurer21:07:26

@hiredman that’s precisely what I’m wondering how to do. Is there an easy way to express this recursion procss with stdlib functions?

hiredman21:07:28

you can take the description map and turn it to into a sequence of paths and predicates and reduce over that with the data

hmaurer21:07:48

or to turn it into a sequence of paths

hiredman21:07:22

(defn f [m1 m2]
  (letfn [(g [p m]
            (if (map? m)
              (for [[k v] m
                    i (g (conj p k) v)]
                i)
              [[p m]]))]
    (reduce
     (fn [x [path predicate]]
       (and x (predicate (get-in m2 path))))
     true
     (g [] m1))))

hiredman21:07:32

dictated but not read, etc

hiredman21:07:01

that assumes the description map is a map of keys to predicates, so you will have to change it to do your regex and = compares instead

hmaurer21:07:31

great. It’s sane to convert it to a map of predicates anyway

hmaurer21:07:32

thank you!

hmaurer21:07:01

I was thinking of writing my tests in a descriptive form as EDN, using tags for different types of predicates

hmaurer21:07:03

(e.g. regex)

hmaurer21:07:42

with your approach it should extend nicely to other predicates

mordus23:07:46

Is there a protocol I can implement to get peek/pop/conj to work on a queue like datastructure I'm building?

hiredman23:07:09

conj maps to the cons method of IPersistentCollection java interface

hiredman23:07:49

peek and pop map to the IPersistentStack java interface (with the same method names)