Fork me on GitHub
#clojure
<
2015-07-02
>
ordnungswidrig07:07:44

@dergutemoritz: regarding config as a component, how do you tackle the case that configuration should defined the actual composition of the system?

pupeno08:07:39

I just pasted unbalanced brackets into a file while structure mode is on in Cursive, how do I add the extra parenthesis to balance it?

sandbags08:07:04

pupeno: turn off structure mode temporarily

sandbags08:07:25

(edit>structural editing menu)

pupeno08:07:43

Yeah, I know how to turn it off and on. I was hopping it wasn’t needed.

cfleming08:07:56

@pupeno: You can disable SE briefly in the toolbar at the bottom of the screen, or you can cut&paste a closing paren.

sandbags08:07:14

cfleming: never noticed it in the toolbar! thank you simple_smile

sandbags08:07:32

cfleming: automatically balancing pasted code would be a nice add

cfleming08:07:57

@sandbags: Yeah, I’m planning to hook into cut & paste to prevent this.

pupeno08:07:18

Being able to type a close parenthesis when it’s balancing parenthesis out could be a solution.

sandbags08:07:23

a cheaper version might be to automatically turn off SE in this case until it’s manually rebalanced (with approrpirate visual indicators)

sandbags08:07:42

then just re-enable once it’s balanced again

sandbags08:07:59

but balance-on-paste would certainly be nicer

cfleming08:07:42

Yeah, I’ve considered temporarily disabling it, I’ll try to get to the real solution but if I don’t that might be a good workaround.

cfleming08:07:32

There are tricky edge cases though, like selecting an unbalanced section of text and deleting it through typing or pasting - I don’t know if I can catch that or not.

cfleming09:07:22

@pupeno: Yeah, it would be nice to implement that, but it’s surprisingly tricky to implement correctly. I suspect it would be more confusing than anything.

pupeno09:07:00

@cfleming: I created a cursive channel here. I really like your product simple_smile

cfleming09:07:20

@pupeno: Thanks! I’m glad you’re enjoying it.

pupeno09:07:47

Is there a way to wrap the selection in #()? Maybe # when something is selected could do it?

cfleming09:07:30

Good idea, there isn’t right now, no. If you select what you want to wrap you can wrap it in parens, but there’s no way to wrap in #() at the moment.

cfleming09:07:02

In general the handling of #() could be better - it’s occasionally annoying with Raise, for example.

cfleming09:07:22

I’m not sure whether #(a b |(c d)) should raise to #(c d) - probably

pupeno09:07:13

I’m just getting started with structural editing. I built a cheatsheet and I’m trying to keep it on as much as possible. http://www.cheatography.com/pupeno/cheat-sheets/cursive-on-mac-os-x/

cfleming09:07:44

Yeah, I saw that, thanks! One thing that would help with that would be to break it into related sections - perhaps Structural Editing, Structural Movement, REPL, Testing etc

pupeno09:07:04

Yes, I’m planning on doing that once the sections become clearer to me.

cfleming09:07:49

One other thing I noticed is that you have Execute Current Statement in there - that’s not one you need there probably, it’s only created as an external action so that people can customise the keypress. See https://cursiveclojure.com/archive/662.html for the motivation.

cfleming09:07:38

The sections probably mostly follow the menu grouping - see Navigate->Structural Movement, Edit->Structural Editing, Tools->REPL etc

pupeno09:07:01

Ok, I’m starting to do it.

pupeno09:07:06

What would be the structural editing way of going from (foo (bar (meh))) to (bar (meh))?

cfleming09:07:20

That’s Raise

cfleming09:07:41

Put the cursor like this: (foo |(bar (meh)))

iae10:07:22

