Fork me on GitHub
#clojure
<
2017-02-16
>
bradford00:02:32

Heyas. Is there a more succinct way of doing

(apply merge (map-indexed #(assoc {} %1 %2) ) ["a" "b" "c"])
?

gfredericks00:02:42

(zipmap (range) [...])

bradford00:02:53

ohhhhhhhhhhh nice

bradford00:02:14

the beauty of laziness

alexbaranosky00:02:27

that's perdy 🙂

gfredericks00:02:14

@bradford I should point out that for a lot of things, a vector is equivalent to such a map

jamesy_source_clojure00:02:27

Hey @ channel Where are the best places to post Clojure gigs?

jamesy_source_clojure00:02:47

I'll drop it in announcements

jamesy_source_clojure00:02:18

strike that, I dropped it in #jobs check it out!

richiardiandrea00:02:11

is there an example somewhere for annotating and implementing an abstract class? does :gen-class provide that?

bradford02:02:21

@gfredericks Oh, I totally agree, but it's for a cranky bad API

Pablo Fernandez07:02:40

Am I using :prep-tasks correctly to run sass4clj? :prep-tasks [["cljsbuild" "once"] "javac" "compile" ["sass4clj" "once"]]. When I add sass4clj ti keeps on rebuilding ClojureScript over and over.

mpenet16:02:32

@richiardiandrea it might, but it'll get messy. You're probably better off writing a small clojure friendly java wrapper for it

borkdude16:02:18

Is there a macro that does this? (m a b c) ;=> {:a a :b b :c c}

residentsummer16:02:38

@borkdude once I needed this too

(defmacro ->map [& symbols]
  `(hash-map ~@(interleave (map keyword symbols) symbols)))

borkdude16:02:43

I started playing with your previous example @residentsummer . Now I wonder why (zipmap (:a :b) '(1 2)) is an empty map

borkdude16:02:50

but thanks 🙂

residentsummer16:02:26

you lost a quote on the first list

jr16:02:27

(zipmap '(:a :b) '(1 2))

borkdude16:02:05

another possibility is then:

(defmacro ->map [& symbols]
  (let [keywords# (map keyword symbols)]
    `(zipmap (list ~@keywords#) (list ~@symbols))))

residentsummer16:02:42

yep. don’t need hash for keywords# though

mpenet16:02:53

#(into {} (map (juxt keyword identity)) %) works too

mpenet16:02:27

Well as a macro... Not difficult to convert

borkdude16:02:15

Oh I see by using macroexpand what it’s doing

residentsummer16:02:42

borkdude: it's just a list of symbols at compile time, so no evaluation happens

borkdude16:02:50

right of course

borkdude16:02:09

(if I knew your twitter handle I would give you credit)

residentsummer16:02:33

spread the knowledge! 🙂

ccann16:02:03

I’m trying to run a compiled C script in my resources folder, does anyone know why I can’t slurp it and run it using (sh “bash” :in (slurp (io/resource “mycprogram”)))

rauh17:02:19

@ccann So bash expects a bash script but a compile C program will be machine code (ELF). I'm pretty sure you can't just run machine code that you have in java memory like this, unless you go very low level. Easiest would be to spit it into a file (give it the executable bit) and then run it (sh "/tmp/your-program")

borkdude17:02:18

What’s the easiest way to go from qualified keywords to unqualified in a map

borkdude17:02:38

{:foo/a 1} to {:a 1}

borkdude17:02:39

In Clojure 1.8

thegeez17:02:10

@borkdude isn't that just more syntax than {:a 1 😛 2}? What is the benefit of using ->map?

rauh17:02:34

(sp/transform [sp/ALL sp/FIRST] (comp keyword name) {:foo/bar 1}) if you use specter

bronsa17:02:16

(into {} (map (fn [[k v]] [(keyword (name k)) v])) {:foo/bar 1})

borkdude17:02:28

@thegeez I can now write:

(->map query-state
  database
  redis
  body)
instead of:
{:query-state query-state
 :database database
 :redis redis
 :body body}
Darn, now I wrote it by hand after all.

nathanmarz17:02:19

@borkdude with next release of specter:

user=> (setval [ALL FIRST NAMESPACE] nil {:foo/a 1 :bar/b 2})
{:a 1, :b 2}

nathanmarz17:02:35

@bronsa the problems with that approach are that it's slow and it changes sorted maps to unsorted maps

ghadi19:02:50

I've been wanting k-v transducers for a while. They're easy to make in userspace

borkdude19:02:12

Nested keys destructuring isn’t possible?

(let [{:keys [a {:keys [c] :as b}]} {:a {:c 2}}]
  [a b c]) ;;=> [{:c 2} nil nil]

ghadi19:02:37

not with the keys short-cut

ghadi19:02:47

and it wouldn't make it through code review 😉

gfredericks19:02:19

it'd be goofy because it'd only be allowed when you have :as and when the value of :as is a symbol

ghadi19:02:18

(let [{{bar :bar :as foo} :foo} ...])
unreadable

arrdem20:02:16

yeah.... never did like the nested destructuring notation :c

souenzzo20:02:35

(let [{{:keys [b]} :a} {:a {:b :ok}}] b) (let [{{b :b} :a} {:a {:b :ok}}] b)

borkdude20:02:31

@ghadi That works, thanks

ghadi21:02:19

i wouldn't recommend it @borkdude

pesterhazy21:02:51

why not? I use that style all the time

ghadi21:02:20

it's hard to read nested destructuring

ghadi21:02:36

doesn't scan well

zane21:02:15

I like core.match for this.

arrdem21:02:52

yeah core.match solves this problem pretty well

pesterhazy21:02:15

I like nested destructuring, it's one my favorite parts of Clojure's design

risto21:02:33

does core.match check for exhaustiveness? or at least is there a way to make it check for that?

dpsutton21:02:44

it always exhausts

arrdem21:02:49

core.match does not and cannot check for exhaustiveness

dpsutton21:02:52

but its because it adds a wildcard

arrdem21:02:02

^ yeah wildcards are the solution there

risto21:02:35

i guess you can simulate it with generative testing

risto21:02:25

is there a way to do something like this in clojure?

public class Foo {
  private String bar;
  public Foo(String bar) {
    this.bar = bar;
  }
}

risto21:02:40

i need it to be something I can construct dynamically

arrdem21:02:14

You can make anonymous vars, and there are now transient vals too

risto21:02:17

and the constructor variables need to be private and only accessible indirectly w/ methods I'm exposing

risto21:02:51

arrdem is there a way to do that with deftype?

arrdem21:02:06

not that I remember offhand.

risto21:02:26

actually it doesn't matter if it's deftype, just something that has that sort of functionality

risto21:02:46

I looked at gen-class, but I don't think it can do private variables

dpsutton21:02:14

what problem are you actually trying to solve?

dpsutton21:02:30

is it possible you've figured out a solution but there may be others out there?

arrdem21:02:54

So if this is really what you want then writing a custom Java class is probably the easy road. deftype doesn’t give you machinery for private mutable fields.

risto21:02:31

@dpsutton Under pretty much any other circumstance I wouldn't care about it being private

arrdem21:02:33

I should reformat that text...

risto21:02:40

but it needs to be private for this particular use case

dpsutton21:02:02

well that's easily done in closures

arrdem21:02:46

@risto: how are you trying to consume this … structure whatever it may turn out to be?

arrdem21:02:15

Is it a value? Are you expecting to consume functions of this value? Are you trying to transform / alter it?

risto21:02:26

it's going to basically be a macro that generates this data type

risto21:02:12

ideally it would be deftype but it's okay if I have to encapsulate it in an inner class of some kind. I'm not sure a java class would work because it needs to be constructed dynamically

arrdem21:02:20

right no but what problem are you trying to solve that this appears to be the solution to you.

arrdem21:02:42

You really don’t want to be generating Java classes truly dynamically.

arrdem21:02:02

That’s gonna be total garbage for performance and very strange code in general.

hiredman21:02:35

have a requirement that a field be private is fishy to me

risto21:02:17

it needs to be private because I need to restrict how the developer interacts with arguments passed into the data type

hiredman21:02:26

the jvms private is easily overridable using reflection, it is really just a comment showing intent that the compiler checks

risto21:02:32

they can't just fetch the inner member because it would break the encapsulation that I need

arrdem21:02:37

If you really want a hidden value that can be accomplished… but this seems like the wrong way to do this.

hiredman21:02:49

if they want to fetch it, you cannot stop them

arrdem21:02:06

What’s the library? wallhack?

hiredman21:02:13

sure wallhack

risto21:02:19

what's wallhack?

risto21:02:14

well the difference between just a property access vs using something like wallhack is that, you know you're already that you're trying to access something you aren't supposed to

risto21:02:39

but if it's just something you can easily access then you can easily accidentally do that if you aren't aware

dpsutton21:02:12

you could do like sicp, encapsulate a value and return a dispatch function that dispatches on keywords

hiredman21:02:31

closed over data is in fields

risto21:02:45

@dpsutton how does that look like?

risto21:02:21

if the user could access the data directly, then the abstraction I'm trying to write would be leaky in pretty horrible ways

arrdem21:02:09

@risto what access model are you trying to accomplish? An opaque session object?

hiredman21:02:32

user=> (def f (let [x 1] (fn [] (+ x 1))))
#'user/f
user=> (f)
2
user=> (->> (class f) (.getDeclaredFields) (map (fn [field] (.setAccessible field true) [(.getName field) (.get field f)])) (into {}))
{"const__0" #'clojure.core/+, "const__1" 1, "x" 1}
user=> 

hiredman21:02:23

I think the const__ fields are already public, and closed overs are marked private

dpsutton21:02:45

i don't think we're going for absolute secrecy but just a clear "don't touch that or else things can break" idea here

dpsutton21:02:02

but i still think you don't need to worry about it

hiredman21:02:10

(defrecord Foo [dont-touch-this-or-things-can-break])

dpsutton21:02:30

and way less awkward than the "dispatch" function style

risto21:02:31

yeah that's not going to work

borkdude21:02:10

@zane > I use core.match for this Can you give an example that looks like mine? Not sure how you use it

arrdem21:02:56

(let [a {:a {:b 3}}] (match a {:a {:b x}} x :else nil))

arrdem21:02:35

9X% confident that’s the correct syntax, the match form has some magic for allowing either a single value or a vector of values to be matched against.

borkdude21:02:46

ah nice, I’m going to give it a try

arrdem21:02:13

If you wanna see some real core.match use, lib-grimoire is mostly core.match in a very Haskell style.

arrdem21:02:34

I have an entire DB query engine implemented in core.match because bad reasons

borkdude22:02:50

Why does this work:

(match {:a {:b 1}} {:a {:b x}} x)
but this doesn’t:
(match {:a {:b 1}} {:a {x 1}} x)
, because values aren’t unique in a map?

arrdem22:02:29

if x were closed over from an outer scope I think that would work.

arrdem22:02:46

core.match does not do search for values which would match in a logic programming style.

bradford22:02:10

Hi! Is there a more succinct way of counting occurrences of a vector of strings than

(apply merge (map #(let [mat (re-seq (Pattern/compile %1) "a a b b c c")]
               {(first mat) (count mat)}
               ) ["a" "b" "c"]))

risto22:02:53

whats the difference between core.match/match and core.match/matchm? I think there are some other ones in the code also

bradford22:02:55

seems reduce-y

arrdem22:02:17

bradford: isn’t there a count-by

dpsutton22:02:45

> Same as match but supports IMatchLookup when matching maps.

bradford22:02:49

hrm there's a frequencies

bradford22:02:19

but the apply-merge-map still feels crufty, it's something I do a lot of

arrdem22:02:01

@bradford

(defn count-by [f coll]
  (reduce (fn [acc x]
            (update acc (f x) (fnil inc 0)))
          {} coll))

gfredericks22:02:46

(def count-by (comp frequencies map))

sophiago22:02:32

quick question: is there a way to use alias (or similar) to remove an alias? in other words, make it as if the library was required without the :as keyword? using unalias seems to remove access to the library entirely, unless i'm confused and it's a matter of reloading it afterwards

hiredman22:02:34

unalias just removes the alias, so you must be confused

hiredman22:02:57

you can refer to a name in any loaded namespace using a fully qualified name

hiredman22:02:40

you are maybe looking for refer, not aliases

hiredman22:02:30

in the absence of an alias, you have to use the fully qualified names, you don't get the short names you get from refers

sophiago22:02:42

to explain the reason i'm interested in this, i want to toggle between two versions of functions in different namespaces and previously would be like (doto 'namespace2 require in-ns). someone suggest i instead require it from the start and then toggle the alias on and off, but i'm having trouble figuring out how to toggle if off...in other words, make it as if i had required it without an alias to begin with

hiredman22:02:19

you will need to reload code

arrdem22:02:19

So that’s not gonna do what you want.

hiredman22:02:29

vars are resolved at compile time, not runtime

arrdem22:02:28

The aliases table is used only when resolving Vars at compile time to find aliased namespaces. Once a function has been compiled, it is linked statically-ish against fully named Vars in the namespace where they are defined.

sophiago22:02:36

does that mean it doesn't make sense to even do it this way then?

sophiago22:02:56

perhaps i'm saving overhead when i toggle back to the first namespace

arrdem22:02:09

Yeah. If this is what you want, you’re gonna want some sort of API object or map of names to functions to pass around.

sophiago22:02:04

i'm not sure what you mean. wouldn't i want to simply want to require it only when i toggle it on and then remove the entire ns when i toggle it off? which would be a slight improvement over do-to since the initial namespace will remain loaded the entire time and just have its functions overriden

arrdem22:02:56

A namespace is a mechanism for resolving names to functions. So if you take a step back, if you have a function defined in terms of a thing you refer with an alias from a namespace, that’s a full application of a function which would accept the thing you’re referring as an argument and return a function that does the thing you want.

sophiago22:02:19

i wouldn't be aliasing them

sophiago22:02:35

but it doesn't seem to override them unless i actually switch namespaces

arrdem22:02:10

I’m sorry you want functions that behave differently depending on what namespace you’re in?

sophiago22:02:09

i want to stay in the same namespace and be able to toggle whether they're overridden by those in an another one

sophiago22:02:04

i had the toggle functions switch namespaces to achieve this same effect effect before and someone suggested i try this instead

arrdem22:02:06

So what I’d do is I’d change my functions so that they take as an argument (probably the first argument) a map of keywords to functions, destructure it and call the functions which were destructured out. You can then define two API maps, one for the functions in the current namespace and one for the implementations elsewhere. This way you can switch back and forth between which implementations you’re using without any mucking with namespaces or compilation.

sophiago22:02:59

i think you're confused about what i'm doing here

sophiago22:02:07

the functions are (some-thing-off) and (some-thing-on). i don't know why i'd have a function where i pass it the names of ~100 other functions to achieve this

sophiago22:02:39

i already implemented it one way that's fine, but now i'm asking specific questions about how to implement it another way

sophiago22:02:19

specifically, how to have a function that requires a library so that it overrides functions

arrdem22:02:24

Because of Clojure’s namespace and compilation model as explained above, you can’t make such a function which doesn’t also (require :reload) the namespace you’re currently in.

sophiago22:02:59

i see. so then the best way is exactly as described before then right?

arrdem22:02:47

The “best” way is not to do this at all as I’ve been trying to say, but if this is specifically what you want to do and what you desire to improve, no there isn’t a better way.

sophiago23:02:01

yeah...i do actually need to meet specifications

sophiago23:02:18

and it seems like the worst possible solution to have a function that's 100s of words long

sophiago23:02:25

i guess there's a question of whether i's better to do (doto 'namespace2 require in-ns) or (ns namespace2 (:require [namespace2]))

ericfode23:02:18

Hello! I need some help… I am getting this error

main   │ Caused by: java.lang.NoClassDefFoundError: snow_client/core/Tabel
main   │ 	at service_now_bot.service$evs_for_tag.invokeStatic(service.clj:100)
main   │ 	at service_now_bot.service$evs_for_tag.invoke(service.clj:97)
main   │ 	at service_now_bot.service$fetch_and_enrich.invokeStatic(service.clj:138)
main   │ 	at service_now_bot.service$fetch_and_enrich.invoke(service.clj:133)
main   │ 	at service_now_bot.service$snow_page.invokeStatic(service.clj:150)
main   │ 	at service_now_bot.service$snow_page.invoke(service.clj:146)
main   │ 	at io.pedestal.interceptor$fn__1366$fn__1367.invoke(interceptor.clj:41)
main   │ 	at io.pedestal.interceptor.chain$try_f.invokeStatic(chain.clj:52)
main   │ 	... 39 common frames omitted
main   │ Caused by: java.lang.ClassNotFoundException: snow_client.core.Tabel
main   │ 	at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
main   │ 	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
main   │ 	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
main   │ 	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
main   │ 	... 47 common frames omitted
when i am running my app from a uberjar but not when i run it in the repl

ericfode23:02:33

If anyone has any ideas i would really love some 🙂

blmstrm23:02:08

@ericfode Hi! After running lein uberjar which one of the jar files generated do you run? I don't know why but I've always been lucky running the jar file that doesn't have my version number in the name, if you now what I mean, as an example: mygreatapp-0.1.1-SNAPSHOT.jar wouldn't run but mygreatapp.jar would.

ericfode23:02:25

The one taht ends with SNAPSHOT-standalone

blmstrm23:02:38

Give the other one a try

ericfode23:02:36

I get

main   │ Exception in thread "main" java.lang.NoClassDefFoundError: clojure/lang/Var
main   │ 	at service_now_bot.server.<clinit>(Unknown Source)
main   │ Caused by: java.lang.ClassNotFoundException: clojure.lang.Var
main   │ 	at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
main   │ 	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
main   │ 	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
main   │ 	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
main   │ 	... 1 more
➜  service-now-bot git:(master) ✗

ericfode23:02:40

When i do that

ericfode23:02:13

It’s possible i constructed my library wrong when i released it

arrdem23:02:35

So that’s easy… Clojure itself isn’t on your classpath somehow.

ericfode23:02:17

@arrdem that makes sense. I am trying to get it into an uberjar so i can put it in a docker file

arrdem23:02:18

the -standalone jar is the one you want....

arrdem23:02:08

The first stacktrace you posted is an AOT problem, you’re referencing a class (`snow-client.core` contains a deftype or something it looks like) before the Clojure code which defines it has been executed.

ericfode23:02:09

Orly? how do i fix

arrdem23:02:53

also do a lein clean

hiredman23:02:59

(that doc explains starting a clojure programming with aot compilation, which is 95% of the reason people give for needing to aot compile)

ericfode23:02:57

ok i got it to work with lein run, but not lein uberjar, that now gives me this Warning: The Main-Class specified does not exist within the jar. It may not be executable as expected. A gen-class directive may be missing in the namespace which contains the main method.

hiredman23:02:35

right, you didn't remove :main

hiredman23:02:08

now, turning off aot compilation won't necessarily immediately fix things, but it will unmask underlying issues