Fork me on GitHub
#clojure
<
2018-02-05
>
aengelberg00:02:42

Will there be a Clojure/West this year?

moxaj00:02:53

@qqq or eval, but that's uglier

whilo00:02:46

hey. i don't want to interrupt, but i don't get how you all can accept the loss of history on slack. this is one of the most important features for me to go back and look things up later if they become relevant again. i understand convenience, but this is really odd because there are alternatives out there. gitter for instance is still running fine and there are things like mattermost. i just wanted to look up a complaint somebody had about my library and now it is gone and instead i am told to pay... the message archives also don't work anymore here btw. last update 2017-11-16.

whilo00:02:00

but they wouldn't work for the private message i am missing right now anyway.

qqq00:02:04

I think it's a matter of activation energy required to get everyone to switch over.

qqq00:02:30

Can you build a "bridge bot" to shuffle msgs between gitter & slack? That might do it.

qqq00:02:04

@moxaj: (class/forName class-name) got me the Class

whilo00:02:25

i am not sure what the best alternative is

whilo00:02:34

but this feels really odd, being a programmer and then being abused by a paywall in such a ridiculous manner. not only is my whole communication outsourced, but i basically lose access to it and it is privatized.

whilo00:02:56

i think it boils down to somebody having to run a piece of software for the chat server.

whilo00:02:29

it would be really nice if it would be written in clojure and open source ofc. but i am pragmatic there.

whilo00:02:28

