Fork me on GitHub
#beginners
<
2018-01-05
>
robert_00:01:21

okay so can I use clojure from ES6?

jcburley00:01:12

@scallions -- so you were able to get Array Manipulation to pass without timeouts, without special tricks? Hm. I might need more of a hint than that...but will think more about it in the meantime.

jcburley00:01:29

...but I just discovered the Discussion tab, so maybe that'll be helpful!

onionpancakes00:01:31

Yea. I don't think I came up the with algorithm myself. I definitely went there first.

onionpancakes00:01:50

Bewarned though, they spoil the solution in that tab.

jcburley00:01:15

Well, yes, they do! I shoulda thought of it, but was taking the Description too literally I guess.

jcburley00:01:19

An earlier problem with timeouts, I "solved" via (apply print ... or some such thing, versus looping. Probably missed an opportunity to think more algorithmically there as well (and I later found at least one place where I had some clunky code that could easily be replace via use of fnil.)

jcburley00:01:25

So this is really good news for me, because I feel I'm weaker algorithmically than I am "programmatically", given my backgound -- and that I haven't really worked on compiler internals in a couple of decades, where thinking algorithmically becomes the norm.

onionpancakes00:01:05

It is a hard problem though, no big deal about not getting it. Usually, these problems have some obscure trick to it which drastically cuts down the time complexity.

jcburley00:01:44

Sure, except I'm supposed to be thinking in terms of O() (time/space/bandwidth/latency) complexity, given my background and where I'd like to go, career-wise. That's why I think it might be "good news" if HackerRank actually challenges me to do more than just express "obvious" algorithms in Clojure.

jcburley00:01:07

FWIW, my transients version is several times faster than my naive version(s) (now that I have a test-case-creator function plus my new handy I/O-redirection macros per the #cider channel).

jcburley00:01:20

Now I'll go on to fix the algo itself. Thanks again for all the help!

jcburley00:01:56

(The transients version still times out on several test cases though -- despite no longer doing so on a few.)

seancorfield01:01:23

@james-clojure Your next step will likely be mutable arrays, possibly mutable arrays of primitives 🙂

jcburley01:01:02

I'll fix the algo 1st tho.

jcburley03:01:54

Hmm, improved algorithm (replacing O(N) behavior with O(1)) passes 7 test cases but still times out on 7.

jcburley03:01:44

@scallions -- sorry to bother you again, but did your solution use any mutable arrays either? As mentioned above, my new implementation (using the delta algo to go to O(1) from O(N)) is lots faster, but still times out on 7/14 test cases, and I'm having trouble identifying any further big-O-level gains. (I even tried replacing the (apply max (reductions + ... at the end with just (apply max ..., to see whether that would still timeout all 7 tests -- and yes, it did, while of course failing the 7 that previously passed. So that extra massaging of the delta vec into an absolute vec, for consumption by max, seems to not be the issue.)

jcburley03:01:24

I did try re-introducing transients (making the vector transient, that is) -- but that made no visible different on my 10Kx10K test case.

onionpancakes03:01:39

Yea I was curious why you where having trouble so I'm trying out the O(n) algorithm.

onionpancakes03:01:11

I'm encountering the same problem as you. Timeouts at tests 7+.

onionpancakes03:01:42

The original solution I used to pass has a complexity of O(m * log(m))

onionpancakes03:01:24

The biggest problem I see in the O(n) algo is allocating that zeroed out vector/array.

jcburley03:01:34

Hmm. Not sure where the log(m) would come from though.

jcburley03:01:15

Oh, you think this let binding is the/a problem? v (vec (map (fn [_] 0) (range n)))

jcburley03:01:46

(It seems to actually be faster than v (vec (replicate 0)), as was suggested on a website I found.)

jcburley03:01:04

(Sorry, v (vec (replicate n 0)).)

jcburley03:01:34

I'll think about how to elegantly avoid allocating the large vector in the first place then.

onionpancakes03:01:10

I've tried (vec (int-array n 0)). and its still too slow.

jcburley03:01:13

(Conceptually it isn't needed.)

jcburley03:01:58

But note that the C solution at the top of Discussion does indeed allocate it.

onionpancakes03:01:29

Well the C solution has the advantage of not repouring a zero array back into a vector.

onionpancakes03:01:42

and n is pretty big.

jcburley03:01:51

I meant C++ solution. (Ditto the Python, Ruby, C, C#, Java, and JavaScript solutions. I haven't finished skimming the thread, but haven't noticed a Fortran solution. ;)

jcburley03:01:28

Anyway, so far, they all seem to start out allocating and zeroing-out a v[n] representing the final result!

onionpancakes03:01:09

Alrighty, I managed to pass the test cases with O(n).

jcburley03:01:23

With Clojure code?! Wow!

onionpancakes03:01:27

but I had to use an array and mutate on it directly.

jcburley03:01:48

Oh, okay. I haven't learned about that yet (I guess it's different from using a transient vector?).

jcburley03:01:04

I'm still not sure how you can arrive at an O(m * log m) solution without allocating a complete vector up front, or essentially risking ending up with one.

onionpancakes03:01:24

Do you need a hint?

jcburley03:01:30

Seems like!!

onionpancakes04:01:04

I used a sorted data structure instead of a vector.

jcburley04:01:48

That's what I thought might be the case, but I guess I'm not sure how to "fold" the results of lines effectively without ending up with a large vector anyway. Gotta think about it more I guess....

jcburley04:01:35

Does it really use less memory and take less time, on large-enough cases, than the straightforward implementation of the O(m) solution everyone seems to have adopted in the Discussion tab?

onionpancakes04:01:07

Well the O(m * log(m)) solution worked first try for me, so I didn't bother with the O(n) until just now.

jcburley04:01:47

Oh, interesting! I would think your first-try solution would have been more complicated...is that the case?

onionpancakes04:01:38

My solution is pretty simple.

jcburley04:01:31

Okay, I'll give that a shot. Maybe tomorrow though, it's late for me. Thanks again for all the help!

jcburley04:01:07

Wow, using a sparse vector (i.e. a map with integer keys) worked! Even though it took a little more time than my previous approach on my test cases, which were "square" (`n = m`). I'll try a very rectangular test case next on my own machine to see the difference more clearly, but I've officially submitted working code now! 🙂

onionpancakes04:01:57

Yep, that's basically the trick.

onionpancakes04:01:01

I used a sorted map. Or you can use a regular map. Either way, you need to sort, so therefore O(m * log(m))

jcburley04:01:02

@scallions-- indeed, huge difference:

app.core> (time (bash/< "test-10M-10000.txt" (runit-v4)))
186149886
"Elapsed time: 2135.874544 msecs"
;; => nil
app.core> (time (bash/< "test-10M-10000.txt" (runit-v5)))
186149886
"Elapsed time: 50.339815 msecs"
;; => nil
app.core>
And, not nearly as complicated as I'd thought. Not doing any transients, mutable arrays, hints, etc.!

jcburley04:01:23

I used a regular map, because I figured there's no need to maintain it in sorted order.

jcburley04:01:39

I'm so proud of myself! With extensive hand-holding, I can do anything!! 😉

onionpancakes04:01:50

I didn't figure out myself either. I guess were comrades in discussion tab peeking.

jcburley04:01:44

Yup. I feel like Joe Pesci's character in "My Cousin Vinny".

jcburley04:01:07

Not that I haven't figured out some pretty interesting optimizations in my past...just, I'm outta practice.

jcburley04:01:07

Strangely, one that I found obvious at my last job involved how bits were numbered. They had various code strewn throughout libraries to handle the fact that much of their code was written in machines where bits in bytes were numbered so 0 was the highest-order bit, 7 the lowest-order -- the opposite of most modern machines.

jcburley04:01:48

So they had various bits of code that pulled apart long bit numbers (those that address more than just one byte, e.g. an array of bits) into "byte" and "bit-within-byte" offsets, then subtracted the latter from 7, then jammed them back together.

jcburley04:01:44

I thought that was hilarious, and the first time I sent out a "fix" of a library for code review, where my code simply did an XOR of the long bit number with 0x7, two of our experts had to work through it carefully to convince themselves I wasn't on drugs or something.

jcburley04:01:40

That's not much of an optimization, but it shows how even some pretty good programmers (one of the reviewers actually contributed to the C standard and helped create UTF-8) couldn't see that solution. Me, I'd learned bit-twiddling at a tender young age, so it was kinda automatic.

jcburley04:01:16

Just gotta do stuff like that regularly for it to become anything near to automatic. Hence my desire to increasingly immerse myself in Clojure and FP.

onionpancakes04:01:16

Well, I found Clojure to be a long, but enjoyable learning curve. Good luck!

Vincent Cantin05:01:40

Question: why can't we have that syntax in a defn? (defn my-fn [a b & rest :as args] ...)

Vincent Cantin05:01:30

is there some way to dispatch to different functions based on the type of the parameters? maybe some macro in the core package?

arrdem05:01:36

multimethods, protocols and interfaces are the primary structures for this.

arrdem05:01:35

multimethods provide open dispatch and allow you to define your own dispatching rules

arrdem05:01:00

interfaces are Java interfaces, but are the fastest when implemented over Java types (records etc.) you control.

arrdem05:01:00

protocols can do interface dispatch on your types, but you can also extend them over other Java types so they're more general at some speed cost.

arrdem05:01:17

But no, Clojure doesn't have ML style pattern matching on function signatures.

Vincent Cantin05:01:43

There must be somewhere some people implementing macros to spare them then manual cond/if dance.

Vincent Cantin05:01:09

@arrdem btw, thanks for the help

arrdem05:01:03

Yeah so multimethods tend to be the usual way to spare yourself the cond dance, but it's got some limitations obviously.

arrdem05:01:38

There is a pattern matcher (clojure.core.match) but it's a fairly uncommon library to see. I like it, together with https://github.com/arrdem/guten-tag (which I wrote, </plug>)

Vincent Cantin07:01:13

is there a simple way to create a vector with different elements at the beginning ?

arrdem07:01:03

#(vector %1 %2 %3 :my-constant-element), alternatively you could use a constant together with update or assoc. Vectors are designed to be efficient when pushing to or popping from the back. There are other datastructures which relax this constraint and are efficient at pushing to either end, but they aren't in core with the exception of the oft-forgotten and not well documented clojure.lang.PersistentQueue.

Vincent Cantin07:01:49

I found (vec (list* 1 2 3 [4 5]))

arrdem07:01:25

Yeah. If this is really what you want, you should probably be using lists / seqs not vectors.

Vincent Cantin07:01:45

hum .. I am not aware of the difference yet.

Vincent Cantin07:01:25

I may not use #(vector %1 %2 %3 :my-constant-element) as the :my-constant-element in a vector which I want to stay flat in the result.

rauh07:01:29

@vincent.cantin You can also just say (into [a b c] [4 5])

Vincent Cantin07:01:24

@rauh indeed, it seems to work.

Vincent Cantin12:01:49

is there a way to destructure an map entry into a couple (key value)?

Vincent Cantin12:01:09

never mind, I found it.

hansw12:01:17

Anyone aware of a way to install leiningen through a wrapper, the way you can with Maven and Gradle?

pablore15:01:51

you could use docker

hansw12:01:14

It's terribly convenient when using CI

Ziyi Yan13:01:47

Hi all! I am a student who is going to apply for GSoC. I have checked the previous idea lists page http://clojure-gsoc.org/project-ideas/. It seems not updated for this year.

joshkh15:01:20

for the sake of argument, how might i go about immediately taking from a channel that i just put to? in clojurescript this never prints, presumably because >! doesn't return a channel?

(go (println (<! (>! (chan) "test"))))

joshkh15:01:42

this works but feels verbose: (go (println (<! (let [c (chan)] (go (>! c "test")) c))))

schmee16:01:22

@joshkh go returns a channel, so you can do (go (println (<! (go "test"))))

joshkh16:01:27

oh right, of course. thanks!

astrashe16:01:08

I feel like this is kind of a dumb question, but what's the difference between figwheel and sidecar?

admay16:01:59

Isn’t sidecar a part of figwheel?

Scot16:01:21

IIRC, figwheel is the leiningen plugin, i.e. what happens when you call lein figwheel, and sidecar is a dependency that allows you to start, stop, and script figwheel from code (as opposed to from project config)

astrashe16:01:11

Thanks, that link explains it

mjo324_5616:01:20

can anybody help me how to fetch from clojurescript in a reagent environment a remote json and display it?

Scot16:01:16

Use cljs ajax to fetch the json and convert to edn. Place the edn in an atom. Use json-html to make a component that reacts to the atom.

mjo324_5616:01:52

@scot-brown i tried something like this, it didn't work, is there anywhere a working example i could look at?

mjo324_5617:01:06

neither of these libs has apropriate examples for my use case

mjo324_5617:01:30

i'll try this one from you above

zsck17:01:28

What's the best environment to be doing clojure development in, coming from a vim background? I'm open to learning emacs, or putting together Atom/VSCode plugins. I recall that Emacs is a favourite of Lisp programmers. Is there anywhere I can learn to set up an effective development environment?

schmee18:01:12

no need to change from vim!

schmee18:01:40

fireplace, vim-parinfer and vim-surround provides a very nice experience, at least IMO

Scot17:01:57

@zack.mullaly either spacemacs or vim with fireplace

mjo324_5617:01:58

it has an excellent vi emulation by default

zsck17:01:19

I've heard good things about spacemacs. I'll have a look.

zsck17:01:37

Thanks for the suggestions

admay17:01:52

@zack.mullaly I use Neovim and tmux for Clojure. If you’re down with a psuedo-repl it’s a great way to go. If you’re interested I can show you some more of my set up

admay17:01:16

I tried moving from Vim to Spacemacs but was struggling because I open and close my editor a ton and Spacemacs is pretty slow spinning up. It’s more of a open once and live there for like 4 days kind of deal. It’s totally a personal thing though!

Scot17:01:48

@admay I don't do this myself, but you could try starting up spacemacs once, and using emacsclient instead of emacs so that every time you open and close emacs you aren't restarting the whole thing

mjo324_5617:01:13

@scot-brown i don;t understand your example

mjo324_5617:01:22

i can display a json in the console

admay17:01:25

@scot-brown Some one told me about that approach too. Another great approach to Clojure development! I heard about it after moving to Neovim though so I wasn’t looking to move back. I like the psuedo-repl approach though. It just goes to show how flexible the Clojure development world is though! So many great ways to write code

mjo324_5617:01:27

(defn make-remote-call [endpoint] (go (let [response (<! (http/get endpoint))] ;;enjoy your data (js/console.log (:body response)))))

mjo324_5617:01:47

i don;t wnat it in the console4

mjo324_5617:01:55

i want it in the htmloutpur

Scot17:01:31

ok, so you need to store it in an atom somewhere

mjo324_5617:01:43

so i need something like "toString" or whatever

mjo324_5617:01:35

json->hiccup

mjo324_5617:01:13

i have (def page (atom #'home-page))

mjo324_5617:01:27

and in (defn home-page [] [:div ....

mjo324_5617:01:32

is my hiccup

mjo324_5617:01:38

so it's an atom

mjo324_5617:01:55

this is supposed to be my only view

mjo324_5617:01:22

where i do one remote call that guives a json back

admay17:01:35

@mjo324_56 Since this seems to be a bit more involved, can you put the project up on GitHub (or something like it) so we can check it out with more context? I think we’ll be able to help out a bit more if we can see some more of the context

Scot17:01:56

I am not entirely familiar with async

Scot17:01:23

but if you are just logging your data, a nil will be returned and it will not be there anymore

mjo324_5617:01:35

how do i display my-element ?

mjo324_5617:01:50

or should i ditch clojure for this?

mjo324_5617:01:01

maybe plain jquery?

mjo324_5617:01:12

because this looks for me way too complicated

Scot17:01:57

Here is a minimal example built on top of the base reagent template

Scot17:01:23

you can replace json->hiccup with whatever rendering of JSON you'd like

Scot17:01:01

if you'd like to use json-html, follow the example on the github page to get styling working

Scot17:01:19

I think the main source of complexity here is the use of async which is a bit excessive for a simple ajax call

mjo324_5617:01:38

this gives me a dev.cljs?rel=1515173992040:10 Uncaught TypeError: Cannot read property 'init_BANG_' of undefined

mjo324_5617:01:41

in the console

mjo324_5617:01:13

i copied your code

Scot17:01:44

replace my init fn with whatever your mechanism of initializing is

Scot17:01:52

do you have a reagent component showing up?

Scot17:01:56

everything below the initialize app line should be in your project already

hansw17:01:34

If i have have two vectors x and y, how do I create a vector z that contains all of the elements from both x and y?

mjo324_5617:01:58

@scot-brown i copied your code, the component does not show up, the html is no generated, i get the default "ClojureScript has not been compiled! please run lein figwheel in order to start the compiler" and beforementioned typeerror in the js console

hansw17:01:59

Can I just say how cool https://github.com/venantius/ultra is? It just told me hint: lists seem to contain the same items, but with different ordering. and was spot on

Scot17:01:38

@mjo324_56 Without seeing your project I can't diagnose exactly what the type error is. It sounds like there may be some configuration issues. I pushed my dummy project if you want to see what it looks like working. Just clone, call lein figwheel from terminal, and go to localhost:3449 https://github.com/SVMBrown/json-test

admay18:01:26

@hans378 There are a ton of great open source tools available to build a Clojure development environment! Ultra has been in my profiles.clj for a good 4 months now and I’m never going back!

seancorfield18:01:32

https://clojure.org/community/resources -- Great list of resources for folks new to Clojure!

seancorfield18:01:10

(since I took that link out of the topic -- I've pinned that message)

Caio Guedes18:01:15

I'm little confused about Clojure/ClojureScript. I've seen a lot of library to do things in Clojure and also in ClojureScript. But I can't imagine when I use clojurescript or clojure...

justinlee18:01:36

@caio.cesar.g.souza clojure targets the jvm and clojurescript targets javascript. If you want to use the language on a browser, you’ll use clojurescript. On the backend, I imagine clojure is more popular.

Caio Guedes18:01:05

but, I can also use cljs in backend, right?

noisesmith18:01:17

sure, but it’s usually a bad idea

noisesmith18:01:59

perhaps you have a definite need to use node, but the performance and resource usage with jvm clojure is much better

Drew Verlee19:01:23

Does anyone know someone willing to give detailed feedback on someones clojure knowledge, maybe by reviewing some code or in another way. This is something I would be willing to pay for.

mjo324_5619:01:12

@drewverlee are you hiring clojure developers?

Drew Verlee19:01:19

No the opposite, I'm trying to get hired as one

donaldball19:01:30

There is a #code-reviews channel here

mjo324_5619:01:40

did you find any job offers already? or any sites that you suggest?

mss19:01:51

is there a method in clojurescript to alias one symbol to another?

Scot20:01:03

@mss what about def?

mss20:01:31

doesn’t seem to working with a macro for whatever reason

Scot20:01:09

@mss Could you elaborate about what you're trying to do?

mss20:01:33

sure, really appreciate the help btw. a macro is defined in one namespace. in another namespace, I want to alias the macro so I can invoke it with a different name. so in ns 1 there’s something like (defmacro my-macro ....) and in ns 2 I’d like to do something like (alias new-name other-ns/my-macro)

admay20:01:22

(def new-name other-ns/my-macro) should work @mss

admay20:01:10

Any reason why you want to do that though?

Scot20:01:14

alternatively, you can use require with :refer :rename (ns my.ns (:require [other.ns :refer [my-macro] :rename {my-macro new-name}])

admay20:01:57

:rename… 3 years… Never had a clue…

admay20:01:14

I should read the ns docs

Scot20:01:09

@admay new-ish to clojurescript, 1.9.183

mss20:01:29

@admay using a library and the way I’m using a macro doens’t quite make sense with how it’s named. would prefer to litter my code with something more readable/understandable

mss20:01:55

@scot-brown basically what I was looking for, appreciate the deep cut!

justinlee20:01:52

not to hijack the thread, but I’ve had a longstanding question, which I think is related to this discussion: the require-macros documentation states There is a nicer alternative if the Clojure macros file has the same name as a ClojureScript file in the same directory, which is a common pattern. In this case, you can just use the :include-macros or :refer-macros flag of the require form. So far I’ve just been cut-n-pasting whatever magic string I need from the readme of the library into my ns expression. Is there a simple way of understanding what this means and when I need to use require-macros vs. refer-macros.

Scot20:01:58

@lee.justin.m afaik *-macros is outdated. cljs now magically handles that for you in a regular require and you can pretend they're functions

justinlee20:01:07

@scot-brown so I should be able to just make the obvious transformation of (:require-macros [cljs.core.async.macros :refer [go]]) to (:require [cljs.core.async.macros :refer-macros [go]?

Scot20:01:51

(:require [cljs.core.async.macros :refer [go]])

justinlee20:01:24

oh I can just use :refer everywhere now?

mjo324_5620:01:06

what is the preffered way on using bootstrap with reagent? is all of bootstrap functionality supported?

mjo324_5620:01:40

i've seen 2 libs that weren't updated since 5 years

mjo324_5620:01:29

so i havent fuigured out the generic way

mjo324_5620:01:58

or should i simply use hiccup to generate the html and everything else will be done automatically?

mjo324_5620:01:26

use the bootstrap tags

justinlee20:01:35

@mjo324_56 I’ve never actually done it, but from what I remember, most of bootstrap is pure css, so all you need to do is pull it in and produce the right elements with the right classes. There is a bit of javascript to enable some features, like dropdowns and modals, if I recall, and so you might have to do a bit more to interact with those elements.

admay20:01:55

@mjo324_56 Here’s a reagent cookbook recipe that uses bootstrap to create a modal https://github.com/reagent-project/reagent-cookbook/tree/master/recipes/bootstrap-modal

admay20:01:06

The index.html page imports the boostrap js and css allowing you to use the classes and whatnot in the Cljs.

mjo324_5620:01:47

my leiningen template didn't generate an index.html, only a css, that confused me

mjo324_5620:01:28

this date picker example is from 2015, this together with the missing index.html made me confused

mjo324_5620:01:39

i thought that the initial html body was generated with clojurescript

noisesmith21:01:09

right - something needs to be sent by the back end

noisesmith21:01:20

but it could be generated in code instead of being a file in your project

mjo324_5621:01:40

(defn loading-page [] (html5 (head) [:body {:class "body-container"} mount-target (include-js "/js/app.js")]))

mjo324_5621:01:50

this was the way it was generated

noisesmith21:01:06

that’s server side code, right?

mjo324_5621:01:39

i could translate the html that includes bootstrap into hiccup

gadfly36121:01:51

@mjo324_56 another alternative is using react bootstrap components... You could do that with https://github.com/gadfly361/baking-soda

mjo324_5621:01:02

but the solution with index.html seamed more elegant

gadfly36121:01:44

@mjo324_56 the server side code you posted and the index.html should functionally be equivalent, so i do think translating the html to hiccup is the way to go if you wanted to use that recipe

mjo324_5621:01:00

this is additional work(instead of copy&pasting), that's why i don't like this

noisesmith21:01:48

the enlive library can take html and output hiccup that would render to that html, btw

noisesmith21:01:28

you could do it once to generate the form to paste into your code, or use enlive inside loading-page to generate the initial page structure

mjo324_5621:01:37

if i'd like to use some bootstrap templates from the net, more complicated ones, then translating each little bit into hiccup is not so good

noisesmith21:01:00

alternatively you can add a script tag that loads js/app.js into the bootstrap file

noisesmith21:01:25

or use eg. selmer to take something that is mostly an existing html file and inject computed contents into it

mjo324_5621:01:34

i' try this:

mjo324_5621:01:35

(defn head [] [:head [:meta {:charset "utf-8"}] [:meta {:name "viewport" :content "width=device-width, initial-scale=1"}] (include-css (if (env :dev) "/css/site.css" "/css/site.min.css" "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" ))]) (defn loading-page [] (html5 (head) [:body {:class "body-container"} mount-target (include-js "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" "/js/app.js")]))

mjo324_5621:01:55

to interpret this

mjo324_5621:01:55

@gadfly361 or can i do like (:require [baking-soda.bootstrap3 :as b3] and all necessary bootstrapstuff will be included and i can use bootstrap tags with [b3/some-bootstrap-tag {...}] ?

gadfly36121:01:57

Yeah, that should work .. baking soda wont bring in the css for you tho, so you'll need to add that

mjo324_5623:01:27

is it advised (and possible) to use reagent without hiccup?

mjo324_5623:01:03

i'd have a couple of html snippets instead

mjo324_5623:01:40

and have some clojure code substitute elements by ID

mjo324_5623:01:24

it sucks, I am fiddleling around getting a form done with a couple of input fields

mjo324_5623:01:40

does anybody else had similar bad experience as i did with reagent+bootstrap?

madstap00:01:37

About bootstrap, I found that I much prefer using https://bulma.io/ instead. It has only css, leaving the javascript up to the user.

madstap01:01:13

To answer the question, yes I did indeed have a bad experience with the reagent/bootstrap combination...

dadair23:01:28

Can anyone identify what is wrong with my macro? I keep getting "Unmatched delimiter: )":

(defmacro defnode [spec & key-overrides]
  `(s/def ~spec
     (s/merge :core/node
              (s/keys :req-un [~@key-overrides]))))

dadair23:01:57

ex: (defnode :node.named/user-session :node.user-session/name)

genmeblog23:01:19

Macroexpansion works

genmeblog23:01:32

(s/def
  :node.named/user-session
  (s/merge :core/node (s/keys :req-un [:node.user-session/name])))