Fork me on GitHub
#clojure
<
2016-11-26
>
martinklepsch13:11:05

is there a built-in/popular way of printing strings while maintaining a max-width like 80 chars?

robert-stuttaford13:11:04

pretty sure i saw line length in the pretty-printer stuff

rauh14:11:56

@martinklepsch Usually called "word wrap", you'll probably find a ton in Java/Clojure I'd bet.

martinklepsch14:11:38

@robert-stuttaford there's stuff in pprint but wasn't entirely sure how applicable that is. probably you're right and it's perfectly fine though

martinklepsch14:11:51

heh, just was on the same pages 😄

amacdougall16:11:34

What's the most straightforward way to select an implementation (a Strategy, for the pattern-inclined)? My exact situation: I have multiple maze generation algorithms, and I realize that each can be expressed in terms of three functions: initial-values, complete?, step, and result. For instance,

(loop [step-values (initial-values grid)]
  (if-not (complete? step-values)
    (recur (step step-values))
    (result step-values)))
; the result function encapsulates knowledge of the step-values structure
This is pretty easy to code! Each algorithm could have its own implementation of step, and its own spec for the step-values datatype. But although it's easy to :require [some-generator :refer [initial-values complete? step-values result]], I'm not sure how to switch behavior at runtime.

amacdougall16:11:14

For now, I'm going to predefine something like:

(def generators
  {::alpha {::initial-values alpha/initial-values, ...},
   ::beta ...})
And then I can implement (generate-maze {::grid grid, ::algorithm ::alpha}) pretty easily. But it seems like there should be something a bit easier.

amacdougall16:11:27

My near-term goal is to provide a strategy selector for a web-based demo; the longer-term goal is to create very large mazes where different areas use different algorithms. In either case, choosing strategies dynamically will be very helpful.

gfredericks16:11:52

@amacdougall protocols and multimethods could both work

amacdougall16:11:22

That was my first thought—I'm just not sure how to set it up. Multimethods and protocol functions both change their behavior based on the type of the argument, right? But what would the argument be in this case? The point is that the original input to the generator (a grid with no connections between cells) is the same... it's only the linking strategy that changes. I guess there could be a strategy flag that gets passed along all the functions.

gfredericks16:11:57

Yeah you have to pass the strategy around

gfredericks16:11:30

If you hate that and like magical things, you probably want to store the strategy in a dynamic var

gfredericks16:11:05

Combining a dynamic var and a protocol wouldn't be too weird

amacdougall16:11:09

In an OO language, you'd say something like generator = new SpecificGenerator and then not worry about the generator type from that point on. But of course that's a setting in a mutable config variable (essentially... we just call it an "object", but from a PL perspective they're kind of equivalent).

gfredericks16:11:39

You'd still have to pass that around, right?

amacdougall16:11:42

I'll think about it. I'm already using a multimethod to choose SVG rendering methods based on the algorithm I'm trying to animate.

amacdougall16:11:01

Oh, of course—the convenient aspect of the OO approach would be that once you've assigned a specific generator to the generator variable, you can call generator.foo without further consideration of the generator's type. But then if I just make :strategy one of the keys in step-values, this all works fairly smoothly. I just need to declare a higher-level ::generator/strategy keyword in a namespace accessible to everyone that uses this API.

amacdougall16:11:44

clojure.spec seems to be leading me in the direction of using a lot of big nested hashes everywhere, because it makes it relatively easy to understand and enforce their contents. Not sure if that's good or bad overall.

amacdougall16:11:59

When in doubt, add another (namespaced) key (which refers to a spec defined elsewhere) to the hash!

gfredericks16:11:55

@amacdougall I think a protocol would have the same conveniences

amacdougall16:11:57

Anyway, an end user could say, I guess...

(re-frame/reg-event-db
  :step-generation
  (fn [{:keys [::g/grid
               ::generator/strategy
               ::generator/step-values] :as db} _]
    (if (nil? step-values)
      (assoc db ::generation-step (generator/initial-values grid strategy))
      (assoc db ::generation-step (generator/step step-values)))))

amacdougall17:11:58

And the final form works because step-values includes a ::generator/strategy key which we use to dispatch the multimethod. Or protocol, but this seems like a more natural fit for multimethods, unless I defrecord the different step-values types.

amacdougall17:11:30

The re-frame aspect is incidental here.

gfredericks17:11:29

You can use reify instead of defrecord

gfredericks17:11:48

Which is something that multimethods don't have an analog for

martinklepsch17:11:27

Anyone aware of libraries designed to let you nicely print things to a terminal? Looking for something that would help visually structuring output similar to what markdown helps with. (Maybe it could even take markdown as input?)

dominicm19:11:46

@martinklepsch there's a clojure library called pretty I think. Boot uses it :)

dominicm19:11:14

Can't think of an actual visual structuring language though really

hiredman21:11:57

both fipp (if I recall correctly) and that paper look at pretty printing in sort of two phases, 1. building some kind of layout document and 2. laying out that document

hiredman21:11:38

the paper is very nice, even if it isn't state of the art in pretty printing anymore

rcanepa22:11:47

Hello everyone! I am a bit lost about how lein compile works. I am trying to incorporate Java code (wsdl client) into my web application backend. I added the sources to src/java folder, and then I specified that path in the project.clj file: :java-source-paths ["src/java"]. However, when I execute lein compile nothing happens, and when I execute lein repl I get a java.lang.ClassNotFoundException. If I remove the import statement from my Clojure code (which imports the wsdl classes), lein repl start without errors, and it also compiles the Java classes. From that point an on, I can uncomment the import statement, execute lein repl and it doesn't throw a java.lang.ClassNotFoundException. Does anyone know why this is happening? Why doesn't lein compile compile those classes when I execute it?

hiredman22:11:56

lein compile is for compiling clojure code

rcanepa22:11:03

Oh, sorry, I forgot to say that I tried that too. It throws the same java.lang.ClassNotFoundException.

rcanepa22:11:22

I don't understand why it "loads" my Clojure code.

rcanepa22:11:56

It seems that in order to compile the java sources, Clojure runs the user.clj (I don't know why) namespace first. And because I am using the Clojure Reloaded approach (with components), this bring all my Clojure code, including my import statement.

gfredericks22:11:57

user.clj is special

rcanepa22:11:17

Yeah, if I remove from my project.clj file the :source-paths of the :dev configuration map, lein javac runs ok.

rcanepa22:11:40

Of course, lein repl stops working too.

rcanepa23:11:09

I found a solution! Executing lein with-profiles test javac works because it doesn't need the user.clj namespace.

tdantas23:11:15

maybe too noobie, but I have to ask I’m doing my first web app using clojure and I’m not comfortable with the following code. The code is to signup a brand new user in the system

(ns user.service)

(require '[user.sql :as sql])
(require '[user.domain :as user])
(require '[web.utils :as reply])

(defn signup-user [pgsql new-user]
  (if-not (user/valid? new-user)
    (reply/bad-request {:message "Invalid user payload"})
    (if (nil? (sql/find-by-email pgsql (:email new-user))))
      (reply/success (sql/save pgsql new-user))
      (reply/conflict {:message "Email already been taken"})))
------------------------
;; signup-handler

(ns user.handlers)
(defn signup-handler [request]
  (user/signup-user (:database request) (:body request)))

tdantas23:11:49

is the signup-user how you guys normally does ?

tdantas23:11:46

what if I have to send email to the new persisted user after save on database. how do you guys normally does that ?