(well open-source for core communication infrastructure should be standard, but it needn't be clojure)

justinlee00:02:04

@whilo I seems to remember that the logging is still happening but the thing that updates the searchable slack log page is broken. My memory is that someone is working on it and is trying to get the program that does it in a state where the community can keep it maintained. This was discussed earlier by people more knowledgeable than me on slack, and I’d go search to find out the details, but… 🙂

whilo01:02:50

@justinlee thanks anyway

seancorfield01:02:13

@whilo #community-development is the channel where endless discussions happen about the issue of history and alernatives to Slack -- this channel is for discussion of Clojure.

seancorfield01:02:07

If you go to that channel and click the hackpad link in the topic, you'll find all sorts of notes about discussions that have happened over the years.

seancorfield01:02:58

As for the logbot, yes, everything is still being logged. It's just a matter of getting the web site and search functionality back online (and I believe @plexus is working on that).

qqq02:02:23

(cr/reflect (Class/forName "my.dyn.TestClass"))
(comment
 {:bases #{java.lang.Object},
 :flags #{:public :final},
 :members
 #{{:name my.dyn.TestClass,
    :declaring-class my.dyn.TestClass,
    :parameter-types [],
    :exception-types [],
    :flags #{:public}}
   {:name go,
    :return-type int,
    :declaring-class my.dyn.TestClass,
    :parameter-types [],
    :exception-types [],
    :flags #{:public :static}}}})
I can't do my.dyn.TestClass/go since this is bytecode generated on the fly. I have done reflect. How do I access the function called "go" ?

qqq05:02:12

I'm writing JVM bytecode. How do I load another class by name and create a new instance of it. I.e. how do I call my.test.Vector/Vector.

rymndhng06:02:38

Hey folks, last week I asked a q about what purpose *loaded-libs* has. [1] I found out the answer from reading this blog [2]. It’s used to ensure dependent namespaces are loaded once when using :reload-all, i.e. (require 'my-namespace :reload-all) [1]: See https://clojurians.slack.com/archives/C03S1KBA2/p1517213125000006 [2]: https://www.deepbluelambda.org/programming/clojure/how-clojure-works-namespace-metadata Thanks @sattvik!

buzzdan09:02:08

Security is fun! Has anyone used the HDIV java project on his clojure solution ? https://github.com/hdiv/hdiv

moxaj10:02:55

in short: Class/forName gives you a Class, newInstance instantiates the class, getMethods gives you an array of its public methods

moxaj10:02:57

loop over those, find the right one (you can for example get its name via getName), then call invoke on it with your args

qqq13:02:48

@moxaj: I got it working, but not with getMethods -- in the repl, it was returning me a list that did not contain the static function I anted ; also, doesn't newInstance create instances of the class? that aeems irrelevant for static methods

moxaj13:02:37

right, you don't need newInstance then; as for why you don't see the method, is it public? also, there's getMethod(String name, Class<?>... parameterTypes)

qqq13:02:19

@moxaj: I'm not sure. 1. Thanks for your help . suggestions. 2. This ended up working for me:

(defn bc->obj [desc code] (let [co (ic/visit {:name    "my.dyn.TestClass"
                                                      :fields  []
                                                      :methods [{:name "go", :desc desc, :emit code,
                                                                 :flags #{:public :static}} 
                                                                ]})] 
                                    (ic/new-instance co)))

        (bc->obj [:int]
                 [[:ldc 20]
                  [:ireturn]])

        (let [c (Class/forName "my.dyn.TestClass")
              m (.getMethod c "go" (into-array Class []))]
          (.invoke m nil (into-array [])))
        
3. I've now moved on to figuring out other things 🙂

qqq14:02:47

@schmee: that is, insn is now one of my favorite libraries

schmee14:02:00

was just about to say, how is it working out for you?

qqq14:02:03

Are you using it in one of your projects too ?

schmee14:02:25

not yet, but I’m looking to do some byte code hacking in the near-ish future

qqq14:02:47

I think the simplest way to describe it is: pre-insn: the JVM sucks, but Clojure uses it, and it has great libraries, so I use it ost-insn: this is $&@#($ amazing, I love the JVM

bronsa14:02:23

insn is really good, I’d highly recommend it if you need to do bytecode manipulation in clojure

schmee14:02:49

@qqq haha, they should put that as a testimonial on github! 😄

qqq14:02:46

@schmee: have you ever thought "I need to sleep soon, but I want to read a few more sections of the JVM spec just for fun?" playing with the insn library will cause that 🙂

qqq14:02:09

it's insane how dynamic the JVM is

schmee14:02:27

the JVM is an awesome piece of tech for sure, and it’s getting better and better all the time

bronsa14:02:34

and with invokedynamic it’s got even more dynamic

schmee14:02:55

I’ve been trying to read and understand the Clojure compiler lately, and reading ASM is not easy for me…

jarohen14:02:55

oh man, the hours spent writing ASM thinking 'I wish I could just give this a clojure data-structure'

bronsa14:02:39

hey, with tools.emitter.jvm you could do that since 2013 :P

bronsa14:02:46

just not as well as with insn

jarohen14:02:03

@bronsa: doesn't t.e.jvm require a clojure-like ast?

bronsa14:02:06

and using an undocumented namespace… (yes, that’s going to change soon)

bronsa14:02:39

@jarohen nah, internally it goes ast -> insn-like IR (the insn IR is almost 1:1 with the one t.e. uses) -> ASM

bronsa14:02:21

wrong repo :P

smee14:02:00

Hey everybody! I would like to write an efficient multi-comparator (think: sort different columns of a table in different orders where each column can be addressed via a key function). My implementation is here: https://gist.github.com/smee/4c6e95d0904c09e23154215a3b6d4c72 The problem is, that the key functions have no namespace in the macro expansion. This means, that count, fn* etc. can't be resolved under advanced compilation in Clojurescript. In Clojure it works, but only if there is no variable in the current namespace that shadows the corresponding core variable.

smee14:02:15

The main idea behind the implementation is a nested comparator.

moxaj14:02:55

@smee if that fails because count isn't namespaced, then (let [foo count] (foo [])) would fail as well, which most definitely shouldn't

moxaj15:02:03

so perhaps you have something else messed up

smee15:02:33

@moxaj I'm not sure what you mean. I think, my example is too big. I think what I really would like to know is: What should I change in ~body so that the expansion includes the namespace of the function I give as an argument in this macro:

(defmacro expand-with-ns [body]
   `(:body-expansion-is ~body :but-it-should-be count))

roklenarcic15:02:46

Hey everyone. If I have a fn that returns an example of a bit of data, how do I turn it into clojure.spec generator?

roklenarcic15:02:12

There's a whole bunch of functions for combining generators, but no function for making them from scratch.

moxaj15:02:24

@smee what i'm saying is that you shouldn't care whether it has a namespace or not

smee15:02:28

@moxaj Thanks, you are right. In Clojure it seems to work. The problem is that under advanced compilation Clojurescript can't resolve the symbol so it doesn't know how to rename it properly. At runtime I get an 'undefined variable' error. But maybe this is specific for Clojurescript, I will ask there.

moxaj15:02:37

wait, maybe I understand!

smee15:02:57

gladly 🙂

moxaj15:02:04

nah, no clue 😕 try replacing count with cljs.core/count, but I'd be surprised if that resolved it

trptcolin15:02:02

in your example (in jvm-clojure),

(clojure.pprint/pprint (macroexpand-1 `(expand-with-ns count)))
(with a backtick instead of a single quote) works as i’d expect in resolving the count symbol to the right namespace

trptcolin15:02:27

i don’t know cljs well, but my suspicion would be more around the fact that whether the macro expands count (and that anonymous function) into actual functions [as opposed to symbols], which works in jvm-clojure

smee15:02:48

@trptcolin Thanks, but the backtick in the calling form is kind of cheating 🙂 I want to enforce the namespace resolution that syntax-quote does for symbols that aren't part of the quoted form in the macro but for symbols I get as an argument. Dunno, maybe the fact that it doesn't work should tell me not to venture further in this direction....

trptcolin15:02:07

i’m struggling for a reason this should require macros. you’re passing multi-compare this very nice value/data structure - could you just use a function?

smee15:02:01

Sure, but then I would need to pay the price for iterating over this data structure for each item when sorting. This was an experiment with code generation: Instead of handwriting a function that first compares argument 1 in ascending order, then, iff equal, sort by argument 2 in descending order etc. In Clojure the macro will generate a more efficient comparator that my pure function. But it isn't that important, performance is good enough. I just struggle with understanding why syntax-quote doesn't resolve these symbols.

moxaj15:02:30

@smee fyi, it works fine for me

rauh15:02:01

@smee I don't see a problem with this code. It should work. Are you sure that this piece of code is the problem under advanced compilation?

smee15:02:29

@rauh I will try to recreate the problem, I thought so but I'm not sure anymore

rauh16:02:13

@smee As an aside: If perf really matters in CLJS, then better roll your own (.sort js_arr ...). It's much faster

luskwater16:02:11

@roklenarcic I think part of the reasoning (and I don’t know for sure) for no making from scratch is shrinking and growing the data, etc. You probably could use your my-own-fn with clojure.test.check.generators/fmap, and pass in a random number to run your generator n times and take the last result (or just ignore the input from a random generator). This is a quick’n’dirty proposal without trying it myself.

dominicm17:02:24

I've been doing some reading on the officially recommended approach for error (unexceptional ones) handling. I found some recommendations from both StuH and RH to use dynamic variables with function calls. I believe there's even a talk to the same effect. Is this still what the core team recommends? I don't see this applied anywhere in clojure.core, but that might be because it's not appropriate in a library like core. It would be interesting to read some more guidance on when to use different approaches.

didibus17:02:27

As far as I know, the core team recommends sticking to normal Java exceptions using ex-info and ex-data with the try macro.

didibus17:02:44

All other methods are not symbiotic to the host platform, and will therefore hit limitations at some point along the way. In my experience, causing more pain then they solve.

dominicm17:02:27

@didibus I think exceptions are only for exceptional cases, RH on this: https://groups.google.com/d/msg/clojure/kOrg9XCYklQ/dnKJiX44oZcJ I'm talking about expected errors, validation errors from user-input, a website being down, things like that.

didibus17:02:29

@U09LZR36F Here's the thing, Java will throw exceptions even for retryable or handleable events. Your IO will mostly be done through interop with Java. IO is where 99% of those events will happen. If you adopt an ad hoc style, like dynamic vars handlers, in my experience, it eventually gets messy because of the mismatch with Java's standard

didibus17:02:29

@U09LZR36F Also, since that thread, I've heard about a lot of issues around the dynamic var strategy. Can't fully remember, but I think there's edge cases that present themselves where they fall flat.

didibus18:02:52

I think its edge cases around thread safety and lazyness

didibus18:02:04

This compares all the popular Clojure strategies

dominicm18:02:30

I think that comparison has a focus on dynamic vars & condition systems. But yes, you're right, dynamic vars have limitations in this respect.

dominicm18:02:54

But that does mean the guidance would still essentially be dynamic vars.

dominicm18:02:49

I agree that java interop makes this painful, and really, the fact that clojure's core spit/slurp don't do this is probably a sign that there's a mismatch here, which is kind of disappointing.

noisesmith18:02:29

my take is like @didibus I think - if you add something other than exceptions for failure states, you’ve introduced one more kind of failure for surrounding code to handle, because clojure doesn’t attempt to hide or abstract jvm level exceptions (and we should be glad it doesn’t) - the simplest answer is something that uses the default and adds extra functionality compatibly (which ex-info and ex-data do)

dominicm07:02:26

I would certainly hate it if exceptions were wrapped, so you will find no disagreement from me here.

roklenarcic17:02:03

@luskwater that sounds reasonable

Binance19:02:41

Get Free 100$ bitcoins https://www.binance.com/?ref=23069530 with invitation link. Happy Trading 🙂

bfabry19:02:17

cc @U04V70XH6 spam account

seancorfield19:02:28

They have been deactivated!

schmee22:02:08

sometimes I write code that spends a lot of time doing contains? on hash sets. is there some higher-performance alternative I can use in these situations? especially if I can assume that everything in the set will be a single kind of record?

bfabry22:02:37

I wouldn't use contains? with a set (though it's certainly valid), I'd just use (the-set test-value)

schmee22:02:52

doesn’t that amount to the same thing?

bfabry22:02:54

unless test-value could be nil

bfabry22:02:57

yes it does

bronsa22:02:02

it doesn't if the value is nil or false

bfabry22:02:10

I did mention that

bronsa22:02:35

I'd say that contains? with sets is more useful than with any other collection

bfabry22:02:17

aaaanyway. I don't think there's anything faster available. it's pretty fast already right?

bronsa22:02:21

well with all collection values in clojure you'll pay the price of a more expensive hashing than in java

bronsa22:02:35

so if whatever you're putting in your set doesn't need those hashing and equality semantics

bronsa22:02:45

a mutable java set could be faster at contains

bfabry22:02:52

contention: more expensive and more correct hashing 😛

bronsa22:02:38

but I'd do some serious benchmarking before arguing that contains? is a significant bottleneck

bfabry22:02:39

I think if you're working with records there's a fair chance you want clojure equality semantics. otherwise (not= (Record->map {:field 1}) (Record->map {:field 1}))

bronsa22:02:57

yes, definitely

sh4z22:02:58

is there any difference to string/split run in clojure contra clojurescript?

bronsa22:02:13

probably wrt regexes

sh4z22:02:43

it seems like in clojurescript the regex i split on is included in the output array of strings

schmee22:02:06

yeah I think I want the regular Clojure semantics… I’ll have to think about this some more, thanks for the input

sh4z22:02:48

Indeed i needed a different regex. Thanks