Fork me on GitHub

Hi everyone ! I am new to clojure. Have read clojure for brave and true. Want to do a web based project in clojure. Any suggestions ??


@sobiaadil you may want to check "Web development with clojure 2nd ed." book - it uses Luminus which is a pretty decent web app template combining multiple useful libraries.


Hi !! Thanks I will look into it.


Hi, I'm looking for something like NCurses for a Clojure console application. I basically want to use raw keypresses in the console. Any suggestions on how to get them or what library to use? The only thing I've found is JCurses, but not sure how to use that from Clojure. Thanks!


@U5JPZFFR6 another alternative would be to write in cljs and use a nodejs ncurses lib. example: obviously this option is very dependent on your other requirements and how comfortable you are with cljs


@U06CM8C3V thanks, that looks exactly like what I need


I'd thought about cljs just because I'm more familiar with JS than Java, but don't care either way


@sobiaadil not got any web based projects but you might want to check out the 4clojure website if you havent before There are about 150 problems there where you need to write a simple function to pass the given questions. Great for learning and great fun too


@daedelus1982 I'm already doing the 4clojure problems. Thanks!!!


I ran into something I cant explain. A function I wrote ran without throwing an exception whereas there was a mistake in it and there should have been an Arity exception. The question was about finding anagrams on the 4clojure site: And here was my solution: (fn [c] (let [anagram? #(and (= (count %1) (count %2)) (empty? (clojure.set/difference (set %1) (set %2)))) anagrams #(set (conj (filter (partial anagram? %2) %1)))] (set (remove #(= 1 (count %)) (distinct (map (partial anagrams c) c)))))) In my local REPL there was no exception but in a separate REPL the expected exception was thrown because there is a missing argument to conj function in the anagrams binding. Presumably my local REPL was using an older working 'let anagrams' binding and not the new broken one. Are let bindings memoized or something?


I've sometimes found that my local REPL and the 4clojure one slightly differed. Maybe Clojure versions.


I don't recall what problem it was, but a few times I had to use slightly different stlib functions to make something work


thanks, I just tried the same broken function in a rebooted REPL with different arguments and it worked fine. no expected exception


@daedelus1982 I think older versions of Clojure throw an arity exception if you call conj with only a single arg, but I just looked up the source for conj in Clojure 1.8.0, and it now accepts zero or more args.


Also, if you go to the main 4clojure page, there’s a link to the github repo. I did a quick clone and checked the project.clj, and 4clojure is still on clojure 1.4.0, so that’s probably why your code throws an exception on 4clojure but not in your local REPL.


thanks for the help. yes, the clojure version does seem to be the cause here. FYI im using 1.8.0


Hi, how can I set use-context-classloader to false? I have a problem that classes from my clojure lib (compiled with gen-class) and added to war are not observable. I have to do ugly thing like ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();


so the questions: can I change the default clojure classloader and where should I do it?


(set! *use-context-classloader* false)


@sundarj thx, i'll try


I’ve been trying to use maps in my programs vs creating new types but i’m wondering what the best way to achieve polymorphism is? When everything is a map I can’t dispatch on type, so protocols aren’t that useful. I’m struggling to see how multimethods can be used, and right now my best solution is to add a :type to my data and dispatch on that. I’m wondering if this is a good pattern to adopt.


that's what Records are for


If you need polymorphism then it’s legit to start defining Records. If you’re new to functional programming, though, it’s possible you’re reaching for polymorphism prematurely, if you’re used to doing things the OOP way. It might be worth describing the bigger picture of what you’re trying to do that you want polymorphism for.


I’m not assuming that you’re necessarily doing it wrong, but just thought I’d mention the possibility, since this is the beginners channel.


@sundarj I was considering using Records kind of the same as defining my own type in this case. Trying to see if I can just use plain maps.


yeah, but if you need polymorphism - then plain maps don't cut it


using Records is a better approach than defining your own ad-hoc :type keys


although what @U06CM8C3V said is very good


@U06CM8C3V I’m just thinking about how to design my app where I might have different data, like users, movies, movie clips etc, and I want to do similar operations on them without necessarily needing to know the shape of the data (keys)


that might be an un-Clojure way of thinking about it though


i wouldn't say so, but i am new to this too 😛


@sundarj yeah, using :type didn’t feel right, so at least I know that much now 😄


@sundarj I was saying that “do similar operations without know the keys” might be un-Clojure


ah, right. possibly


though maybe that's just to simplify the example


yeah, good example, I’ve seen others, and I’d assume that sort of pattern is what hierarchies are meant for:


Often though what you would normally use polymorphism for can be divined from the data itself, and multimethods work great for that


For example you could assume that a map with :width and :height calculates its area via width * height. While a map with :radius would calculate it differently.


@U07TDTQNL that seems more in the spirit of keeping it all data


What’s nice about functional programming is that you often don’t need polymorphism, because all you’re interested in is one or two keys in the map. Movies, actors, directors, and studios might all have a :name key, and you might have a function that, I dunno, translates names into pig-latin. All the function needs to do is grab the :name, transform it, and return the result. It doesn’t care if it’s a movie name or an actor name or whatever.


There are perfectly legit uses for Records and polymorphism in Clojure, but there’s also a lot of cases where it’s not needed, and we just reach for it out of habit. Or at least I did when I was first learning.


i guess the solution is to force yourself to use maps, and then if/when that breaks down you can look at Records and whatnot


pretty much, maps are almost always the right option, sometimes records are faster, that sometimes is a lot less often than people would assume


awesome, thanks 🙂


Hi! I have a question about performing IO. Would you mind if I link a stackoverflow?


@fominok agents are best for the case where you need to accumulate results from these asynchronous operations, but they should happen one at a time


if you want to run them in parallel, and still merge results, I’d use futures that call swap! on an atom only after they get their result (so that only the data modification is retried, and not the http request)


a single agent will only run one action at a time


and using a single agent for a request that doesn’t rely on the data in other requests doesn’t really make much sense


for more complex interactions I’d look into core.async (putting IO into core.async/thread invocations, and reading the result from the channel returned) or possibly a mix of futures for IO and refs for state coordination - really depends on what kind of coordination needs you have


Are all the Lisps basically transposable


So, you won't make a choice learning the "wrong" Lisp?


Yes and no. I’m not having a problem reading On Lisp and the little schemer while studying clojure.


Yes and no. I’m not having a problem reading On Lisp and the little schemer while studying clojure.


Is there a canonical book for the Clojure community?


Is it the Brave and True book?


some people like that one, but there’s also Joy of Clojure and Clojure Programming and Clojure Applied - depends on your tolerance for silliness


because Brave and True is definitely silly


i'm part-way into the brave and true book and enjoying it, but got a little stuck on one of the exercises and haven't gotten back to it for a while. hopefully i'll find some time in the near future to go back to it and get some help from here


I would like to run this (merge-with union {1 [1]} {1 [3]}) code and I have ({1 [1]} {1 [3]}) format. How can I change in easy way to use with merge-with union? flatten not works.. any idea? maybe I’m tired 🙂


@sb I’d expect (merge-with into ...) to work


@noisesmith thanks I try it now!


but I have an extra ( ) around of this.. that is my problem


@sb clojure.set has many functions that quietly accept things that are not sets but also don’t quite do the right thing (though I’m not sure union is one of them, I think into has the correct collection-independent behavior)


ohh thanks!! 💪👍