#clojure logs

2015-09-16

01:14nowprovisionwhats the best way to unzip all dependencies into a reference folder somewhere for viewing
01:15nowprovisionall dependencies -> all first level lein dependencies (not the complete graph)
01:16nowprovisionsay I had a project that depended on midje and clj-http, defined in dependencies: [] in project.clj, i want to do something like `lein magic-something src-ref/` and then have them unzip there for viewing
02:23crocketWhat is the best way to learn clojurescript?
02:26dbaschcrocket: it depends on your background and what you want to do with clojurescript. What language(s) do you know already?
02:27crocketJava, javascript, clojure
02:28crocketI'm looking for the best self-learning material.
02:28crocketdbasch, ^^
02:29dbaschcrocket: probably this one https://github.com/magomimmo/modern-cljs or the one by dnolen
02:29crocketWhat about clojurescript wiki?
02:30dbaschcrocket: you may want to try asking at #clojurescript too
02:31dbaschif you know clojure, the main difference is the tooling and the development process
02:32dbaschand of course the fact that you have to deal with js instead of java interop
03:34rritochHi, is there a good resource to get up to date on the changes to clojure over the past year?
03:35oddcullychangelog clojure 1.7?
03:36rritochoddcully: Cool, thanks :) Does it include the transducers?
03:37rritochnm, I see it in the clojure 1.7 press release.
03:39rritochHas there been any significant improvement in providing http async by addon libraries? Last I knew there wasn't any good http async library for clojure.
03:54rritochSorry, but one more question. I see that 1.7 introduces "Reader Conditionals". Do these deprecate cljx?
03:55oddcullyrritoch: it's not mentioned and it has still valid use
03:56rritochoddcully: Thanks again :)
03:56rritoch,+oddcully
03:56clojurebot#error {\n :cause "Unable to resolve symbol: +oddcully in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: +oddcully in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6704]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: +oddc...
03:56rritochHmm, what's the syntax for upvoting someone?
03:57oddcullyit was inc. but i doubt it works
03:57Bronsait works when lazybot is around
03:58rritochOk, thanks. I'll try to catch it later when lazybot returns from siesta
04:02rritochMy return to this community is somewhat conditional on some meetings I have next week, but I'm optimistically trying to debrief myself back to Clojure. I spent the last month working with common lisp and returning to clojure is a bit like trading in a pinto for a lexus. So many new features :)
04:04rritochI do have one crossover question, does clojure have anything comparable to common lisp "Random-State"?
04:06rritochI see the new UUID feature, which is very cool, but there is something to be said for a clonable, serializable stream of random numbers.
04:06rritochIt's the only feature from common-lisp that I haven't noticed within clojure.
04:08dstocktonrritoch: what about java? https://docs.oracle.com/javase/8/docs/api/java/util/Random.html
04:08rritochdstockton: That isn't quite the same thing since Random doesn't expose it's internal state.
04:08dstocktoni see
04:11rritochI was able to produce this feature in ABCL but my implementation is a bit sluggish for large seed sizes https://github.com/rritoch/jrelisp-abcl/blob/master/impl/src/main/java/org/armedbear/lisp/RandomStateObject.java my complexity I believe is polynomial O(n^2) since every random number requested needs to recalculate each value in the seed.
04:11rritochMy implementation wrapps java's native random function
04:12rritochThe value of the random numbers produced by it, are questionable at best. I never truly tested it to ensure that it has a decent amount of entrpy. I just assume there's a direct relationship between seed size and entropy for the algorithm.
04:16rritochEither way, I was just wondering of Clojure has a comparable feature. I'm not sure how significant the usage cases are, but in grid computing it is probably useful to have a duplicatble random state.
04:18rritochI'm not trying to make waves, or push this feature into clojure, I just wanted to know if the feature was already there someplace.
04:20gilliardrritoch: Does the SplittableRandom class added in Java 8 help? https://docs.oracle.com/javase/8/docs/api/java/util/SplittableRandom.html
04:22rritochgilliard: That is very close, unfortunatly it doesn't implement serializable or in some other way export it's internal state.
04:23gilliardrritoch: do you mean that you want to serialize the RNG to send somewhere else so you have 2 identical sequences of numbers?
04:23gilliardrritoch: I don't know what the CL random-state is used for.
04:24rritochgilliard: Yes, that's what CL random-state is for, it implements the same functionality of SplittableRandom but is serializable (Readable/Writable)
04:26dstocktonRandom implements Serializable
04:28rritochdstockton: I never noticed, but as far as I can tell Random isn't splitable. Probably why Java 8 introduced the new class.
04:33rritochdstockton: SecureRandom may be comparable https://docs.oracle.com/javase/8/docs/api/java/security/SecureRandom.html
04:34dstocktonoh, looks like it
04:34dstocktongetSeed
04:35rritochdstockton: The documentation for it isn't so good though. It doesn't export how many bites of seed you need to get the complete internal state.
04:35rritochbites=bytes
04:36rritochIt seems to make SecureRandom splitable you would need to still wrap it, and re-seed on each random value received from it. Re-seeding is basically how my CL random-state implementation works.
04:37rritochIt is serializable though, that may be the key to splitting it.
04:38gilliardrritoch: What is the difference between an RNG which has generated another one by splitting, and 2 independently-created RNGs? My attempts to teach myself about this aren't going too well..
04:40rritochgilliard: A split RNG will produce the same random number sequence while independently-created RNGs will typically have a different random state and therefore produce a different sequence.
04:42luxbockgilliard: see this talk by gfredericks https://youtu.be/u0t-6lUvXHo
04:42rritochEx: {:split {:a [9 5 3]} {:b [ 9 5 3]} , { :independent: {:a [4 5 1]} {:b [5 3 9]}}
04:42hyPiRionrritoch: use test.check. See https://github.com/clojure/test.check/blob/master/src/main/clojure/clojure/test/check/random.clj
04:43gilliardrritoch, luxbock: Thanks!
04:51rritochhyPiRion: Thanks. As far as I can tell from my initial review I don't see how that's serializable. Take the case where you split after pulling 5 random numbers. You should end up with soemthing like {a: [5 9 6 4 6 3 9 7 4 3] } {b: [3 9 7 4 3 5 2 1 9 6]} (note first 5 of :b are last 5 of :a as a was split to b after 5 integers were extracted)
04:53rritochhyPiRion: That implementation you pointed out probably works fine within a single JVM, but if you need to export the RNG to another JVM, or store it in a database, I don't see an option.
04:56lodin_gilliard: Consider how you would create two independent RNGs, then move the need to create them into a function that only depends on its arguments. That leads you inevitably to splitting, unless you want to rewrite your code to pass in a new seed every time you need a new RNG somewhere down the call chain..
04:57rritochlodin_: What your stating is exactly what I've been doing, unfortunatly. Creating a new seed on each use is a bit expensive depending on your seed generation algorithm.
04:59mungojellyi was surprised when i got to random number generation in knuth how simple it can be
05:00mungojellyof course if you just choose some random randomish algorithm it's not perfect by whatever standards, but as long as you don't use them for the keys to your bank vault i'm sure they're fine
05:01mungojellyin a couple of my projects i used the generator knuth calls the "superduper" generator because my husband I X Key! is also called Superduper so i just used that one for fun
05:06tdammerssome PRNGs have properties that make them ridiculously unsuitable for a bunch of non-security things too
05:06tdammerse.g., noise generators for audio purposes (synthesizers, noise shaping, etc.)
05:06tdammersyou really need something reasonably uniform there, otherwise the noise will be colored in some way
05:07mungojellywell if they make things in your synth sound different then all the more reason to make the RNG pluggable, then people can talk about which RNGs sound the coolest :)
05:07lodin_haha
05:07tdammerssure, you can use suboptimal PRNGs for effects :x
05:08tdammersmy guess is it'd be easier to start with a good one though, and then filter it to sound the way you want
05:08tdammerseasier to introduce non-randomness than to get rid of it
05:10mungojellysure generally usually if you happen to have some really good randomness around that fits your other needs, but i was saying just btw making sloppy randomness is surprisingly easy, it's just a few operations and then you have a stream of randomishness
05:10rritochAs a note, my implementation generated a random number of seed values in a specific range, and then used a custom hash algorithm to extract a seed usable by Java's random function. Each time a new seed is needed it would randomize the seed values using the current (seeded) random object.
05:11mungojellyuntil i read in knuth that it's just those few operations i didn't know where random came from i just bowed down and asked the computer for it and didn't know what it was
05:11rritochI'm not sure that this is cryptographically secure, but it did seem to work.
05:11mungojellyapparently even our actual cryptography approved by actual cryptographers had nonrandomness sneakily inserted by the NSA, so that is really quite not easy at all
05:13tdammersmungojelly: RNG != PRNG
05:13tdammers*actual* randomness is excruciatingly hard to get
05:14tdammersmodern kernels do a fairly decent job by sampling "noisy" system components such as NICs and HDDs, and deriving randomness from those
05:14mungojellycomputers could just ship with one of them radioactive decay random bit generators, maybe we'll add that feature next sometime after the 12th camera
05:14tdammersand then we use PRNG's to derive more randomness from that
05:14oddcullymicrophones
05:15tdammersradio static seems to work pretty well, too
05:15tdammers(as long as you're really picking up static and not some malicious signal, that is)
05:15tdammersbut, anyway, if you run servers that are somehow security relevant, it's a good idea to add some hardware RNG devices
05:16lodin_The problem is that I also want pseudo-randomness because I want a reproducable system.
05:17rritochmungojelly: Knowing the size of the key used to generate random numbers greatly helps in cracking cryptography. If the complexity and randomness of an algorithm increases over time I theorize that it would be unbreakable. My method was loosly based on how SHA complexity is produced. There are actually laws in some countries limiting key size so while this may be possible, it isn't 100% legal.
05:17mungojellyi used to enjoy making things random but then i realized there's no information in it and it just makes you hallucinate something interesting
05:19rritochmungojelly: An erlier iteration of my algorithm used these concepts but I eliminated them from the code due to the potential legal ramifications of it.
05:20mungojellyi thought we won the crypto wars
05:23rritochtdammers: Static is unfortunatly not very random. If it was we wouldn't have decent sound quality as all recordings introduce some amount of static. It isn't that difficult to predict static with decent computing power.
05:25tdammersrritoch: the "we wouldn't have decent sound quality" argument is nonsense
05:27tdammersthe reason we have decent sound quality is because the devices in question add relatively small amounts of noise, and the noise is uniform
05:27tdammersso it affects all frequencies equally
05:27rritochtdammers: This isn't an "argument", these are known facts, and they're not even new facts. A government can place static detectors at enough locations to match your static to a specific geo-location and easily hack everything your static driven random number generator produces.
05:27tdammersthat part I agree on
05:29tdammersthe part about audio quality however... no. We have decent quality audio recordings because the devices in questions have reasonable SNR
05:29mungojellymost of the noise removal tools i know of just throw the baby out with the bathwater and attenuate everything in the frequencies there seems to be noise in
05:30tdammersmungojelly: these things usually work in the frequency domain; frequencies below a certain threshold are muted, leaving only those that are louder than the noise floor
05:30mungojellywhich works great because the problem isn't really usually "this recording technically contains less information about the source event" and more "this recording has an unpleasant hiss"
05:31tdammersmungojelly: you get better results by sampling the noise floor first, and deriving per-frequency thresholds from it, but other than that, that's how it works, yes
05:31tdammersalso, if it's a pitched hiss, notching out the offending frequencies often works much better
05:35rritochtdammers: I'm actually referring to multi-dimensional FFT calcuations which can be applied at some multiplier of the speed static travels at which is ~ c (speed of light)
05:36mungojellyi've never actually written my own noise remover, just played with other people's. i'd think of squishing the noisy freqs twice, squish them if they're below a floor, also squish them by that much even if they go above the floor to punish them for being noisy. idk if that would work. could i write that in overtone you think? i don't know what overtone's model is.
05:36tdammersrritoch: I am unaware of anything in professional audio recording that does stuff like that, and it's certainly not necessary to produce decent quality audio
05:37tdammersmungojelly: you don't want to punish those frequencies when they're above the threshold - statistically speaking, the noise is going to make the sound louder half of the time and quieter the other half
05:38tdammersrritoch: other than that, I guess sampling existing static at various locations and then using that information to calculate the static at the target location and time, yeah, sure, that's at least theoretically possible, given enough computing power
05:39mungojellytdammers: do you use clojure for audio stuff? do you have any code up i could read? :)
05:39tdammersmungojelly: haha no... usually C++
05:39mungojellyc++ is very efficient and useful but in a way that makes me sad :(
05:39tdammersmungojelly: but actually most of the knowledge on the topic comes from doing home recording and studio work
05:41rritochAnyhow, so far off topic.. I just was asking if clojure has a serializable, splitable, random number generator. Instead we're designing security systems for clojure which for ethical reasons shouldn't ever be produced.
05:44lodin_rritoch: I would love to see you adapt gfrederick's code in test.check and make it available as a standalone library. :-)
05:48rritochlodin_: Making it serializable is simply a matter of your original post, generating a new seed on each use. It's computationally expensive and I can't say with any certainty that it produces a quality RNG.
05:51rritochlodin_: If I find a solution that isn't computationally expensive, I would have no problem making it open source or applying it in an existing API.
05:52rritochlodin_: To give you an example of the cost involved, a 1000 integer key literally trippled the amount of CPU time used by the CL ansi test suite.
05:53rritochlodin_: It isn't practical for a random number generator to consume 66% of CPU resources.
05:53mungojellyso does anyone have any recommendations of code in clojure i should read? what's well written, what do you like?
05:53lodin_rritoch: Ah. Reality. Bummer.
05:54mungojellydo y'all not read clojure as well as write it? it's like going to a writers chat and saying "what's your favorite book" and people are like "idk i read a short stort once that was ok." have you never read a program in clojure that was inspiring to read?
05:56rritochlodin_: Yeah, I'm really annoyed about that to. As far as I know, "entropy" is the natural state, and it takes energy to create "order". Why my algorithm works in reverse, consuming more energy to create entropy, I can't quite figure out.
05:56mungojellywhat i'm reading right now is the clojure agents tests. i'm learning about agents but it's a little dry.
05:57lodin_rritoch: haha.
05:57mungojellyentropy and order are enemies and so it's very hard to make one if you have the other. but secretly they're deeply the same. that's why you can use a bunch of order-- all the data on a disk drive-- to easily make a bunch of chaos. or vice versa if you can produce enough noise-- test.check-- you can produce perfect solidity.
05:59mungojellythat's the dichotomy that's at the source of our apparent experience of time. anyway so no recommendations what to read?
05:59rritochmungojelly: That is a very good explaination. I'm sure there's some scientific law I'm not aware of that explains my problem, but what you described is exactly the dilema I ran into.
06:01mungojellyjustin smith when i asked before linked me to something called useful with some assorted nice ways to say things
06:04mungojellyi'd really like to read something medium sized that's a coherent idea so i can see how things relate to one another
06:04lodin_mungojelly: I think that while there are lots of open source Clojure libraries, there's a general lack of open source systems. See e.g. http://www.uswitch.com/tech/more-open-source-clojure-systems-please/
06:06mungojellylodin_: ok interesting. but what library should i read?
06:06lodin_mungojelly: See also https://www.youtube.com/watch?v=loL7_lvsDBo.
06:06mavbozomungojelly, i don't like reading code without understanding the reason the code was written and also how the code got into the current form
06:07mavbozobut, for clojure, i like code and comment written in this format http://fogus.github.io/marginalia/
06:07mavbozothat's the code for marginalia leiningen plugin
06:08mungojellydo y'all not read assorted clojure code in general, just to learn about it or for fun?
06:10tdammersI tend to read source code for libraries that I consider using
06:10mavbozomungojelly, not the whole library code but the part that interests me or the part where there's lack of documentation
06:10tdammersat least scan it to get a feel for the overall approach and quality
06:11mungojellytdammers: and what's one that you've especially liked the overall approach and quality? please? :)
06:11mungojellyi don't know if i'm asking people to play favorites, or if you really don't have favorites, or..?
06:11rritochmungojelly: I can't speak for the rest of the clojure community, but 80% of the code I've written in clojure was for proprietary (non open-source) systems.
06:11tdammershaha, hum, my mind tends to remember mostly the "stay away from this" type libraries
06:12mungojellyhmm yeah there's this whole intentionally keeping secrets thing. it seems like open source is more part of the game than an actual practice today. :'(
06:14mungojellyanother possibility i guess is that nothing beautiful has been written (and published) in clojure, but i can't believe that, it's a beautiful language, surely someone has something meaningful to say in it somewhere
06:15rritochmungojelly: I'm finding it difficult to explain my view of the issue without upsetting "the powers that be". So I'll explain my view of the open source community like this. When a developer has obligations that aren't compatible with his personal vision of computing, the developer usually opts to place their work in open source to protect their intellectual property from being misused or stolen.
06:16rritochmungojelly: I'd say PGP is a good example of this concept. The person who released it faced many legal problems, but they did it to keep their vision in the hands of the people who need it, and so that they themselves could freely use it for any future project they were involved in.
06:17rritochmungojelly: I suspect Clojure open source projects fall into the same category. When developers are making something for a proprietary system that they need to use outside of that proprietary system, they generally produce it "off the books" as open source to protect themselves from legal obligations, such as employment contracts which grant ownership of all your work to the company
06:17rritochyour employed by.
06:18rritochWhen you release an open source clojure library, you strip all of it's financial value, making it not worth stealing.
06:18mungojellyi guess i understand these things in general in theory, but come on, how can that really work all the time to constrain the flow of clojure, when the people in this community could easily put together interesting fun things with a few paragraphs of text
06:19mungojellythere's some taboo on even stating short simple things, like to say a sentence is to Release that sentence As Open Source
06:20tdammersactually, releasing code under an open source license is often a very valid financial trade-off
06:21tdammersyou give up the opportunity to make money on the software by selling licenses, but that's only one possible profit model
06:21tdammersquite often, the software you're writing is a means to an end, and writing it is not your core business
06:22tdammerse.g., google's core business is serving targeted ads; the browser they build is a means to an end - better browser means better advertising
06:22tdammersby releasing things as open source, you lose the ability to sell licenses, but you gain in terms of user base, and often this results in people doing a lot of work for you for free
06:23tdammerseven if it's just running the thing through its paces and reporting bugs
06:23mavbozomungojelly, i find pedestal library's concept of interceptors to handle web request processing and its route as a data elegant. it's open source.
06:23mungojellybut i mean beyond large systems which obviously there's various economic factors that can get involved with the amount of effort involved in making them, what about just little systems we could spin up just chatting right here
06:24tdammersmost open source projects start small
06:24mungojellymavbozo: ok i'll check that out thanks!
06:24tdammersemacs, one of the most popular programmer's text editors, started as a loose collection of macros for another editor
06:24visof__hi guys
06:25tdammersit wasn't even a project, just a bunch of people using that other editor (teco), and then at some point someone decided to collect everyone's macros and package them into something more structured
06:25mungojellylike what if we just had in this chat a bot that instead of forgetting everything we had a way to make it store data (and thus code), then we'd be able to build a large interesting system just as easily as we chat in the form of examples
06:26mungojellybtw does anything collect the code people say here?
06:26tdammersprogramming doesn't work that way
06:26visof__i'm trying to implement this method, it should return number of first 0 on list, so when it's gaved (0 0 1 2) -> should return 2, (0 1 2 3) -> 1, (1 2 34) -> 0, i did this https://gist.github.com/aibrahim/e3c99d53a2d003501189 but seems wrong
06:26visof__can anybdy help
06:26visof__?
06:26tdammersservices like github do, in fact, implement most of what you're proposing, but in a way that is more suitable to programming
06:26mungojellyin #lojban we collect all the lojban people say, it'd be even easier to grab all the clojure people say here
06:27tdammersthere's also Literate Programming, which tries to instate a programming workflow that is identical to writing prose or even having a discussion
06:27mavbozomungojelly, as i recall, justin_smith tries to do it. i don't know if that is still his priority
06:27rritochtdammers: Emacs was developed by MIT. Expanding on mungojelly's statement. The financial model for a college isn't based on selling software, it's based on selling education. For them producing a technology which made their students more efficient technology professionals built their brand attracting more income.
06:27mungojellytdammers: github has been a very interesting social explosion, but it still feels to me like it's tremendously slowed by continuing taboos on speaking anything partial or participatory or silly or easy or fun
06:28lodin_mungojelly: https://pragprog.com/book/vmclojeco/clojure-applied just came out. Maybe that's what you are looking for? Depends on how well you are familiar with the basics. I have not read it btw.
06:29tdammersrritoch: yeah, that's the thing - their core business is education, and a text editor is a means to an end. Making it open source means there will be more contributions, more scrutinity, and better documentation, than they could afford to produce using a proprietary model, and selling software licenses is not the business they're interested in anyway
06:29mungojellylodin_: hmm maybe! there's so many books about clojure i haven't even started to try to look through them and pick one
06:30tdammerslikewise, when your core business is selling web hosting, then you benefit more from using and contributing to an open-source platform than you would if you were to develop your own proprietary platform
06:31gilliardvisof__: something like (count (take-while zero? [0 0 1 2 3])) ?
06:31rritochSpeaking of financial models, my wife wants me to start a youtube channel on programming. Now that's certainly a case where I'd open source everything I produced.
06:32rritochSomehow I doubt the world is ready for the number of Fb0mbs I drop while coding, lol
06:32wasamasahm
06:32wasamasaperhaps take a look at this livecoding website
06:33wasamasaI've heard some of the people there play the guitar for their viewers
06:34tdammersrritoch: when I'm programming, people can judge progress by the amount of swearing radiating from my desk - at first the frequency increases monotonically, then at some point it drops off dramatically, with just an occasional mild "oh fuck" every now and then for a few hours while I get my documentation and formatting in order
06:34TEttingerI like this stream http://livestream.com/tinykittens/tip
06:36gilliardvisof__: I think the problem you're having is that your initial loop variables include a seq and separately the first item of the seq. But when you (recur) you are passing a seq and the first item from the previous seq.
06:40rritochtdammers: I think I was like that at some point, but my wife is sensative to swearing so I've learned to hold it back somewhat, now it's more like a tsunami, once it passes everything just seems to work, but anyone or anything standing in my way tends to get their feelings hurt.
06:42rritochIn extreme cases, hardware ends up getting RMA'd
06:42gilliardvisof__: I commented on your gist, too.
06:42tdammersmy abuse is strictly verbal
06:43rritochtdammers: Heh, my abuse is strictly code, CPU & GPU cooking code in some cases.
06:48rritochtdammers: I suppose that's why I like clojure. It is very resitant to abuse and doesn't cry when you hand it expontential complexity +, it just does what you asked it to do without crying. (Stack overflow, out of memory, etc.)
06:48tdammersmaybe I do things wrong, but I get a lot of crying from clojures
06:48tdammersfootlong stack traces, cryptic errors, surprising behavior
06:49mavbozo,(get get get get)
06:49clojurebot#object[clojure.core$get 0x2eac0d45 "clojure.core$get@2eac0d45"]
06:49tdammersmaybe the problem is that it won't tell me when I'm asking something that doesn't make sense
06:50rritochtdammers: Hmm, I really don't know what design pattern your using, but it sounds like you need to make more use of clojure's lazy methods. I don't recall ever breaking the stack or running out of memory in clojure.
06:51tdammersno, I'm not breaking the stack or anything, just triggering all sorts of runtime exceptions
06:59rritochtdammers: Aaa. Well runtime exceptions aren't so bad. Since clojure is open source you can usually use the clojure source code to see why clojure isn't doing something the way you expected it to. Runtime exceptions are soft limits and there are usually fairly clear paths around them, including CPU intensive "paranoid" defensive programming.
06:59tdammersI'm talking about my own code doing surprising things and exceptioning out
07:00tdammersand defensive programming being CPU intensive at runtime is kind of really bad in my book
07:03rritochtdammers: I'm not a by-the-books developer. I have no problem throwing out all of the rules to get something to work. Once it works than you can optimize. Those books were written to make money, they weren't written to solve every problem that you will be faced with.
07:05tdammersI find that when I try "get shit done" mode, by the time I end up with something that almost works, the only meaningful thing I can do with it is throw it out the window and start from scratch
07:06tdammersI prefer evolving my abstractions and my code along with my understanding of the problem
07:06tdammersI form a hypothesis, write a solution based on it, see if it fits the problem, adjust the hypothesis, adjust the code to match it, rinse and repeat
07:07tdammersand it works best when I aim for the best possible quality from the get-go, more or less
07:12rritochtdammers: Your solution, while by the books, will only work to solve problems that are logical and solvable with current technology. The scientific process itself can't solve paradoxes, to solve many paradoxes you have to create a new system which operates outside the rules and doesn't contain the paradox. Comparable to using calculus isntead of algebra to solve a problem.
07:15tdammersrritoch: if it's not solvable with current tech, trying to solve it anyway and ignoring the theory doesn't make it the slightest bit more solvable
07:15rritochtdammers: I can give you an exact example https://github.com/rritoch/clj-osgi-namespaces , while that code works, it breaks many rules.
07:16tdammersit runs on actual hardware, doesn't it?
07:17tdammersthe rules it breaks are conventions; it is still limited by formal logic, just like any other computer program
07:17rritochtdammers: Sure, but it breaks the "rules" of clojure, by using reflection to bypass the rules of java, specifically the modification of static final's.
07:17tdammersyes, so?
07:17tdammersrules still exist
07:18tdammersand they're just as rigid and formal
07:18tdammersjust not explicit maybe
07:18rritochSure, the rules still exist, but to solve that particular problem I needed to develop code that operated outside of those rules.
07:18tdammersthe rules you're breaking are not the ones I'm talking about
07:19rritochtdammers: No, every problem is different, and in many cases there is a solution within the rules of best practices. In many cases you need to break best practices and get something functional before you'll see a solution that is within best practices.
07:20tdammersbut again, that's not the kind of rule I'm talking about
07:21rritochtdammers: Again using the same system as an example, when that project started it was a fork of clojure as I couldn't find a way to do it within the rules of clojure. Eventually I found a way around it, with the help of some #java experts.
07:22rritochtdammers: It sounds like you have a specific problem your trying to solve. Why not just post the code and let this room find the solution?
07:22tdammersthe thing is, I break rules like these all the time, when that's appropriate - but when I do, I do it because the programming language I'm using doesn't have the expressive power to encode the abstractions I need; I don't fool myself into thinking that I am somehow transcending the realm of formal logic
07:23tdammersno, I have about a hundred small specific problems every day, and I can solve them, that's not the problem
07:23rritochtdammers: This isn't a case where I transcended formal logic, but I have.
07:24rritochtdammers: There's a specific problem I needed to solve that only had a solution in the realm of high dimensional fuzzy logic (~7 dimensions).
07:24tdammersyou always end up with a formal system to express what you want the computer to do
07:24tdammerswhether you do that on purpose or not is a different matter
07:24tdammersas is the question how sure you can be that that formal system matches your requirements and expectations
07:25tdammersyou are always going to simplify things, too, in order to make them fit into such a formal system
07:25tdammers(almost always, anyway)
07:27rritochThe exact problem was this. 1. The system must be able to determine the users X address, where X is one of (mailing, physical, billing, primary, primary-*). 2. Do not require users to enter X
07:28rritochThis solution doesn't exist in the realm of logic, it is a paradox. The solution exists within the realm of fuzzy logic.
07:28rritochWith a little bit of AI "magic".
07:28tdammersThat's not the exact problem, and it's not a paradox either
07:29tdammersif what you wrote there were the full problem exactly, the correct solution would be to make a random guess
07:29rritochtdammers: lol, wrong
07:29tdammersyou used more information
07:30rritochtdammers: Randomly choosing an address wouldn't have solved the problem, but that would have been a funny solution to use.
07:30tdammerswith the information at hand, that solution is as good as any
07:30rritochtdammers: It would have saved me from solving the problem
07:31tdammersmy point is, you had more information about the problem than that
07:31rritochtdammers: Anyhow, what I did was developed a 7 dimensional fuzzy logic system, where each address type is represented as a dimension
07:32tdammersfuzzy logic is a well-defined formal system you know
07:32tdammersit's not boolean logic, but it's just as formal
07:32rritochtdammers: A weighted average of known implications is computed such that a mailing address is a mailing address 1, but a maybe mailing address (.5) that is a billing address, is probably a mailing address by implication that most billing addresses are mailing addresses.
07:32tdammersyes, I know how fuzzy logic works
07:33tdammersI still don't see a paradox there
07:33rritochtdammers: So I coded in all of the implications, producing the solution without just randomly selecting an address because the client's specification wasn't logical.
07:33tdammersI still maintain that you had more information
07:34rritochThis is just one example where the scientific process which leads you to the conclusion of picking a random address, is wrong, because there is still enough information to come up with a solution that will be accurate 99% of the time.
07:34tdammersyou didn't disclose the extra information
07:35rritochtdammers: There isn't any extra information, other than the establishment of weighted implications that address X[1] -> X[2] at some probability.
07:35tdammersso where do those probabilities come from?
07:36tdammerswhat do you know about the user?
07:36tdammerswhat do you know about addresses in general?
07:36tdammerswhat's the situation, even?
07:36tdammersyou know a lot about these things
07:36tdammersand you encode that knowledge in your code
07:36tdammersthe knowledge isn't formal, but the code is
07:37tdammersit has to be, because we haven't yet figured out how to build computers that can reliably interpret vague requests
07:37rritochtdammers: That isn't entirely true
07:37tdammersnot for programming purposes anyway
07:38rritochtdammers: See https://en.wikipedia.org/wiki/Cyc
07:38rritochNow that would be a nice clojure project :)
07:39tdammershaha
07:40tdammershttps://en.wikipedia.org/wiki/Cyc#Knowledge_base
07:40tdammersnote how that part describes a very rigid grammar
07:40rritochEither way, my theory stands. To find solutions to some problems you have to work outside the rules of traditional logic or current technologies.
07:40tdammersclojure is a current technology
07:41tdammersyou cannot make clojure do something that clojure cannot do
07:41tdammersyou are bound by its hard rules
07:41rritochWell, cyc is barely a current technology, unless you happen to have Mark Zuckerberg money
07:41tdammersthey may not align with the stated rules, or the conventions...
07:42rritochtdammers: Sure you can. The link I provided earlier produces a feature in clojure that clojure cannot do in it's current state. It uses Java and Reflection to bypass those rules.
07:42tdammerswhat you *can* do, however, is tear down existing abstractions and build new ones
07:43tdammersusing Java and Reflection are explicitly things that clojure can do
07:44rritochOk, well now your just playing games with the concept of "rules". Using reflection to bypass restrictions is not within the "rules" of best practices.
07:44tdammerstime travel, allocating more RAM than your machine can provide, traversing infinite lists in finite time, calculating all the digits of Pi, accurately predict the future, actually losslessly reversing lossy compression, etc., are things clojure absolutely cannot do
07:45tdammersI'll say it again, "best practices" aren't the rules I'm talking about
07:45rritochtdammers: Ok, so let me solve these impossible problems you present.
07:46rritochFirst, time travel. Solved, solved again. We are already traveling through time at different rates.
07:46tdammersdude.
07:46oddcullywasn't there some clojure-ot channel?
07:46rritochSecond of all, allocating more ram than machine can provide. Compression, solved. Has been solved for awhile.
07:46oddcullysorry for beeing a party pooper
07:46tdammersoddcully: np, this is getting ridiculous anyway
07:49rritochWell, as it is extremly relevant, and not to continue this useless conversation, traversing infinite lists in finite time, clojure not only does, but does so elegantly with lazy lists.
07:52tdammersno, it doesn't. It traverses unbounded lists in linear time and in constant space, but if the list is actually infinite, so is the traversal.
07:53tdammersyou can *create* lists that are actually infinite, and you can pass them around and perform finite operations on them in finite time, but a full traversal of an infinite list cannot be done in finite time
07:54tdammersit's not even possible to devise a completely accurate finiteness checker for lists that is guaranteed to run in finite time
07:54tdammers(the halting problem, basically)
08:05rritochThis poor room is silent. Can we at least debate how a clojure implementation could solve the lossy compression problem?
08:10kavkazWhattup Clojure fam
08:11mungojelly i just made my first finger tree! wow these seem super useful
08:14kavkazmungojelly: Haha congrats, I'm looking it up right now
08:17mungojellyit's like, build me this list, but while you're at it, keep track of quality X of the things in the list, so i can quickly get to wherever in the list the X adds up to the amount i want, and then seamlessly invisibly maintain that accounting of everything as meanwhile i heedlessly mess around with the contents
08:37snowellAnybody know of an easy way in cursive clojure to "fix" the indentation of a block?
08:37snowellOr is that more of a "set up IntelliJ to do that" sort of thing?
08:37snowellIf I'm writing code live, it does the indentation perfectly, but if I copy/paste somewhere, it can be misaligned with what I'm pasting it into
08:39oddcullysnowell: in regular intellij its ctrl-alt-l (or `=` if in vi mode). if nothing is selected the whole file gets indented
08:40snowelloddcully: I love you
08:40snowell(inc oddcully) ; And my brain thanks you
08:40oddcullyhehe, yw
08:44kavkazsnowell: How are you liking cursive?
08:44kavkazHow does it compare to emacs + Clojure mode + CIDER?
08:44snowellkavkaz: After being against it for no reason, I'm actually loving it, especially with the structural editing
08:45snowellAnd having never used emacs, I can't really make a fair comparison
08:45kavkazsnowell: structural editing?
08:45snowellhttps://cursiveclojure.com/userguide/paredit.html
08:45snowellI can really only compare it to Light Table, and it's light years better
08:47kavkazsnowell: so basically it's editing focused on the selected expression?
08:47snowellAnd easily moving elements into/out of structures
08:48kavkazAh cool
08:53mungojellyi assume there's some way to get your expression processed by some clojure and given back to you?
08:54mungojellyin cursive i mean, so you can say in clojure how you want to change things
09:05kavkazmungojelly: I don't understand what you're saying lol
09:06kavkazBut code is data, you can change how the Clojure language works
09:06kavkazhaven't really done that myself though
09:06snowellWell you can use a REPL
09:06snowellCursive isn't a language, it's an IDE
09:07snowellApologies if I misunderstand what you're asking :)
09:07mungojellywhat interface does cursive present to you if you're a clojure program
09:08kavkazmungojelly: Which specific part of cursive? Are you talking about the REPL?
09:08oddcullymungojelly: you want to pass an expr from the ide into a clojure program, transform it have the result placed, where the original went off?
09:09mungojellyoddcully: sure well or somewhere else too i'd think why not
09:10mungojellyi can't find cursive source, is it closed source? :o
09:10oddcullyyes
09:10oddcullyand it will cost money at some point in the future
09:10mungojellyweeeeeiiiiiiiird why
09:11snowellI don't think it's weird that a dev wants to get paid for his/her effort and time
09:11mungojellyso then of course you don't get proper hooks into anything because then plugins would easily transport to a different ecosystem and dissolve the supposed value of holding you there. :(
09:15oddcullymungojelly: the audience for cursive to me seems clearly the "im fed up with fiddling vim/emacs/younameit" folks. it's easy to setup, debugger, refactoring, ...
09:15oddcullythe platform to add new things is the intellij api
09:15oddcullyeverything beyond that, cfleming, the author, can for sure shed more light on
09:15mungojellyok well i can cross cursive off my list of things to look into then, one down
09:18pvinishello. i want to make a little daemon-kind application, that i can control through command line and also a little gui based on reactjs. i was thinking, should i make the application in clojure, and have a server to connect to and control it, or should i make the application with the gui in clojurescript and react, and just connect the command line app to that somehow?
09:22Igor___How can I catch exception when I run Aleph with Gloss frame (string :utf-8) and send non utf8 byte (e.g. "^c" - ctrl+c byte) via telnet?
09:22kavkazmungojelly: If you're really planning to modify your environment, look into emacs
09:26mungojellykavkaz: i do use emacs but i'm not very good at it, i just poke around at characters with it like any boring text editor mostly
09:51aneis it good practice to have unit tests run satisfies? checks for protocols?
09:51anethat is to test whether record X satisfies some protocols
09:52opqdonutI think that's a good first step
10:17gfrederi`gilliard: luxbock: lodin_: I always meant https://github.com/gfredericks/four to be a good supplementary lib for randomness; e.g., the test.check splittable generator could be copied over there
10:17gfrederi`there could also be a contrib lib or two eventually I imagine
10:18srbakerheya folks
10:19srbakerhopign someone can help me figure this out, i've been beating on it for days. just waiting for a paste
10:19srbakerhttps://www.refheap.com/109615
12:34mungojellyi like the idea of #_ for comments
12:39sobelin clojure?
12:39sobeloh right, you don't like to leverage existing solutions. i remember you.
12:40mungojellythis is a suggestion from Ron Toland, apparently his company uses it in their dialect
12:40mungojellyall very dialectical around here with the no sharing
12:41mungojellybut anyway it's a good idea! that's much more harmonious. ;; is a textual syntax, no? that's a weakness.
12:42TEttinger; is until end of line
12:42TEttinger;; is the same as ;
12:43mungojellyyeah, "end of line" is a funny concept, why have a construct that starts ; and ends \n among ( ) { } [ ] are much clearer and less fragile, #_"comment" fits in better
12:43TEttingertrue, but most code does have the need for line comments at least sometimes
12:43TEttingermostly inline docs
12:44mungojellycouldn't you put #_"This line sucks!" at the end of the line?
12:44TEttingerindeed you could, though I'm not sure it would highlight super well
12:45TEttingereven the dumbest syntax highlighters can do ; to EOL
12:46TEttingerand on the web there's plenty of bad ones
12:46mavbozomungojelly, so you prefer multiline comment like this https://www.refheap.com/109618 ?
12:47TEttingerwell that actually is something I like for multiline comments
12:48mungojellyidk if it were up to me i'd like to put lots of metadata, way more explanation and decoration than action
12:48mungojellylike i think it would be nice if we decorated all our functions with colors. then you could colorize everything very distinctively and sensibly.
12:49TEttingerit would provide a nice visualization for profiling, up to about 8 colors
12:50blake_I'm trying to figure out if core.logic is useful for what are essentially giant if/case/cond type setups.
12:51blake_Here's a sample table: https://www.refheap.com/109619
12:52hiredmanyou likely want a rules engine
12:52hiredmanlike https://github.com/hraberg/mimir or drools
12:53blake_Maybe so. Our situations don't seem to be as complex as drools allows, such that drools seems like serious overkill.
12:53hiredmancore.logic is more like, here are the relationships between these variables, here are values for some of the variables, what possible values are there for the other variables such that all the relationships still hold
12:53hiredmanit is search
12:54blake_hiredman: OK, cool. Thanks! I'll save my digging into that for later.
12:55hiredmanthe classic algorithm for rules engines is called RETE, and there are a number of pure clojure implementations that are likely easier to work with than drools
12:55hiredmanmimir was just one of the hits on google for `clojure rete`
12:58aneis it possible to have two sets of annotations for a fn, like (defn foo ([^String x] ...) ([^Number y] ...)), a kind of pattern matching based on type
12:59hiredmanno
13:08justin_smithane: you can effectively do that with a protocol or multimethod
13:08justin_smithbut not with that specific syntax
13:09aneoh? it supports types?
13:09justin_smithboth can dispatch by type
13:10anehow do protocols do it?
13:11justin_smith,(defprotocol IFoo (frob [this]))
13:11clojurebotIFoo
13:11justin_smith,(extend-type String IFoo (frob [this] (clojure.string/reverse this)))
13:11clojurebotnil
13:11justin_smith,(frob "hello")
13:11clojurebot"olleh"
13:12justin_smith,(extend-type Number IFoo (frob [this] (* this this this)))
13:12clojurebotnil
13:12justin_smith,(frob 42)
13:12clojurebot74088
13:12justin_smith,(frob 1/8)
13:12clojurebot1/512
13:12justin_smithane: with a protocol you get better performance, and you can implement multiple methods in one protocol
13:13justin_smithane: with multimethods you get more flexibility of dispatch (which you don't actually need)
13:15aneyah i was doing something like (defn foo [x y] (let [t1 (type x) t2 (type y)] (cond (and (identical? x String) (identical? y String)) (concatenate the strings))))
13:16TEttinger(identical? t1 String), you mean?
13:16aneyeah oops
13:17anei wonder if that's possible with a protocol, a multimethod worked just fine, in fact it's bloody brilliant, but i have two types i need to dispatch on
13:18TEttingerthat's the multi in multimethod
13:18aneyeah
13:18justin_smithTEttinger: no, if that was the case they would be called "arbitrarymethods"
13:19justin_smithbecause the dispatch is an arbitrary function of the inputs
13:19justin_smithhell, you could use a random number generator to dispatch and ignore the args
13:19ane(defmulti (fn [x y] [(class x) (class y)])) and so on
13:19TEttingeram I confusing multimethod with CLOS stuff?
13:20justin_smithwell, multimethods are related to the CLOS stuff, but the multi refers to "multiple implementations" not "dispatches on multiple values" I thought
13:21TEttingerfrom http://clojure.org/multimethods : Clojure multimethods are not hard-wired to class/type, they can be based on any attribute of the arguments, on multiple arguments, can do validation of arguments and route to error-handling methods etc.
13:21TEttingerI suspect the multiple arguments thing is what we're after
13:22anei would think it's multiple implementations
13:28TEttingerYour dispatching function can return any arbitrary value using any or all of its arguments. The next example defines a multimethod that takes two arguments and returns a vector containing the type of each argument, and a method that matches when each argument is a string:
13:28TEttingerhttp://www.braveclojure.com/multimethods-records-protocols/
13:28TEttinger*cough justin_smith* Incidentally, this is why they're called multimethods - they allow multiple dispatch, or dispatch on more than one argument.
13:29anemaybe it's not the cardinality of the arguments of the methods but the number of argument types
13:29TEttingerthey also use an RNG to dispatch and ignore the args on the wikibooks examples
13:29TEttinger,(defmulti types (fn [x y] [(class x) (class y)]))
13:29clojurebot#'sandbox/types
13:29anei think i'm wrong about this though, dynamic dispatch is where there's just one
13:30justin_smithTEttinger: eh, I wouldn't call braveclojure an authoritative source
13:30TEttinger,(defmethod types [java.lang.String java.lang.String] [x y] (str "Strings! " x " " y "!"))
13:30clojurebot#object[clojure.lang.MultiFn 0x7503eb9f "clojure.lang.MultiFn@7503eb9f"]
13:31TEttinger,(types "hey" "justin")
13:31clojurebot"Strings! hey justin!"
13:31sobelis there a section on other authoritative sources, on clojure.org?
13:31TEttinger,(types "hey" 1)
13:31clojurebot#error {\n :cause "No method in multimethod 'types' for dispatch value: [java.lang.String java.lang.Long]"\n :via\n [{:type java.lang.IllegalArgumentException\n :message "No method in multimethod 'types' for dispatch value: [java.lang.String java.lang.Long]"\n :at [clojure.lang.MultiFn getFn "MultiFn.java" 156]}]\n :trace\n [[clojure.lang.MultiFn getFn "MultiFn.java" 156]\n [clojure.lang.Mult...
13:31TEttingersobel: http://clojure.org/multimethods
13:31sotojuanWhat's a good fun project I can write in Clojure? Been learning through math-y problems so far.
13:32TEttingerit's not a super great intro it seems, the official one
13:32justin_smithTEttinger: it's an excellent intro I think
13:32TEttingerjustin_smith: but... it didn't tell you important stuff about it actually doing multiple dispatch
13:33justin_smith? it absolutely does!
13:34justin_smithTEttinger: a quote from that page: "(defmulti bar (fn [x y] [x y])) (defmethod bar [::rect ::shape] [x y] :rect-shape) (defmethod bar [::shape ::rect] [x y] :shape-rect)"
13:35justin_smithand it also covers things like heirarchies and prefer-method that almost no other source touches
13:35TEttingeryeah, I had no idea what that did tbh. it doesn't help that it links to the docs on http://clojure.github.io/clojure/clojure.core-api.html#clojure.core/defmethod ... and defmethod has essentially no docs
13:36justin_smithTEttinger: the text on that page (outside the examples) explains what is happening there, but would have been more tedious to quote into this channel
13:36anejustin_smith: is the performance improvement in protocols due to compile time magic? i understand multimethods are runtime
13:36TEttingerI mean I read it and still didn't get it
13:36justin_smithane: the dispatch has less work to do
13:37aneok. is it possible for it to work on two parameters then?
13:37TEttingeryes.
13:37TEttingererr
13:37justin_smithTEttinger: it's a multimethod that dispatches based on the values of the two args, and it uses heirarchies to pick the apropriate method
13:37anehow do you extend two types at the same time o_O
13:37TEttingerfor protocols? no idea. I pasted an example for multimethods
13:37justin_smithane: protocols only dispatch on the first arg
13:38justin_smithso if you can't differentiate impls to call based on the first arg alone, you might need multimethods
13:47aneok. used a multimethod, was the simplest
13:47aneis there any difference between using [(class x) (class y)] and [(type x) (type y)]
13:48justin_smith,(type ^{:type "FOO"} {})
13:48clojurebot"FOO"
13:48justin_smith,(class ^{:type "FOO"} {})
13:48clojurebotclojure.lang.PersistentArrayMap
13:48anehm
13:48justin_smithso type gives you extra power
13:48justin_smithin case you want to differentiate an existing IMeta by metadata
13:48BronsaI can't imagine why that'd be useful
13:49BronsaI guess it predates the existence of records?
13:49justin_smithBronsa: when all you want is the type dispatch, and don't need the other features of defrecord?
13:49justin_smithor that
13:50justin_smithBronsa: not totally clear on how it's best used (or even if it has a great use), just answering the "what's the difference between type and class" question succinctly :)
13:50Bronsajustin_smith: I'd rather the type be explicit if I want to dispatch on it, either by concrete class or by an :op/:type field
13:50justin_smithyes, I'd agree
13:51Bronsajustin_smith: yeah yeah I wasn't antagonizing you, just wondering if `type` is still useful in clj 1.7
13:55amalloyBronsa: it's used for print-method
13:56amalloybut it certainly predates defrecord/deftype, and was mostly used to let you pretend user-defined "types" (that are just maps) are a distinct type
13:57Bronsaamalloy: I was looking at that, but it seems like print-method just supports `type`, it doesn't *use* it
13:57amalloywell, right
13:59amalloyif print-method didn't support type, it would be kinda hard to create a user-defined type that acts like a map and prints differently. defrecord doens't let you override toString, and you don't want to have to implement ILoookup by hand for every deftype
13:59amalloyotoh, nobody is actually using this feature really, so maybe it is not an important one
13:59Bronsaamalloy: one could just extend print-method to the record type
14:00amalloyoh, indeed
14:02justin_smiththis might not be helpful, but here's a crossclj snapshot of who uses clojure.core/type (of course it's harder to look up where it's being used intentionally for the metadata feature) https://crossclj.info/fun/clojure.core/type.html
14:03Bronsa(inc crossclj)
14:03Bronsa:(
14:04Bronsajustin_smith: I'm pretty sure I've at least once used `type` instead of `class` because it's one char less to type
14:04justin_smithhaha
14:06Bronsaoh I never realized struct maps instances don't preserve the struct type
14:07amalloywhat do you mean, the struct type?
14:07Bronsathe struct name
14:08Bronsalike, (defstruct point :x :y) (def p (struct-map point :x 1 :y 1)) < there's no way to know that p is a `point`
14:09justin_smithI guess that's part of why we don't use structs any more
14:10BronsaI wonder if there's still instances where structs might have some performance advances over maps/records
14:10BronsaI never actually read their implementation
14:11Bronsalooks like it's an array+extmap instead of fields+extmap of records
14:49sdegutisDo you find that your top-level System component often has like a dozen subcomponents directly under it?
14:51justin_smithsdegutis: as in a dozen components that each have sub-components, or just a dozen subcomponents?
14:52justin_smithbecause I have more like 8 sub-components, but it totally depends on how many stateful moving parts your project is going to have...
14:52sdegutisRight.
14:52clojurebotexcusez-moi
14:52justin_smithbut I don't have nested sub-components
14:53justin_smithbecause I avoid the whole information-hiding thing in app level code
14:53sdegutisYeah, I don't have nested subcomponents. I have a top-level System, which has 9 components, and sometimes a function in one component will take another as an argument, but they aren't hierarchically structured.
14:53justin_smithyeah, totally normal then
14:53sdegutisAnd because of this, my System defrecord takes like 9 or 10 arguments. It feels a bit unweildly.
14:54sdegutisor whatever that words supposed to be
14:54justin_smithwait, I just have a system-map and dep map literals, and I don't do a defrecord for my top level...
14:55justin_smithin fact I even use optional args to filter components out (eg. start up everything but the http server, and those components which depend on the http server)
14:55sdegutisHmm yeah I don't think I technically need a defrecord for the System map. That said, I think a map might suffice for any of my components.
14:56justin_smithwell, you still want a custom start/stop for most of them don't you?
14:56sdegutisBut I'm pretty sure there's value in using defprotocol/defrecord for at least some of the components, I just can't remember what.
14:56sdegutisOh right, that's the value. Different start/stop methods.
14:56sdegutisGreat, thanks.
14:56justin_smithright, you don't need that at the top level
14:56justin_smithit's just a call to component with a map of components and a map of maps of deps
14:56sdegutisRight. It just calls interface functions, so it's the same at that level.
14:57sdegutisThe only different thing is the creation of the System component, which is just a function anyway.
14:57sdegutisso (memory-system) vs (live-system)
14:57sdegutisThanks justin_smith.
14:57sdegutisI like keyword-based APIs on account of how I have to import/require fewer things.
14:58sdegutisI wonder if it makes sense to just turn all my components into functions that return maps, some of the keys of which are functions.
14:58sdegutisLike, why even bother with defprotocol/defrecord?
14:58justin_smithsdegutis: you should check out how onyx does things
14:58justin_smithkeyword all the things!
14:58sdegutishttp://www.macupdate.com/app/mac/11582/onyx ew
14:59justin_smithI mean onyx as in the clojure distributed processing tool that mdrogalis makes
14:59sdegutisoh cool
15:00sdegutisjustin_smith: in your opinion when would you use a defprotocol/defrecord rather than just a map?
15:01justin_smithsdegutis: when I need to use or support protocols
15:18sdegutisjustin_smith: with protocols you didn't write, right?
15:19sdegutisjustin_smith: so then do you often have :keys refer to functions, that you call like ((:key m) args ...)?
15:28pseudonymousI'm trying to wrap my head around loop&recur - and failing miserably at that (yay!). Matters are made worse by me having to kill my cider repl session buffer and making a new one each time it gets into an infinite loop (with lots of printing involved). Is there a way to safeguard against this ? (yes, I'm using emacs)
15:30tcrayford____sdegutis: also reminder that defrecord is much faster than maps for known key lookups
15:31sdegutistcrayford____: Ah, didn't think of that!
15:31tcrayford____see like, KeywordLookupSite and such
15:31sdegutistcrayford____: Does that count function-like method-calls, like (foo r) where foo is defined inside a defprotocol?
15:32justin_smithsdegutis: well, protocol method calls are faster than function calls, yes, but this is a separate speedup - field access for defined record fields is faster too
15:32tcrayford____protocol calls are noticeably faster if the implementation is defined inside a defrecord/deftype rather than outside it
15:32sdegutisAh, like (:foo r)
15:32justin_smithsdegutis: in both cases hash lookups are replaced by direct index, more or less
15:33justin_smithtcrayford____: because var lookup is avoided right?
15:33sdegutisThis, plus typo-safety, plus a defined list of public methods, seems like a good reason to keep my current protocol/record based setup.
15:33tcrayford____justin_smith: it's worse than that. Go look at how protocols *actually* work
15:33amalloypseudonymous: C-c C-c probably cancels the loop
15:35amalloyjustin_smith: i would be surprised to find that protocol method calls are any faster than an ordinary function call; rather, they are probably a bit slower. the reason protocols are faster on the whole is because calling them avoids the type-dispatch you'd otherwise do inside your ordinary function instead, and *that* would slow you down
15:36amalloyif the type dispatch is unnecessary (because you are replacing a monomorphic function with a protocol method), just using a regular function is probably faster
15:36tcrayford____amalloy: reminder that the JVM can optimize type based conditionals inside function definitions as well though
15:36tcrayford____the jvm: how does it work
15:36tcrayford____like if you do code like
15:36tcrayford____(if (instance? java.util.Map x) thing1 (if (instance? java.util.Collection x) thing2))) the JVM can PIC that
15:38amalloyPIC?
15:38amalloythe only thing i can guess that sorta fits there is per-instance callsite
15:38sdegutisamalloy: I thought protocol calls were just Java method calls and thus really fast?
15:38tcrayford____polymorphic inline cache
15:38amalloysdegutis: calling a function is just a java method call
15:38sdegutisoh.
15:38sdegutisnm then
15:38tcrayford____+ a var deref + +
15:39sdegutisWhich protocol calls still have I presume
15:39amalloya protocol function is looking something up in a hashmap and then calling some java method
15:39tcrayford____amalloy: not always
15:39tcrayford____it's
15:39amalloytcrayford____: calling a *global* function involves a var deref. we call lots of non-global functions
15:40tcrayford____"check if the thing implements the interface that's hidden inside the protocol, if it does, call the interface method that corresponds to this function, otherwise look up the thing in the cache"
15:40amalloyoh, that's right, the interface check is before the hashmap lookup
15:43tcrayford____anyway most judgements about "is X faster than Y" are BS anyway because of the JVM. Benchmark it if it matters, with a good benchmarking mechanism, otherwise ignore it. In most clojure apps I don't expect this level of thinking about performance to matter all that much
15:45TEttingerI'm curious what the clojure community's ideas on this are. There's an open issue on a java lib that I've inherited and am actively adding to, relating to taking a heavily-used Coord type (currently just two mutable ints, x and y) and making it immutable
15:46TEttingerclojure had good immutable collections that also share structure, and I'd like to have a way to minimize GC on Coords
15:47ed-gHello, has anyone used BYTEA columns in Postgres? How do I insert and retrieve files using them via JDBC? (exec-raw db ["insert into files (file) values (? :: bytea)" [ (slurp "/path/to/file") ]]) gives errors
15:47TEttingerthe fastest way we've thought of so far in java is to bitwise or the two ints into one long (could also be shorts and an int, x and y never should go above 2^15 under any circumstance).
15:48tcrayford____TEttinger: bitwising them seems dope to me
15:48TEttingerit would be better if I could somehow alias the type...
15:48tcrayford____means you can stick a tonne of em in an array without the usual JVM problem of cache misses everywhere you look as well
15:48tcrayford____yeah haha :(
15:49TEttingernow there's no way to restrict values to always being Coords, you could pass total garbage in easily
15:50TEttingera possibly weirder solution involves two factors: strings are already immutable, chars are 16-bit, and strings can be interned
15:50tcrayford____just carry on praying real values land properly in java 9 and that all of your clients can upgrade to java 9 when it releases?
15:51TEttingerAndroid is a target, hence the concern about GC and static
15:51tcrayford____ah yeah
15:51tcrayford____and likely android ain't getting dem values either :(
15:51TEttinger(static variables can outlive your application in some cases, and persist into the next run)
15:51tcrayford____oh for a typedef
15:57amalloyTEttinger: what does clojure's immutable shared-structure collections have to do with minimizing gc on coords?
16:01TEttingerclojure seems to have a better way of handling immutable stuff
16:02TEttingerI'm sorta lost on the best way to have type safety, low-GC, and immutability on a pair type
16:05tcrayford____TEttinger: right now on the JVM: there's no good way of doing that :(
16:07TEttinger...maybe. this is getting into black magic territory, but could an annotation produce a typedef-like effect?
16:08ed-gIs there a standard library function to convert a byte-array to a string containing hexadecimal digits?
16:09TimMcIf there is I'll be annoyed because I've wanted something like that.
16:10tcrayford____there's one in apache commons
16:10ed-gTimMc, :-) It's not like its hard to write my own but I'm sure it will be slow for my gigs of data I need to load into DB.
16:11tcrayford____org.apache.commons.codec.binary.Hex/decodeHex
16:11amalloyhttp://stackoverflow.com/a/9855338/625403
16:12tcrayford____" Performance is equivalent to Commons Codec, which uses very similar code"
16:13xemdetiaTEttinger, how static are these coords out of curiousity? I mean I am thinking more of 3d float sense which is not helpful :)
16:13TEttingerxemdetia: static as in unchanging or static in the belongs-to-class java sense?
16:13xemdetiastatic as in unchanging
16:13xemdetiasorry
16:14TEttingerthey should never change, new ones should be different values. a long would correctly handle most of it
16:14TEttingeressentially I want either C++ or C# features and Java is right in the middle with neither
16:16xemdetiawell would it be worth just *doing* it in c++ with android ndk? I forget if that is still supported
16:16xemdetiabecause it isn't like you have speed problems you just have memory management problems
16:18TEttingerhang on, you just gave me an idea
16:27TEttingerit's possible that the points could be mutable, then become immutable? I could have a "final int x, y;" pair of fields, an "int tempX, tempY" pair of fields, and a finalize() method that assigns x and y the values of tempX and tempY
16:33amalloyTEttinger: if you were going to actually do that you'd rather have a bool frozen
16:34TEttingergah, I was fearing that.
16:34TEttingera lot of the usage of the existing Coord stuff just uses the fields, not getX() and getY()
16:37noncom|2justin_smith: from your experience: what is better: having all state in one namespace or is it possible to have small local states on various pages?
17:04justin_smithnoncom|2: this is in reagent, correct?
17:33BalvedaI'm having an error trying to extend a protocol, telling me immutant.web.internal.ring.LazyMap does not exist when I do a lein run
17:35BalvedaAny ideas? I'm requiring it in the ns declarations
17:36tcrawleyBalveda: try a `lein clean`
17:36BalvedaAlright
17:36tcrawleyare you trying to extend LazyMap itself?
17:37Balvedanope
17:37BalvedaDidn't work either
17:37Balvedathis is the code
17:37Balvedahttp://pastebin.com/5FQNk8zm
17:38tcrawleywhat does your ns declaration look like?
17:39Balvedahttp://pastebin.com/DkdpKP3J
17:40tcrawleyhmm, you may need to (:import immutant.web.internal.ring.LazyMap)
17:41BalvedaException in thread "main" java.lang.RuntimeException: Unable to resolve symbol: LazyMap in this context, compiling:
17:41tcrawleyI'm curious why you need to extend the protocol to LazyMap specifically though, you should be able to extend to java.util.Map
17:41Balvedaer
17:42Balvedamade a mistake
17:42Balvedaoh, there's an idea
17:42BalvedaI'll try it out
17:42tcrawleywhich would be more general
17:44Balvedathat did it
17:44Balvedathanks
17:45tcrawleymy pleasure!
17:45amalloytcrawley: extending a protocol you don't own to a type you don't own is dubious
17:47Balveda(inc tcrawley)
18:09lodin_amalloy: I'd say it's OK at an application level, but not in a library (since you can end up with conflicts and render other libraries unusable).
18:11Balvedais there any middleware in the luminus defaults that could be interfering with a ring response redirect?
18:12BalvedaAs in, I'm doing a response/redirect but it's just printing the html in the console rather than redirecting
18:21sdegutisjustin_smith: Do you use jetty-ring-adapter? If so, how do you integrate that with start/stop, seeing as the create-server is private and only run-server is public?
18:31domokatois record access supposed to be faster than map access?
18:33sdegutisjustin_smith: I guess I can do (.stop server) and GC it, and create another one when the time comes...
18:34domokatonevermind. i thought my timings were coming out the same, but my code was just wrong
18:44sdegutisnm found https://github.com/weavejester/ring-jetty-component/blob/master/src/ring/component/jetty.clj
18:44sdegutisLooks like I really ought to start using real-life Components, not just records.
19:04TEttinger,(defmacro pi [] `(float 3.141592))
19:04clojurebot#'sandbox/pi
19:04TEttinger,(pi)
19:04clojurebot3.141592
19:06TEttingerI'm curious if anyone knows if that method of declaring a "primitive constant" has some flaw I haven't seen. AFAIK, defining a value boxes it and I don't know how you typically get around that
19:20neoncontrailsTEttinger: Would you expect otherwise? I'm not being snarky, just curious. In my mind, functions are always preceded by parens, and macros are a kind of function (even when they have 0-arity)
19:42TEttingerneoncontrails: yeah, I'm just unsure of any other way to propagate (float 3.141592) into the code without storing it as a capital-F Float and suffering boxed math issues
19:43neoncontrailsOh, I see. Math/PI is out of the question?
19:44jeremyliteTEttinger: if it's a double, you can type hint function arguments to not box it
19:45neoncontrails,(defmacro pi [] '(float 3.1415926535897))
19:45clojurebot#'sandbox/pi
19:45neoncontrails,(def pie (pi))
19:45clojurebot#'sandbox/pie
19:45neoncontrails,pie
19:45clojurebot3.1415927
19:45neoncontrailsThat work?
19:45jeremyliteneoncontrails: he's talking about java's boxed primitives
19:45jeremylitefloat vs java.lang.Float
19:46justin_smithwith the macro, clojure shouldn't need to box
19:46neoncontrailsOhh, right. The autoboxing behavior
19:53TEttingerjustin_smith: can you elaborate?
19:53TEttinger,(defmacro piii [] 3.1415926535897)
19:53clojurebot#'sandbox/piii
19:53TEttinger,(piii)
19:53clojurebot3.1415926535897
19:54TEttingerwould that box it?
19:54jeremylitei'm finding this difficult to debug in a repl
19:54TEttingerno kidding. try: (set! *unchecked-math* :warn-on-boxed)
19:54TEttinger,(set! *unchecked-math* :warn-on-boxed)
19:54clojurebot#error {\n :cause "Can't change/establish root binding of: *unchecked-math* with set"\n :via\n [{:type java.lang.IllegalStateException\n :message "Can't change/establish root binding of: *unchecked-math* with set"\n :at [clojure.lang.Var set "Var.java" 221]}]\n :trace\n [[clojure.lang.Var set "Var.java" 221]\n [sandbox$eval145 invokeStatic "NO_SOURCE_FILE" -1]\n [sandbox$eval145 invoke "NO_S...
19:55justin_smithwell, that works locally
19:55TEttinger,(with-bindings [*unchecked-math* :warn-on-boxed] (* 2 (piii)))
19:55amalloywhy not just (def ^:const pi 3)
19:55clojurebot#error {\n :cause "Unable to resolve symbol: piii in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: piii in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6704]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: piii in this co...
19:55TEttinger,(defmacro piii [] 3.1415926535897)
19:55clojurebot#'sandbox/piii
19:55TEttinger,(with-bindings [*unchecked-math* :warn-on-boxed] (* 2 (piii)))
19:55clojurebot#error {\n :cause "java.lang.Boolean cannot be cast to clojure.lang.IMapEntry"\n :via\n [{:type java.lang.ClassCastException\n :message "java.lang.Boolean cannot be cast to clojure.lang.IMapEntry"\n :at [clojure.lang.Var pushThreadBindings "Var.java" 317]}]\n :trace\n [[clojure.lang.Var pushThreadBindings "Var.java" 317]\n [clojure.core$push_thread_bindings invokeStatic "core.clj" 1818]\n [c...
19:55justin_smithTEttinger: at compilation time, the macro is expanded, so it should not need to box a value coming directly from a macro
19:56TEttingeramalloy: I wasn't aware of ^:const
19:56amalloyi don't think clojure will do any math on float primitives anyway
19:56amalloyso all you could really do with such a const is pass it to a java method
19:56TEttinger,(doc with-bindings)
19:57clojurebot"([binding-map & body]); Takes a map of Var/value pairs. Installs for the given Vars the associated values as thread-local bindings. The executes body. Pops the installed bindings after body was evaluated. Returns the value of body."
19:57TEttinger,(defmacro piii [] 3.1415926535897)
19:57clojurebot#'sandbox/piii
19:57TEttinger,(with-bindings {*unchecked-math* :warn-on-boxed} (* 2 (piii)))
19:57clojurebot#error {\n :cause "java.lang.Boolean cannot be cast to clojure.lang.Var"\n :via\n [{:type java.lang.ClassCastException\n :message "java.lang.Boolean cannot be cast to clojure.lang.Var"\n :at [clojure.lang.Var pushThreadBindings "Var.java" 318]}]\n :trace\n [[clojure.lang.Var pushThreadBindings "Var.java" 318]\n [clojure.core$push_thread_bindings invokeStatic "core.clj" 1818]\n [clojure.core$...
19:57TEttingerthe heck...
19:57TEttinger,*unchecked-math*
19:57clojurebotfalse
19:58amalloyTEttinger: (a) you want binding, not with-bindings; (b) using binding to set a compiler option doesn't work
19:58TEttinger,(binding [*unchecked-math* :warn-on-boxed] (* 2 (piii)))
19:58clojurebot6.2831853071794
19:58TEttingerit's not a compiler option is it?
19:58TEttingeryou can set it at runtime
19:58justin_smithTEttinger: the reflection warnings happen on compilation
19:59justin_smithTEttinger: try eval inside the binding block
19:59TEttinger,(binding [*unchecked-math* :warn-on-boxed] (eval '(* 2 (piii))))
19:59clojurebot6.2831853071794
19:59TEttinger,(let [p (piii)](binding [*unchecked-math* :warn-on-boxed] (eval '(* 2 p))))
19:59clojurebot#error {\n :cause "Unable to resolve symbol: p in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: p in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6704]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: p in this context"\n ...
20:00TEttinger,(binding [*unchecked-math* :warn-on-boxed] (eval '(let [p (piii)](* 2 p))))
20:00clojurebot6.2831853071794
20:00TEttingerso let bindings preserve primitive-ness?
20:00amalloy,(binding [*unchecked-math* :warn-on-boxed] (eval '((fn [n] (+ 1 n)) 1)))
20:00clojurebot#error {\n :cause "denied"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.SecurityException: denied, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 6891]}\n {:type java.lang.SecurityException\n :message "denied"\n :at [clojurebot.sandbox$enable_security_manager$fn__835 invoke "sandbox.clj" 69]}]\n :trace\n [[clojureb...
20:00TEttinger,(def p-uh 3.14)
20:00clojurebot#'sandbox/p-uh
20:01TEttinger,(binding [*unchecked-math* :warn-on-boxed] (eval '(* 2 p-uh)))
20:01clojurebot#error {\n :cause "denied"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.SecurityException: denied, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 6891]}\n {:type java.lang.SecurityException\n :message "denied"\n :at [clojurebot.sandbox$enable_security_manager$fn__835 invoke "sandbox.clj" 69]}]\n :trace\n [[clojureb...
20:01TEttingerah, we can't get compilr warnings
20:01amalloywhy did it let TEttinger eval once?
20:01TEttingerbecause I didn't throw an unchecked warning
20:01TEttinger,(binding [*unchecked-math* :warn-on-boxed] (eval '(* 2 3)))
20:01clojurebot6
20:02TEttinger,(binding [*unchecked-math* :warn-on-boxed] (eval '(* 2 p-uh)))
20:02clojurebot#error {\n :cause "denied"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.SecurityException: denied, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 6891]}\n {:type java.lang.SecurityException\n :message "denied"\n :at [clojurebot.sandbox$enable_security_manager$fn__835 invoke "sandbox.clj" 69]}]\n :trace\n [[clojureb...
20:02TEttingerwhen it throws the warning, something gets blocked by the sandbox
20:02ed-g(inc tcrayford)
20:02ed-g(inc amalloy)
20:07justin_smithTEttinger: OK, so like I said a macro returning the float avoids reflection, right?
20:12TEttingeryep, it makes sense now, thanks justin_smith
20:16irctcquit
22:31Guest___What's the preferred lib for making http calls from ClojureScript?
22:36justin_smithGuest___: I think people usually use js/Ajax via interop
23:12dnolenGuest___: goog.net.XhrIo works fine, there are a few core.async based wrappers too
23:12Guest___Thanks. Taking a go at https://github.com/JulianBirch/cljs-ajax for now