Fork me on GitHub
#clojure
<
2016-01-08
>
lambeta01:01:28

Hi hivemind, I wanna [1 1 1 1 10 1 1] to be [ (1 1) (1 1) (10 0) (1 1)], is there any good way to do?

lambeta01:01:55

partition is not enough for me because I need to add 0 after 10.

johanatan01:01:53

what is the rule for when to add 0?

johanatan01:01:56

anything non-1 ?

meow01:01:42

@lambeta: I would use replace to turn every 10 into a 10 0 pair, cat that together, then use partition for the final result

johanatan01:01:35

Or flatten instead of cat no?

johanatan01:01:45

i.e., (flatten (map #(if (= %1 10) '(10 0) %1) orig))

meow01:01:03

I tend not to use flatten as it goes deep and I rarely need that, but sure.

johanatan01:01:05

or yea mapcat

meow01:01:44

could also use transducers, perhaps

johanatan01:01:45

(mapcat #(if (= %1 10) '(10 0) '(%1)) orig)

meow01:01:08

no real context was given so its hard to say what would be best

meow02:01:31

there are two challenges: 1. what code will do the job 2. what code communicates the best (ignoring performance requirements)

lambeta02:01:30

BTW, the position of 10 should be odd

johanatan02:01:56

if it weren't then you'd end up with a (1 10) (0 1) combo of pairs in your result (with the code I posted)

johanatan02:01:53

but if it were, then all is well.

meow02:01:57

(partition 2 (mapcat (fn [v] (or ({10 [10 0]} v) [v])) [1 1 1 1 10 1 1]))

meow02:01:36

looks horrible with those literals

meow02:01:00

100 ways to skin this cat

johanatan02:01:11

How is that any better than the code I posted?

johanatan02:01:22

Seems like if would perform better than a map lookup

meow02:01:58

since there was no context given there is no way to evaluate any of the solutions

johanatan02:01:18

huh? the two solutions provided are functionally equivalent

johanatan02:01:08

So, still my question remains-- how is an or (a branch), a map construction, and a lookup within that map better than just an if (a branch)?

meow02:01:34

I made the assumption that there was more to this question than meets the eye and responded with how I think about transforming data.

meow02:01:16

Without any context why is performance or even code readability a concern?

johanatan02:01:45

ahh, yea. the skeleton is there either way-- which road you take could vary depending on the particular data involved.

johanatan02:01:53

Well, you can take the question at face value (though yes it is a bit ambiguous) and within that fixed structure, then you can compare codes for 1) readability and 2) performance. I would sacrifice performance for readability but in my opinion, the code you posted is worse on both axes (in absence of any extra requirements which your framing of the solution would help with)

meow02:01:46

There are patterns (ala the gang of four patterns and christopher alexander) even in functional design

johanatan02:01:18

Yes, and if you follow that logic then there are anti-patterns too

johanatan02:01:24

i.e., premature abstraction

meow02:01:23

Right. So what I did was look at my real code to see why I was thinking about the problem the way I was and this is what I found:

(defn rewrite
  "Returns a successor, which must be a vector or a function. If no match is
   found in the rules mapping, the original module is return within a vector."
  [rules m]
  (or (rules m) [m]))

(defn rewriting
  "Returns a rewriting transducer."
  [axiom rules generation]
  (map (partial rewrite (get-rewriting-rules axiom rules generation))))

johanatan02:01:55

Gotta run! Good evening!

meow02:01:01

replace that with literals and it looks like crap

johanatan02:01:01

Yea, if I had those functions in my toolbag, I'd certainly use them. I'm a fan of bottom-up design (which I think most LISPers adhere to).

j1mr10rd4n03:01:46

hi all, first time to #C03S1KBA2… i’m dipping my toes into the clojure waters and i’ve got a question about the style guide at https://github.com/bbatsov/clojure-style-guide, specifically about indenting… the guide suggests indenting by 2 spaces the bodies of any forms that have body parameters… I understand why a defn/defmacro form has a body parameter, but what is a body parameter when calling a macro? e.g. the good when example at https://github.com/bbatsov/clojure-style-guide#body-indentation

meow04:01:32

;; good
(when something
  (something-else))

meow04:01:23

You're going to love this. You're going to tell me the answer to your own question.

meow04:01:51

then click on the "source" link off to the right of the function definition on that page

meow04:01:01

(defmacro when
  "Evaluates test. If logical true, evaluates body in an implicit do."
  {:added "1.0"}
  [test & body]
  (list 'if test (cons 'do body)))