Hello, I was wondering if somebody could help me in my understanding of Clojure concerning lists. See, I have two data types (defrecord Maze [cells]) (defrecord Cell [visited? valid-dirs open-dirs]) And I create the maze like so: (defn create-maze [size] "Create a maze sizeXsize large." (Maze. (let [total-cells (* size size)] (map-indexed (fn [idx _] (create-maze-cell idx size)) (range total-cells))))) Now, before that I had a version that handled a maze with dimensions 1x1 as an edge case, something like this: (defn create-maze [size] (Maze. (if (= size 1) (create-cell) (...))))) This returned a Cell. instead of (Cell.) and my test failed (is (= 1 (count (:cells tiny-maze)))) because it then counted the properties inside the Cell., which is understandable. However, even if I then wrote (count (into [] (:cells (create-maze 1)))) the test would still fail and the resulting array looked like [[:visited? false] [:valid-dirs #{}] [:open-dirs #{}]] It unwrapped my Cell and stuck it all into an array, but I just want to stick the Cell as the only item into a list, which I thought (into []) does. So, um, given a Cell object, how do I place it into a list properly?

annapawlicka10:07:29

@dergutemoritz: I can see your point, and thanks for the explanation simple_smile I don’t really have a use case for making the config a component but it’s interesting to see how other projects are structured

acron10:07:46

@iae please post code on http://refheap.com mate, it's a bit unreadable in slack

agile_geek10:07:31

@iae would be useful to see code for create-cell too

acron10:07:41

@iae: is it just a case of changing ln 12 to: (list (create-cell)) ?

acron10:07:05

@agile_geek: create-cell is there but create-maze-cell is not

acron10:07:42

@agile_geek: i don't think that's relevant to the issue (but agree would be nice to have a complete sample)

iae10:07:21

It gets a bit longer for a full sample, but I'm sure I can provide that.

acron10:07:45

try the change I suggested

agile_geek10:07:51

@acron cool I was still reading code in Slack not refheap! Doh!

acron10:07:54

you're pulling out :cells from maze, but it's counting the Cell map (because that's what :cells is). Just make create-maze always return a list, rather than a single cell or a list

acron10:07:38

Sorry, I should say, the constructor for Maze should always take a list, rather than a single cell or a list

iae10:07:01

@acron I'll try your sample out now but yes, it seems I totally forgot something as simple as the list function.

acron10:07:11

@iae no need to trivialize it, Clojure has a vast number of forms and I forget them all the time simple_smile

agile_geek10:07:47

I have to re-learn them at every Dojo!

acron10:07:03

(And looks like it needs updating to 1.7 as well, ahem)

iae10:07:37

Yup, the list form worked like a charm, thanks!

acron10:07:47

in fact, I've just learnt a new one in @iae 's sample: map-indexed

acron10:07:00

It's a bit like collecting Pokémon

iae10:07:16

Instead of syntax you collect functions and macros 😄

canweriotnow11:07:16

Anyone using compojure-api? I really like it in theory, in practice I’m having trouble organizing my routes and project in a way that seems logical to me based on regular ole compojure sites.

canweriotnow11:07:48

@iae @acron http://conj.io is an even bester friend 😉

juhoteperi11:07:20

@canweriotnow: defroutes* should allow splitting the routes like in regular compojure

iae11:07:29

@canweriotnow: Oooh, I'll give it a look and a bookmark, thanks!

canweriotnow11:07:35

@juhoteperi what I’m not seeing is how I would compose routesets from multiple ns’s like I would otherwise, I think the defapi macro is throwing me.

canweriotnow11:07:55

@iae: it is the Clojure Grimoire, use it with care and love.

juhoteperi11:07:37

@canweriotnow: In defapi you can refer to routes created by defroute* in other namespaces

canweriotnow11:07:17

@juhoteperi and compose them something like,

(defapi app
  (context* “/foo” []
     my-ns/routeset))

canweriotnow11:07:28

Wrong I’m sure, but general idea?

juhoteperi11:07:54

@canweriotnow: That's about right. Though you might need to move the context* to routeset

canweriotnow11:07:30

@juhoteperi: Ahhh, gotcha… I will play and return with questions of a deeper nature. Thank you!

juhoteperi11:07:06

@canweriotnow: I checked and it should work both ways, context* on defapi or defroutes*.

acron12:07:07

@canweriotnow: ultra helpful, thanks

canweriotnow13:07:46

@acron: np, happy to help 😉

acron14:07:41

still no EuroClojure vids 😞

tcrayford14:07:58

they aren't up for a few weeks

tcrayford14:07:04

(at least that's what I was told as a speaker)

tcrayford14:07:24

shameless plug though: my talk is already up (from my own audio/video): http://yellerapp.com/posts/2015-06-29-performance-and-lies.html

Alex Miller (Clojure team)14:07:06

acron: they're being edited, should start showing up in a few days

tcrayford14:07:15

@alexmiller: dang, that's fast simple_smile

acron14:07:32

:thumbsup:

jstaffans17:07:24

When using the Component library, I sometimes find myself introducing bugs in the start/stop handlers, which leaves the system in limbo when trying to do a reset. I end up having to restart the JVM. Any folk wisdom on how to deal with that, other than keeping the handlers as small as possible?

dergutemoritz17:07:09

@ordnungswidrig: In fact, we just don't do that simple_smile We disable components via a config setting which they check during the start phase - if that's what you're aiming at.

dergutemoritz17:07:52

@annapawlicka: You're welcome! Showing how a "real world" application could be structured was indeed one of our main motivations for presenting Pepa.

hlship18:07:22

@jstaffans My big issue with Component was starting up a Jetty instance and then having some later component throw an exception ... now there's nothing that has a reference to the Jetty instance to shut it down, forcing a REPL restart to recover. I partially addressed this by defining new lifecycle protocols that moved the Jetty initialization later, after the end of (component/start-system).

stuartsierra18:07:24

Yes, this is a problem I've encountered as well.

stuartsierra18:07:19

I find it's only a problem when you're writing new components. After a few iterations to work out the bugs in start/stop, everything works smoothly.

stuartsierra18:07:57

So it doesn't bother me much.

stuartsierra18:07:34

It's theoretically possible to recover from a failed start/stop — the ex-info thrown from update-system contains the current state of the system.

stuartsierra18:07:55

But I usually don't bother and just restart Java. simple_smile

jstaffans18:07:15

gotcha. It's annoying, but not a showstopper ..

pupeno18:07:23

How do you coerce a value into true/value depending on its truthiness?

pupeno18:07:00

Like (comp not not)

gtrak18:07:00

@pupeno: I think boolean

gtrak18:07:16

,(boolean 3)

max19:07:20

I vaguely remember a threading macro that would bail out if it hit a nil. Anyone know where it is?

max19:07:30

oooh and it’s in clojure.core

max19:07:32

fantastic

ordnungswidrig20:07:18

(-> 1 ()) expands to (nil 1). Is this a bug?

arohner20:07:23

@ordnungswidrig: I get Can’t call nil, as I would expect

ordnungswidrig20:07:34

yep, I question the expansion.

arrdem20:07:04

why what would you expect... the first of () is nil and -> is defined to provide the previous threaded subexpression as the first argument to the next form.

arrdem20:07:17

argument != call target

arohner20:07:13

@ordnungswidrig: what expansion do you expect?

bostonaholic20:07:26

user=> (macroexpand `(-> 1 ()))
(nil 1)
user=> (macroexpand `(-> 1 (nil)))
(nil 1)

bostonaholic20:07:40

^^ probably the source of confusion

ordnungswidrig20:07:00

bostonaholic: like that, yes.

ordnungswidrig20:07:51

(nil 1) makes no sense except that’s how the macro is implemented.

arohner20:07:07

(first ()) => nil

ordnungswidrig20:07:16

(1) would be as valid. None of both makes sense, thus an error would be the sanest to do, I guess. The actual expression that made me run into this was something like (-> x .getClass()) which is unfortunate.

arohner20:07:49

I think .getClass() is different behavior

arohner20:07:56

because that also involves how forms are read

ordnungswidrig20:07:45

this is also nice: guess what this evaluates to (-> 1 's))

ordnungswidrig20:07:20

ok, that might be an edge case.

trptcolin20:07:31

what it evaluates to or what it expands to? ;) (quote 1 s) -> 1

bostonaholic20:07:47

@ordnungswidrig: what you wanted was (-> x .getClass)

bostonaholic20:07:01

you want to pass to a function, not the invocation of the function

ordnungswidrig20:07:31

bostonaholic: I now. however the error was confusing.

bostonaholic20:07:40

welcome to Java 😉

arrdem21:07:21

Eh... that errors are bad now is no excuse for them to be bad for all time

bostonaholic21:07:40

they're getting better for sure

bostonaholic21:07:42

but when you're dealing with macros and the dynamic nature of clojure on a statically typed jvm, it's going to be tough

ordnungswidrig21:07:30

An easy fix could be that -> refuses empty lists as forms.

bostonaholic21:07:07

I think the current behavior is prefered IMO b/c passing an empty form is an "exceptional case"

bostonaholic21:07:15

therefor an exception should be thrown

ordnungswidrig21:07:19

yes, an „EmptyFormException“ simple_smile

gtrak22:07:05

Does anyone know of a project that generates like pojo builder classes from a data schema? Use case is to have clojure define the API to java code for itself to consume.

gtrak22:07:31

would love to use google autovalue or something familiar to java devs

arohner22:07:49

@gtrak: worst case, you could use the asm library clojure does. There’s probably a nicer option though

arohner22:07:55

@gtrak: are deftypes good enough?

gtrak22:07:27

maybe, but feels like reinventing the wheel

gtrak22:07:11

gonna see how hard it is to hack autovalue simple_smile