Fork me on GitHub
#clojure
<
2017-05-04
>
arthur00:05:36

@piotrek in SO pointed out that I should be able to extend ring.core.protocols/StreamableResponseBody to do this

(extend-protocol protocols/StreamableResponseBody
  LinkedBlockingQueue
  (write-body-to-stream [output-queue _ ^OutputStream output-stream]
    (log/error "starting")
    (with-open [out (io/writer output-stream)]
      (.write out "starting")
      (loop [chunk (.take output-queue)]
        (log/errorf  "got chunk %s" chunk)
        (when-not (= chunk ::EOF)
          (.write out (str chunk))
          (.flush out)
          (recur (.take output-queue)))))))

arthur00:05:52

though I'm trying to figure out whey that handler doesn't actually run for me

arthur00:05:19

and setting the jetty output buffer size to one does make it "work" though that's a bad idea for other reasons i suppose

weavejester00:05:41

It might be because Jetty has a set buffer size that doesn’t support flush.

arthur00:05:47

ok so it works if I jump into ring.util.servlet and reload the buffer with the repl

arthur00:05:29

then it starts calling my extension to ring.core.protocols/SreamableResponseBody

weavejester00:05:44

Reloading protocols in the REPL does have some caveats I believe. Not sure if that affects records only or existing class extensions as well.

arthur00:05:39

I don't normally need to reload the library that uses a protocol to have it notice that I extended that protocol right?

weavejester01:05:45

I don’t believe so.

arthur01:05:02

It does seem to work when all the protocol is extended in a namespace that's loaded initially, so this is a REPL only situation whatever it is that's going on here

wei01:05:16

can anyone point me to a good article explaining the viewpoint of not using namespace aliases?

tbaldridge01:05:37

@wei of not using them? I'm not sure that I've seen any. What problems are you anticipating?

noisesmith02:05:48

where namespace alias is an alternative to unqualified import perhaps?

wei07:05:47

@tbaldridge the arguments I’ve heard for using fully-qualified names for every function call are related to readability. interested to see the argument fleshed out in an article and I was wondering if anyone has written about it

wei07:05:11

I’ve been preferring one-letter namespace aliases for conciseness, so I’m interested in hearing the opposite view

qqq09:05:54

I've been playeing with one letter namespaces

qqq09:05:00

so stuff is named things like c for client

qqq09:05:06

and client/gui.cljs instead would be c/g.cljs

qqq09:05:17

then, when I import the namesapce, it's just [c.g] and its' short enough to not need to alias

tbaldridge11:05:15

qqq: that sounds horrible. Now I never have a clue what the namesapce I'm in is doing.

tbaldridge11:05:50

That saves like what...10 characters? What's the use-case that makes that a good tradeoff

qqq16:05:27

you can put a comment at the top of the namespace, for ecample:

(ns c.g)
;; client.geom

bronsa09:05:56

why would you do that

lincpa09:05:58