meow04:01:14

Did that succeed in answering your question, or not? simple_smile

j1mr10rd4n04:01:07

well, any argument(s) you pass after the first one are bound to the symbol “body”, is it that simple or am i missing something?

meow04:01:51

I think you've got it.

meow04:01:35

What editor are you using? One like Cursive/IntelliJ does nice indenting/formatting for you.

j1mr10rd4n04:01:43

but that would imply, as per my understanding of the style guide, that had the macro author decided on a different name for their arguments “predicate” and “when-true” say, any code calling the macro should be differently indented - or is there a convention to say when a macro argument should be called “body”… i guess i’m trying to ask if there is a more concrete definition of what is a “body-parameter” than a parameter that the author decided to name “body”

meow04:01:39

I think you are reading too much into this, but these are good questions. There is the notion of the "body" and the convention of naming the parameter body.

meow04:01:13

but naming it something else wouldn't alter the style guide recommendation

j1mr10rd4n04:01:57

probably reading too much into it - it was spurred by the thought of “how do i tell vim about this rule?"

j1mr10rd4n04:01:10

and trying to explain it to myself first

meow04:01:18

these rules tend to be baked into the editor

j1mr10rd4n04:01:35

editors don’t bake themselves 😉

meow04:01:48

no, only cookies can do that

meow04:01:58

is there a cursive mode or plugin for your vim?

meow04:01:20

lots of folks use vim mode in Spacemacs for clojure

meow04:01:16

I prefer the Cursive plugin for IntelliJ IDEA myself. Lots of emacs users here too. It's all good.

j1mr10rd4n04:01:27

but the indentation is slightly different from the style guide

meow04:01:57

there is an #C050AN6QW channel here where you might find vim people who could offer tips

j1mr10rd4n04:01:08

excellent, thank you

juhoteperi06:01:43

@j1mr10rd4n: check options g:clojure_fuzzy_indent and local lispwords. Here is what I use: https://github.com/Deraen/dotfiles/blob/master/.vim/after/ftplugin/clojure.vim

hans10:01:47

I wonder what the best way to generate a class that can be accessed from java would be. I need to create a .war file that contains a class which implements a certain interface and is instantiated from a Java application. It seems the :gen-class and AOT compilation would make the most sense, but maybe I can also place a reify expression on the top level of a file and AOT that. Does anyone have advice?

robert-stuttaford10:01:28

clojure 1.6 added niceties for this

hans10:01:32

Right, I've seen that SO post and as there were multiple answers claiming that they would be "best", I thought I'd ask here to confuse me more simple_smile

hans10:01:13

No, but really - The clojure.java.api method seems to require that I need to be called first and then compile the required classes, or am I wrong?

robert-stuttaford10:01:15

start with clojure.java.api and see where that takes you; it’s the newest capability the Clojure language offers

robert-stuttaford10:01:32

i’m not sure. i’m kind of winging this answer because i’ve not done this myself simple_smile

hans10:01:03

Okay. Thanks for your honesty simple_smile

robert-stuttaford10:01:47

i jumped in mostly because i knew that 1.6 added stuff for this. good luck simple_smile

jstaffans11:01:49

@hans: not sure if I understood your question correctly, but I have had some success with a pattern like this for interacting with a Clojure library (included as a standalone JAR) from a Java application: https://gist.github.com/jstaffans/747504f0150c8ada0e1d

hans11:01:10

@jstaffans: Thanks, exactly that was what I was looking for!

mbertheau15:01:17

How much of the way that libraries like medley and plumbing or useful lay do transducers go?

meow15:01:38

@mbertheau: Can you rephrase that question? I don't understand it.

darwin15:01:32

I’m running a long-running task in background from my REPL. It does println during its lifetime and that breaks my REPL prompt. I have control over those println calls. Is there a way how to do println, but restore REPL prompt somehow?

mbertheau15:01:59

@meow: I mean that these libraries exist and provide functions for manipulating maps like filter-vals and others, which could reasonably expected to be in core. To implement the corresponding functionality with core functions would mean verbose and rather unreadable code. Now concerning transducers I only watched Rich's talk about them, but never used them in practice. I wonder if transducers make many of the functions in these utility libraries obsolete, in the sense that with transducers you can implement their functionality succinctly and readably.

meow15:01:48

@mbertheau: Gotcha. I've used transducers a fair amount. I don't think they take away the need for those libraries.

meow15:01:50

Transducers aren't the solution to every problem.

meow15:01:40

Transducers really only apply when you are transforming data in a single pass and you want to apply multiple small transformations to that data.

meow15:01:57

Transducers provide a nice mechanism to compose those transforming functions and apply them to collections without concern for the type of collection.

meow15:01:21

There are plenty of times where I need to manipulate data in a way that doesn't match what I just described and so I don't use transducers there because they don't apply, and so I still might have a need for the kinds of functions that exist in those libraries you mentioned.

meow15:01:02

When I have a need for a transducer I gladly use them - I love transducers.

mbertheau15:01:13

@meow: Hmm, ok, thanks. I should try out transducers anyway, so I know when they're useful.

meow15:01:00

I highly recommend taking a look at the into function which can take an optional transducer.

meow15:01:35

into is the "swiss army knife" for data transformations

meow15:01:44

probably my favorite clojure function

bobbycalderwood15:01:47

@cddr Yes, single stream of commands from web tier to Kafka topic pending-commands. Then business logic processes that stream and writes to either accepted-commands or failed-commands topic. You could certainly have different jobs on different stream consumers for each type of command, and rely on filtering to only present the desired command types to a given unit of business logic.

mbertheau15:01:59

@meow: If you have a little time, do you have any insight into how I could make this function more readable? https://gist.github.com/mbertheau/ebdf995dc3c635e1f55e

cddr15:01:07

Do you have enough throughput that you need to partition the command log? If so what do you use for the partition key?

bobbycalderwood16:01:39

@cddr: total ordering in Kafka is only guaranteed within a partition, so a given command log would have to be single partition

bobbycalderwood16:01:41

throughput per partition is quite high in Kafka (see various benchmarks on the web), but you could give orthogonal command types separate command streams if throughput becomes a problem

akiva16:01:27

Hey, gang, is it better to do database access wrapped in a with-open binding or just keep a connection open at all times bound to a var? The database is small and hosted on the same machine as the web server.

akiva16:01:50

I’m more interested in what’s more idiomatic these days.

roberto16:01:10

use a connection pool

roberto16:01:15

that would be my advice simple_smile

lvh16:01:48

How can I get (partition 2 1) as a transducer? partition-all is a transducer, but that’s not what I want.

ghadi16:01:29

lvh: nothing in core does it, but https://github.com/cgrand/xforms does

lvh16:01:39

ghadi: cool, thanks

ghadi16:01:29

akiva: always use a db argument

ghadi16:01:36

never bind to a var

ghadi16:01:59

roberto's advice is orthogonal to how you manage the state

ghadi16:01:30

I've found the component library to help out a lot

akiva16:01:13

Yeah, this app uses Component.

meow16:01:17

@mbertheau: Not sure I'll be able to do that. Lots going on.

meow16:01:11

@mbertheau: there is also #C053PTJE6 channel

mbertheau16:01:30

Oh, nice! I'll try there.

akiva16:01:02

@ghadi, thanks, by the way; I didn’t even think about handling the connection via Component.

ghadi16:01:08

you wouldn't even have to handle the connection/pool with component, just the spec for the connection/pool. You'd still with-open for scoped usages

jarredlhumphrey18:01:49

Anyone have any suggestions for automated benchmarks in a leinengen project? I’ve been playing around with criterium (https://github.com/hugoduncan/criterium) and perforate (https://github.com/davidsantiago/perforate) which work hand in hand, but it seems perforate hasn’t had any active development for more than a year so I’m hesitant to start relying on it too heavily. Is there a more prominent library out there for this? or how do others usually solve this?

ghadi19:01:33

criterium is what you want

ghadi19:01:21

1) don't use leiningen while benchmarking if possible. If not possible 2) Always use :jvm-opts ^:replace [...blah]

ghadi19:01:36

lein trampoline run -m project.benchmark

ghadi19:01:21

the way we benchmark clojure itself is usually java -cp ... clojure.main -m thenamespace

esnunes19:01:50

I have a general question, I believe it applies to both Clojure and ClojureScript. You, experienced guys, when you start a project do you have to deal with a lot of boilerplate? I'm coming from js/nodejs world which is getting more complex every day, what is you feeling about cl/cljs?