use last part of namespace as aliasename , example: (:require [http://aa.bb.cc :as cc] [xx.yy.core :as yy])

lincpa09:05:38

Try to keep the alias globally unique, just like best practices for database naming

lincpa09:05:37

also convenient to generate notepad++ autocomplete file.

stathissideris09:05:15

is it possible to refer to a gensym generated with the # syntax from inside ~?

leonoel10:05:51

just quoting it with backtick returns the generated symbol

bronsa10:05:05

you'll have to manually use gensym

bronsa10:05:58

auto-gensyms only exist within the backtick context they were created in

stathissideris10:05:59

@bronsa thanks, I thought I was missing something 🙂

bronsa10:05:24

if you

`[a# ~`a#]

bronsa10:05:32

this will generate 2 different gensyms, one per backtick context

stathissideris10:05:06

got it. It’s just that I end up using gensym “manually” most of the time and I thought that maybe there was a way to avoid it that I didn’t know about

xsyn11:05:10

@ctford Hi there. I’m hoping you could help me understand something with Leipzig (which I order by the way), I’m passing in nils to act as breaks in phrases, but when I use live/play it silently fails and stops playing entirely when it gets to the nil. Is this behaviour you’ve experienced before?

tbaldridge11:05:42

@wei, I haven't heard convincing arguments to not use namespace aliases. Most programs will have a convention to them that makes their aliases make sense in the context of the project. As a consultant I read a lot of code written by other people, and the aliasing of namespaces has never been a problem for readability. Problems with readability I've encountered are much more around things like overuse of higher order functions, macros, etc.

mbjarland12:05:57

if I call a function from within a core.async go block and then try to use the >!, <! channel macros within that function it is considered "not in go(....) block". What's the rationale here?

mbjarland12:05:57

answering myself. Found a discussion around go block semantics at https://github.com/clojure/core.async/wiki/Go-Block-Best-Practices

elevi12:05:36

timeout returns the same object, for two different calls, I know it's memory efficient, but it's not the Clojure idiomatic way I guess

tjtolton13:05:44

is there a version of with-out-str that returns both the stdout string and the value that would have been returned from the expression?

tjtolton13:05:31

I want to basically do

(let [[elapsed result] (with-out-str (time (some-function)))] 
    (log elapsed)
    result)

moxaj13:05:59

@tjtolton I don't think there's anything like that in core, but if you check out the source, it's a really simple modification

tjtolton13:05:47

yeah, the example even has a simple version of it

tjtolton13:05:52

called with-out-str-data-map

moxaj13:05:18

@tjtolton fyi, the example should have (do ~@body), before it bites you 🙂

tjtolton13:05:37

when does that bite one?

tjtolton13:05:52

I'm not asking because I disagree, I'm asking because that's valuable information to have

moxaj13:05:03

try (with-out-str-data-map 1 2)

moxaj13:05:36

if you are on 1.9, you should get a really nice readable error message (jk)

tjtolton13:05:36

nice. great catch.

tjtolton13:05:42

I haven't run it yet

tjtolton13:05:57

but, in figuring out where to put that line, I realized the problem

ejemba14:05:51

hi o/ what is the best way to test clojure developement under mswindows ?

ejemba14:05:02

I know boot is not fully supported

mbjarland14:05:11

is the poison pill pattern considered an anti-pattern for core async pipelines? i.e. sending down a special value down a chain of pipelines to shut the "network" down

ghadi14:05:32

i wouldn't say it's an anti-pattern at all, but usually you close the channel instead of poisoning it

ghadi14:05:28

You'd use a different poison pill if you want to keep the channels open after poisoning

ccann15:05:05

does anyone have any conventions around using some?? I can’t think of when I’d ever use it over just checking the truthiness of the form instead, or using seq and empty? in the case of sequences

bronsa15:05:23

core.async

bronsa15:05:04

some? was essentially added to test for closed core.async channels

bronsa15:05:52

see also if-some

ccann15:05:57

interesting. because you might want false as a value?

ccann15:05:07

well thanks!

shayanjm15:05:24

I'm seeing a weird stackoverflow occur and I'm having a really hard time reasoning about it

shayanjm15:05:42

I have no idea why this is overflowing. My understanding is that this should be tail call optimized, so this sort of overflow shouldn't happen right?

bronsa15:05:26

he's not concatenating over the results of the iteration

dpsutton15:05:01

ah thanks for the clarification for me

dpsutton15:05:44

I see link-snapshot is either (get-as-hickory ...) or its an error. But either way you call (data-parser-fn link-snapshot) on it. Is it possible you fail above and then call data-parser-fn on data that doesn't make sense?

qqq16:05:35

case fails to match ==> exception cond failes to match ==> it just returns False ?

lmergen16:05:21

i think the reasoning is that cond is more like an if .. else if ... else if .... where case is more like a switch

qqq16:05:15

I see; it just surprised me as I'm used tocase throwing xceptions (which I then debug) on not matching, whereas cond just "silently return snil"

bronsa16:05:57

if anything case is the exception here, most things return nil in clojure on not found/no match

noisesmith17:05:31

@shayanjm so is that error happening inside (data-parser-fn link-snaphsot) ?

noisesmith17:05:34

if so, I bet data-parser-fn is doing something funky with nested lazy operations in a loop

lvh17:05:42

yeah, case is enumerating options, cond not necessarily

shayanjm17:05:48

@noisesmith that's a great question

shayanjm17:05:05

It's definitely happening in the link parser but didn't drill down into it

shayanjm17:05:19

I included a full trace which refers to hickory quite a bit

shayanjm17:05:29

I suspect you're likely right

negaduck17:05:01

hello. I’ve just used https://github.com/clojure/core.match in my re-frame pet project and it adds some clarity to my code. I wonder why it’s stuck at alpha version?

tbaldridge17:05:15

Well, to quote some maintainers of Clojure: " Because we don't really associate any emotional significance to the version number." 🙂

hiredman17:05:07

wellllll, the whole spec.alpha seems to telegraph feelings about the significance of the alpha designator, if not the version number

tbaldridge17:05:33

But last I heard (and I can't find the talk) there's also some open questions about how core.match should evolve in a language like Clojure that prefers open dispatch.

hiredman17:05:05

dnolen is also a busy guy

tbaldridge17:05:11

I.e. in a perfect world we could extend a match statement with new clauses from a different namespace, and yet not loose any of the performance or features of the original statement.

noisesmith17:05:51

there’s also the fact between for, doseq, match, and core.async you can use two, maybe three if you are lucky, in one nested scope, before your methods are too large for the jvm

noisesmith17:05:20

sometimes you can only get away with one, depending on how well the code is factored…

negaduck17:05:48

ok, but I mean it’s so useful

hiredman17:05:18

doseq is a neat nerdsnipe https://gist.github.com/ghadishayban/fe84eb8db78f23be68e20addf467c4d4 even with the neat approach there you still generate a fair bit of code

ghadi17:05:06

heh that code output doesn't even take into account chunked seq or the let/while/when clauses

ghadi17:05:06

99% of doseq's in the wild tho, do not use let/while/when

ghadi17:05:16

and most have a single binding

hiredman17:05:39

yeah, it is a rabbit hole, which makes it a neat puzzle, you think "oh this is simple, I'll just ..." and then five hours later you have something that frustratingly still doesn't cover all the edge cases

tbaldridge18:05:27

the compiler nerd side of me hates that Clojure isn't as simple as Scheme. Every other side of me is thankful that it's not.

xiongtx18:05:22

tbaldridge: Heard from @U2JSH5AGJ: someone should port cljs to the JVM!

tbaldridge18:05:48

It'd be a fun project, but remember, CLJS doesn't have threads, Vars, namespaces, type hints (the list goes on).

bronsa18:05:22

it does have type hints

tbaldridge18:05:42

kindof? Propagated type-hints?

bronsa18:05:42

slightly better inference than clojure even

tbaldridge18:05:51

heh, interesting

bronsa18:05:10

they're disjoint set in features/uses tho :)

tbaldridge18:05:45

I mean, Clojure JVM even requires a number system, CLJS doesn't

tbaldridge18:05:19

I sat down recently and thought about what CLJS on the JVM would look like and it's a nasty mess of circular deps.

bronsa18:05:23

cljs gets away with alot just by virtue of having to compile to js rather than to bytecode

bronsa18:05:53

i keep starting mini projects to self-host and bootstrap clojure but I always end up drowning in complexity, pulled between the ideal implementation that I'd like to build and the reality of compromises that need to be made in order to bootstrap

hiredman18:05:10

have you looked at shen's klambda? I haven't really, but I understand that it is like the IR for shen, so you can bootstrap shen on a new host by writing a klambda interpreter, and it must have some facilities for host interop and people have used it to bring up shen on a bunch of hosts

ghadi18:05:36

what sort of compromises @bronsa

michaellindon20:05:59

What are people using for data visualization from a clojure repl? 🙂

zane20:05:42

clojure.pprint/pprint 😁

zane20:05:00

In all seriousness, I'd love to hear others' answers to this.

jumar05:05:43

@U46LFMYTD not sure what kind of visualization you mean, but for the basic stuff, cider-inspect is quite good

michaellindon13:05:20

@U06BE1L6T cider-inspect is great, but I'm really looking for a charting library to create, say, boxplots or histograms etc...

darwin20:05:13

haven’t used it, but this looks impressive: https://atom.io/packages/proto-repl

michaellindon21:05:34

@darwin Its a good suggestion. When I was using Atom as my editor I was using proto-repl combined with this proto-repl-charts. Since switching over to Emacs and Cider I was not able to get proto-repl-charts to place nicely.

michaellindon21:05:48

Sorry, first time slack user. Is it better to reply in the thread or in the main channel?

darwin21:05:11

that’s pretty new feature, I guess most people don’t care

michaellindon21:05:15

So far I'm aware of the following ideas. Incanter uses Jfreechart, which I find creates very old fashioned looking plots, but its good you can use it from a repl. Proto-repl-charts is using C3.js as a backend, built on top of D3.js which is cool which creates plots in a browser window. Similarly gorilla-repl plots using a similar endeavour called vega,

michaellindon21:05:49

Both Vega and C3 are very healthy looking projects. https://github.com/c3js/c3 https://github.com/vega/vega

wiseman21:05:14

i’ve used gorilla-repl a bunch (http://viewer.gorilla-repl.org/view.html?source=github&amp;user=wiseman&amp;repo=leaflet-gorilla&amp;path=example-worksheet.cljw is one of the more involved examples, with a map renderer i wrote), but i would probably look to see what the state of jupyter/clojure integration was if i were doing that again.

michaellindon21:05:02

thats cool 🙂

bostonaholic21:05:18

it’s a logging library, so I imagine it’s pronounced “timber”, as someone would yell when chopping down a tree; in the logging industry.

mobileink21:05:03

timbre and timber are completely different. lumberjacks have timber, musical instruments have timbre ("TAM-br").

mobileink21:05:18

assuming it was intentional, it's a beautiful pun. different logging libs have different timbres, even tho they all log.

michaellindon22:05:18

I have a question about excluding dependencies when pushing to clojars. When I'm working on some code, I tend to have more "development dependencies" in my project.clj file than are needed for users when I push to clojars. For example I might have some testing dependencies or some visualization dependencies that I use when I'm writing and testing the code, but these do not need to be in the jar that I distribute. Is there a flag to list some dependencies as development, so that lein deploy clojars does not add these as dependencies for others?

zylox22:05:39

so like the test scope during maven build?

zylox22:05:41

because i think you can do that with profiles

Alex Miller (Clojure team)22:05:36

Yes, people use the dev profile for this in lein

michaellindon22:05:19

Ah, this is what I'm looking for. Thank you Alex