shaun-mahood19:01:43

@esnunes: I find it much, much simpler to navigate the start of a project than I would in the JS world. Still can be difficult, and there is a pretty significant amount to learn at the start, but it doesn't seem to have the crazy explosion of extra choices and complexity as the JS world does to me.

esnunes19:01:20

thanks @shaun-mahood , I don't mind learn a lot of things in order to develop something, what bothers me is the amount of source-code I have do create (or copy n paste) to bootstrap a project

shaun-mahood19:01:26

@esnunes: It feels like very little to me. For cljs, it's worth starting with the figwheel/devcards templates. In clj, Luminus is a popular template but I prefer starting from a bare project and adding things as needed.

jarredlhumphrey19:01:43

@ghadi: whats the purpose of the jvm-opts update if using leinengen? is this just due to leinengen defaults that aren’t optimal to benchmarking and production code? If we already are altering the jvm-opts to better match our production config in our profiles, is that sufficient? Or am I missing something?

noisesmith19:01:43

lein disables hotspot, basically. And you need the ^:replace metadata to avoid that flag.

ghadi19:01:47

jarredlhumphrey: yeah you hit it. if you don't specify ^:replace your opts are merged with lein's opts. You should always control things explicitly

jarredlhumphrey19:01:09

ghadi: awesome thanks man

noisesmith19:01:13

and without hotspot, your profiling won't reflect an optimum server runtime

jarredlhumphrey19:01:28

noisesmith: gotcha.. I’ll have to dive more deeply into the default jvm-opts lein uses. thx

noisesmith19:01:10

jarredlhumphrey: you shouldn't be running lein at all on a prod machine anyway, that's what uberjars are for

ghadi19:01:24

run your project then run jps -v from the commandline

ghadi19:01:58

should show you what is being added

noisesmith19:01:29

cool, jps is a trick I'll need to remember

ghadi19:01:30

lots of the jvm management things are great. jstack when stuff hangs/deadlocks, jmap jdump when you want to snapshot heaps

jarredlhumphrey19:01:11

noisesmith: yea we def dont run lein on our prod servers 😉

jarredlhumphrey19:01:44

ghadi: awesome I’ll dig into those tools

noisesmith19:01:28

@jarredlhumphrey: you'd be surprised how many people do, so I try to make a point of mentioning it

sharms20:01:44

I have a sequence of strings ("line 1" "line 2" "line 3") and I want to add "line 4" to the end of it - whats the most pragmatic way

srdjan20:01:34

@sharms: I believe that if you have a vector, conj will add to the end of it. If you have a list, it’ll add to the front of that. That’s how these data structures are optimized

sharms20:01:58

ok I can convert it to a vector easily enough

sharms20:01:16

just didn't know if there was a better way - I created the seq by using line-seq from a BufferedReader

srdjan20:01:52

yeah, you can use vec to convert the sequence to a vector

meow20:01:07

@esnunes: as far as boilerplate goes I think that you will find that clojure has little to no boilerplate at all, depending on the type of app you are developing. When you start using various libraries and frameworks you might have more or less, but on the whole it is less that I have ever experienced in about 30 years of programming

voxdolo21:01:01

Am I missing some core function that takes a value and a function calls the function for side-effects on the value then returns the original value?

voxdolo21:01:39

seems like that's a thing that would exist and I want it regularly… easy enough to write (if I could figure out what the heck to call it)

jr21:01:29

@voxdolo: doto ?

user=> (doto "foo" println)
foo
"foo”

voxdolo21:01:50

that'd do it 😄 Thanks @jr!

voxdolo21:01:41

I've only ever used it for Java interop. Didn't even occur to me.

ghadi21:01:27

an lovely idiom i picked up from a former coworker: (doto 'my.application require in-ns)

bridget21:01:43

I like that one, too, ghadi simple_smile

akiva22:01:52

Interesting.

peterbak23:01:14

anybody know of a macro that's a mix of cond and a bunch of if-let? something of the form

(cond-let
  [var1 (some-test)] (blah var1)
  [foo (test-bar)] (do-something foo)
  etc)
where it finds the first binding that's not nil and returns result of the corresponding clause.... is this making any sense? is there a concise way to do this using existing macros?

peterbak23:01:35

i guess it could be a fun exercise to write one...

peterbak23:01:48

partially answering my own question: one can do that by stringing together a bunch of when-let in an or