:bootclasspath causes java.lang.NullPointerException
Hello, I'm trying to compile my project with :bootclasspath set to true, so as to have the jar for a java agent added to my classpath, but in one of my projects it's generating java.lang.NullPointerException on this line: (def app (middleware/wrap-base #'app-base)) which is preceded by: (defroutes base-routes (route/resources "/") (route/not-found "Not Found")) (def app-base (routes (var service-routes) (wrap-routes #'home-routes middleware/wrap-csrf) #'base-routes)) The full backtrace is: java.lang.NullPointerException, compiling:(handler.clj:86:10) at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:3628) at clojure.lang.Compiler$DefExpr.eval(Compiler.java:439) at clojure.lang.Compiler.compile1(Compiler.java:7323) at clojure.lang.Compiler.compile(Compiler.java:7390) at clojure.lang.RT.compile(RT.java:399) at clojure.lang.RT.load(RT.java:444) at clojure.lang.RT.load(RT.java:412) at clojure.core$load$fn__5448.invoke(core.clj:5866) at clojure.core$load.doInvoke(core.clj:5865) at clojure.lang.RestFn.invoke(RestFn.java:408) at clojure.core$load_one.invoke(core.clj:5671) at clojure.core$load_lib$fn__5397.invoke(core.clj:5711) at clojure.core$load_lib.doInvoke(core.clj:5710) at clojure.lang.RestFn.applyTo(RestFn.java:142) at clojure.core$apply.invoke(core.clj:632) at clojure.core$load_libs.doInvoke(core.clj:5749) at clojure.lang.RestFn.applyTo(RestFn.java:137) at clojure.core$apply.invoke(core.clj:632) at clojure.core$require.doInvoke(core.clj:5832) at clojure.lang.RestFn.invoke(RestFn.java:482) at projectx.core$loading__5340__auto21.invoke(core.clj:3) at clojure.lang.AFn.applyToHelper(AFn.java:152) at clojure.lang.AFn.applyTo(AFn.java:144) at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:3623) at clojure.lang.Compiler.compile1(Compiler.java:7323) at clojure.lang.Compiler.compile1(Compiler.java:7313) at clojure.lang.Compiler.compile(Compiler.java:7390) at clojure.lang.RT.compile(RT.java:399) at clojure.lang.RT.load(RT.java:444) at clojure.lang.RT.load(RT.java:412) at clojure.core$load$fn__5448.invoke(core.clj:5866) at clojure.core$load.doInvoke(core.clj:5865) at clojure.lang.RestFn.invoke(RestFn.java:408) at clojure.core$load_one.invoke(core.clj:5671) at clojure.core$compile$fn__5453.invoke(core.clj:5877) at clojure.core$compile.invoke(core.clj:5876) at user$eval9$fn__16.invoke(form-init8240839476947253640.clj:1) at user$eval9.invoke(form-init8240839476947253640.clj:1) at clojure.lang.Compiler.eval(Compiler.java:6782) at clojure.lang.Compiler.eval(Compiler.java:6772) at clojure.lang.Compiler.load(Compiler.java:7227) at clojure.lang.Compiler.loadFile(Compiler.java:7165) at clojure.main$load_script.invoke(main.clj:275) at clojure.main$init_opt.invoke(main.clj:280) at clojure.main$initialize.invoke(main.clj:308) at clojure.main$null_opt.invoke(main.clj:343) at clojure.main$main.doInvoke(main.clj:421) at clojure.lang.RestFn.invoke(RestFn.java:421) at clojure.lang.Var.invoke(Var.java:383) at clojure.lang.AFn.applyToHelper(AFn.java:156) at clojure.lang.Var.applyTo(Var.java:700) at clojure.main.main(main.java:37) Caused by: java.lang.NullPointerException at org.webjars.WebJarAssetLocator.listParentURLsWithResource(WebJarAssetLocator.java:66) at org.webjars.WebJarAssetLocator.getAssetPaths(WebJarAssetLocator.java:84) at org.webjars.WebJarAssetLocator.getFullPathIndex(WebJarAssetLocator.java:121) at org.webjars.WebJarAssetLocator.(WebJarAssetLocator.java:152) at ring.middleware.webjars$wrap_webjars.invoke(webjars.clj:27) at ring.middleware.webjars$wrap_webjars.invoke(webjars.clj:25) at projectx.middleware$wrap_base.invoke(middleware.clj:90) at clojure.lang.AFn.applyToHelper(AFn.java:154) at clojure.lang.AFn.applyTo(AFn.java:144) at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:3623) ... 51 more Exception in thread "main" java.lang.NullPointerException, compiling:(handler.clj:86:10) at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:3628) at clojure.lang.Compiler$DefExpr.eval(Compiler.java:439) at clojure.lang.Compiler.compile1(Compiler.java:7323) at clojure.lang.Compiler.compile(Compiler.java:7390) at clojure.lang.RT.compile(RT.java:399) at clojure.lang.RT.load(RT.java:444) at clojure.lang.RT.load(RT.java:412) at clojure.core$load$fn__5448.invoke(core.clj:5866) at clojure.core$load.doInvoke(core.clj:5865) at clojure.lang.RestFn.invoke(RestFn.java:408) at clojure.core$load_one.invoke(core.clj:5671) at clojure.core$load_lib$fn__5397.invoke(core.clj:5711) at clojure.core$load_lib.doInvoke(core.clj:5710) at clojure.lang.RestFn.applyTo(RestFn.java:142) at clojure.core$apply.invoke(core.clj:632) at clojure.core$load_libs.doInvoke(core.clj:5749) at clojure.lang.RestFn.applyTo(RestFn.java:137) at clojure.core$apply.invoke(core.clj:632) at clojure.core$require.doInvoke(core.clj:5832) at clojure.lang.RestFn.invoke(RestFn.java:482) at projectx.core$loading__5340__auto21.invoke(core.clj:3) at clojure.lang.AFn.applyToHelper(AFn.java:152) at
Re: Using a dynamic var for my database connection for implicit connections+transactions
On 5 August 2015 at 19:33, James Reeves ja...@booleanknot.com wrote: So when you're testing, presumably you use a dynamic binding to override the global connection to the test database? The wrap transaction always overrides the dynamic binding, whether it's in tests or not. -- J. Pablo Fernández pup...@pupeno.com (http://pupeno.com) -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Using a dynamic var for my database connection for implicit connections+transactions
On 3 August 2015 at 23:47, Rob Lally rob.la...@gmail.com wrote: I’m also a little confused by your suggestion that it would be impossible to enclose each test in a transaction. The article you point to shows one way. It shows how to pass data to the test by using a dynamic var, which is what we are using to track the connection, which is what I'm interested in passing in to the test. If my solution to use a dynamic var to track the connection is dirty and unacceptable, so is that one. The only difference I can think of is, using a dynamic var only for tests dirties only tests but using a dynamic var to track connections is consistent across the code-base. -- J. Pablo Fernández pup...@pupeno.com (http://pupeno.com) -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Using a dynamic var for my database connection for implicit connections+transactions
Other than the fact that this approach doesn't reach the level of functional purity that some people want, after playing with it for a while, we found it very productive and leads to clean/readable code and tests, so we decided to turn it into a library: https://clojars.org/conman https://github.com/luminus-framework/conman You are still in control of the connection so you can do other things with it and have more than one if necessary. On 31 July 2015 at 01:44, J. Pablo Fernández pup...@pupeno.com wrote: Hello Clojurians, I found passing around the database connection to each function that uses it very error prone when you are using transactions as passing the wrong one could mean a query runs outside the transaction when in the source code it is inside the with-db-transaction function. So I ended up defining the db namespace like this: (ns db) (defonce ^:dynamic conn (atom nil)) (defn connect! (reset conn (generate-new-connection))) (defn run-query [query] (run-query query @conn) [query conn] (run-the-query-in-connection query conn)) This is pseudo-code of course, simplified to highlight the part that I'm most unfamiliar with: (defonce ^:dynamic conn (atom nil)) The reason why it's an atom is so that connect! can *set* it and the reason why it's a dynamic var is so I can do this: (jdbc/with-db-transaction [db-connection-with-transaction @db/conn] (binding [db/conn (atom db-connection-with-transaction)] (db/run-query SELECT *)) and the query will be implicitly run inside the transaction. Does it make sense? Is this wrong? will it fail in unexpected ways? Is there a better way? Thanks. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to a topic in the Google Groups Clojure group. To unsubscribe from this topic, visit https://groups.google.com/d/topic/clojure/fRi554wbPSk/unsubscribe. To unsubscribe from this group and all its topics, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout. -- J. Pablo Fernández pup...@pupeno.com (http://pupeno.com) -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Using a dynamic var for my database connection for implicit connections+transactions
Rob, The transactions are not global, the transactions are local. Connections are global and there's no way around it with the constraints of a traditional RDBMs. Your idea of making the global connection unavailable for code that's in the context of a transaction would prevent the errors I'm trying to prevent but you would still required to pass the connection around, which in a webapp, means that the whole chain of function calls, pretty much everything, would have a database connection. That is ugly in some cases, impossible in others. A piece of code that would be impossible is to enclose each test in a transaction using clojure.test: http://stackoverflow.com/questions/31735423/how-to-pass-a-value-from-a-fixture-to-a-test-with-clojure-test Furthermore, I don't think this solution gains you any purity, you still have a global estate and you are hiding it away when starting a transaction. My proposal was to make it work instead of hiding it. They are rather equivalent from the complexity point of view. On 1 August 2015 at 18:29, Rob Lally rob.la...@gmail.com wrote: Hey Pablo, I could be wrong, but it seems that the key problem here is the existence of the global transaction. If the global transaction didn’t exist then any time you failed to pass in a transaction the code would fail: immediately and loudly. I appreciate what you’re trying to do but it seems like you’re on a path to solve the problems caused by one shared, implicit, global variable by creating more shared, implicit, slightly less global, variables and that doesn’t seem like it is going to end well. Implicit connections in a binding will fail in, perhaps mysterious ways if you ever include any sort of concurrency: even things as simple as asynchronous logging can start logging wrong values or missing values. Can you somehow render the global connection inoperable in some way? Perhaps redefine it, point it at a data source that doesn’t exist or… by some other hook-or-crook have it fail in a loud, grotesque manner if it is touched? R. On 31 Jul 2015, at 01:54, J. Pablo Fernández pup...@pupeno.com wrote: Hello James, Thanks for your answer. I do understand your point. Pure functions are easier to reason about and my use of dynamic here breaks that purity. I'm not doing it lightly. It already happened to me, that one of those functions that was running inside the transaction, was not passed the transaction connection and instead got the global one and the failure was silent and very hard to debug, and this was with a project that has less than 200 lines of code. I'm trying to find patterns that will work when this project has 200k lines of code. For me, the thing is, I have a traditional relational database here, this is already far from pure. For example, calling (db/create-user pup...@pupeno.com) twice will not only not return the same thing the second time, it'll actually raise an exception the second time. Also, the database connection is *global state* unless each function creates its own connection, which would be terrible. So, this global state also breaks functional purity. The problem with the second aspect of breaking purity as far as I can see is this: at some point, this global state has to be picked up and used, so at some point a function will *not* get a database connection passed to it but *will* access the database by using this global connection. I haven't advanced this project enough to say this with 100% certainty, but, I think there's going to be more than one function like that and at some point I'll need to have one inside the other so I need them to be composable. Let me show you a naive example: db/create-user is the low level database function that creates a record in the user table user/create is the function used to create a user, it takes care of, for example, encrypting the password. account/register is the function to register a new user, it takes care of creating a user but also validation, sending a welcome email and so on. So each function calls the predecessor there and would pass the database connection, account/register, being the entry point, would grab it from the global state so it doesn't get a connection passed to it. So far, a lot of it looks like pure functions (let's ignore the fact that a database breaks that purity). The problem arises when I get another function, account/invite, that is used to register a bunch of people one after the other, so that account/invite would call account/register many times. The problem is that account/invite *can't* start a transaction and have account/register and all its inner functions use that transaction when that makes a lot of sense. To make account/register composable it needs to accept an optional database connection and use that one if it's present, or the global one if it's not. Every time a function does that there's a high risk of picking the wrong database and account
Re: Using a dynamic var for my database connection for implicit connections+transactions
James, I'm not new to functional programming and I understand the principles and why they are good. I worked in Haskell, Erlang and other Lisps before. Even if only a tiny portion of my codebase deals with the database, I still need a pattern for that part of the codebase. It is very easy to say this is dirty, you should not do this without offering an alternative solution and by alternative solution I mean one that applies to the pattern of making web applications that are database heavy. Think of your traditional CRUD application, you can say quarentine the code that deals with the database and yes, you can do that, but it still is 90% of the code. On 3 August 2015 at 06:00, James Gatannah james.gatan...@gmail.com wrote: On Thursday, July 30, 2015 at 7:44:31 PM UTC-5, J. Pablo Fernández wrote: Hello Clojurians, I found passing around the database connection to each function that uses it very error prone when you are using transactions as passing the wrong one could mean a query runs outside the transaction when in the source code it is inside the with-db-transaction function. I'll go ahead and make the point that it's error-prone for different reasons. Pretty much by definition, that database connection is a system boundary. It's all about something that's *way* more complex than random global state changes inside your program. This is a thing that interacts with the outside world, with all the nastiness that implies. Everything that everyone else has already written about this approach is true, but I don't think they've gone far enough. Even if you pass that database connection around as a parameter everywhere, you're talking about throwing away a huge part of the benefit of using a functional language. Isolate your side-effects. Think of a castle. You have a moat surrounding it, and a few gates that you use to allow your peasants to enter/exit. This particular gate opens up to a swamp full of alligators. Your approach amounts to letting the gators wander around loose. Passing the connection around to each function in the call chain is like tying a ribbon around the gator's neck and hoping you can use that as a leash. You can use either approach to great effect. If you're really, really good. And so is everyone else on your team (you did mention a 200 KLOC project). One of the main benefits to functional programming is that admitting you aren't really, really good is incredibly liberating. I don't have the time/energy to dedicate to trying to maintain this sort of code. (Yes, I spent lots of time recently thinking about how java was designed for very average programmers, but it really takes much better programmers than a functional language to actually write correct programs). Even if I were that good...I'd rather be focused on the problems that make my customers happy. I'm going to appeal to authority here for the right answer: http://prog21.dadgum.com/23.html (in my defense, it's a great blog). Have your web response handler (which is another system boundary...this one is next to an active volcano populated by fire-breathing dragons) build up a list of all the nasty side-effects that will eventually have to happen. Don't just isolate your side-effects. Quarantine those suckers as if each and every one means you're dealing with the most diabolical hacker you can imagine. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to a topic in the Google Groups Clojure group. To unsubscribe from this topic, visit https://groups.google.com/d/topic/clojure/fRi554wbPSk/unsubscribe. To unsubscribe from this group and all its topics, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout. -- J. Pablo Fernández pup...@pupeno.com (http://pupeno.com) -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Using a dynamic var for my database connection for implicit connections+transactions
On Friday, 31 July 2015 11:48:54 UTC+1, Colin Yates wrote: I am away from the code at the moment, but is there any reason why the dynamic connection can’t be private? This goes some way to providing safety. No, I don't think there's a problem with it being private, I just didn't think of it and my code to handle transactions is in a different namespace, but it should go in the db namespace anyway and then it can easily made private. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Using a dynamic var for my database connection for implicit connections+transactions
Hello James, Thanks for your answer. I do understand your point. Pure functions are easier to reason about and my use of dynamic here breaks that purity. I'm not doing it lightly. It already happened to me, that one of those functions that was running inside the transaction, was not passed the transaction connection and instead got the global one and the failure was silent and very hard to debug, and this was with a project that has less than 200 lines of code. I'm trying to find patterns that will work when this project has 200k lines of code. For me, the thing is, I have a traditional relational database here, this is already far from pure. For example, calling (db/create-user pup...@pupeno.com) twice will not only not return the same thing the second time, it'll actually raise an exception the second time. Also, the database connection is *global state* unless each function creates its own connection, which would be terrible. So, this global state also breaks functional purity. The problem with the second aspect of breaking purity as far as I can see is this: at some point, this global state has to be picked up and used, so at some point a function will *not* get a database connection passed to it but *will* access the database by using this global connection. I haven't advanced this project enough to say this with 100% certainty, but, I think there's going to be more than one function like that and at some point I'll need to have one inside the other so I need them to be composable. Let me show you a naive example: db/create-user is the low level database function that creates a record in the user table user/create is the function used to create a user, it takes care of, for example, encrypting the password. account/register is the function to register a new user, it takes care of creating a user but also validation, sending a welcome email and so on. So each function calls the predecessor there and would pass the database connection, account/register, being the entry point, would grab it from the global state so it doesn't get a connection passed to it. So far, a lot of it looks like pure functions (let's ignore the fact that a database breaks that purity). The problem arises when I get another function, account/invite, that is used to register a bunch of people one after the other, so that account/invite would call account/register many times. The problem is that account/invite *can't* start a transaction and have account/register and all its inner functions use that transaction when that makes a lot of sense. To make account/register composable it needs to accept an optional database connection and use that one if it's present, or the global one if it's not. Every time a function does that there's a high risk of picking the wrong database and account/invite and account/register shouldn't be dealing with database connection management. That feels to me like lower level details leaked into higher level abstractions. Now, I know this is a naive example and you could push the grabbing of the global connection higher and higher, as long as the example is naive and simple like this, but it does represent what in my experience is the reality of web application development at least in another languages and I haven't seen anything to make me think Clojure will be radically different here (at least when using a patterns such as compojure). So yes, it's not purely function but with a database that's already impossible and if I wanted purely functional I would probably be using Haskell instead of Clojure. What I like about Clojure is this: Clojure is a practical language that recognizes the occasional need to maintain a persistent reference to a changing value and provides 4 distinct mechanisms for doing so in a controlled manner - Vars, Refs, Agents and Atoms. I'm just trying to be practical here. But I'm new and I'm not sure if an atom that is a dynamic var has some hidden issues that I'm not seeing (other than the fact of it being state that changes and that I have to manage explicitly because the language is not protecting me from shooting myself in the foot with it). Does it make sense? On 31 July 2015 at 03:16, James Reeves ja...@booleanknot.com wrote: On 31 July 2015 at 01:44, J. Pablo Fernández pup...@pupeno.com wrote: I found passing around the database connection to each function that uses it very error prone when you are using transactions as passing the wrong one could mean a query runs outside the transaction when in the source code it is inside the with-db-transaction function. So I ended up defining the db namespace like this: (ns db) (defonce ^:dynamic conn (atom nil)) (defn connect! (reset conn (generate-new-connection))) (defn run-query [query] (run-query query @conn) [query conn] (run-the-query-in-connection query conn)) This style of code is generally considered to be unidiomatic in Clojure. The reason for this is that it significantly
Using a dynamic var for my database connection for implicit connections+transactions
Hello Clojurians, I found passing around the database connection to each function that uses it very error prone when you are using transactions as passing the wrong one could mean a query runs outside the transaction when in the source code it is inside the with-db-transaction function. So I ended up defining the db namespace like this: (ns db) (defonce ^:dynamic conn (atom nil)) (defn connect! (reset conn (generate-new-connection))) (defn run-query [query] (run-query query @conn) [query conn] (run-the-query-in-connection query conn)) This is pseudo-code of course, simplified to highlight the part that I'm most unfamiliar with: (defonce ^:dynamic conn (atom nil)) The reason why it's an atom is so that connect! can *set* it and the reason why it's a dynamic var is so I can do this: (jdbc/with-db-transaction [db-connection-with-transaction @db/conn] (binding [db/conn (atom db-connection-with-transaction)] (db/run-query SELECT *)) and the query will be implicitly run inside the transaction. Does it make sense? Is this wrong? will it fail in unexpected ways? Is there a better way? Thanks. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: (flatten non-sequential) has a surprising result
Yes, reading the source code and trying to understand why rest was being called there is how I came up with this case. On 2 July 2015 at 07:54, icamts ica...@gmail.com wrote: Hi Pablo, I think you're right. Have a look at flatten source (defn flatten Takes any nested combination of sequential things (lists, vectors, etc.) and returns their contents as a single, flat sequence. (flatten nil) returns an empty sequence. {:added 1.2 :static true} [x] (filter (complement sequential?) (rest (tree-seq sequential? seq x it is the rest function that causes this behavior and it seems to be just an optimization to avoid filtering the first element of tree-seq that is known to be the whole sequence. A simpler definition of flatten seems to have the behavior you expected. (defn flatten1 [x] (filter (complement sequential?) (tree-seq sequential? seq x))) Il giorno mercoledì 1 luglio 2015 13:55:28 UTC+2, J. Pablo Fernández ha scritto: Hello Clojurists, Today I was surprised by the result of (flatten 1) which is '(). I was expecting '(1) or an error. Talking in some other people in #clojure @ clojurians.net, not everybody agrees that '(1) is a good result but that '() is somewhat surprising. Would it be better if it raised an error when the attribute is not sequential? -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to a topic in the Google Groups Clojure group. To unsubscribe from this topic, visit https://groups.google.com/d/topic/clojure/L6yf6iFPqe8/unsubscribe. To unsubscribe from this group and all its topics, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout. -- J. Pablo Fernández pup...@pupeno.com (http://pupeno.com) -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
(flatten non-sequential) has a surprising result
Hello Clojurists, Today I was surprised by the result of (flatten 1) which is '(). I was expecting '(1) or an error. Talking in some other people in #clojure @ clojurians.net, not everybody agrees that '(1) is a good result but that '() is somewhat surprising. Would it be better if it raised an error when the attribute is not sequential? -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: (flatten non-sequential) has a surprising result
I agree with you Mikera, it also maintains the homogeneity of always returning a sequence but some people disagreed with it, so an error might be better. -- J. Pablo Fernández pup...@pupeno.com http://pupeno.com On Jul 1, 2015 4:22 PM, Mikera mike.r.anderson...@gmail.com wrote: On Wednesday, 1 July 2015 12:55:28 UTC+1, J. Pablo Fernández wrote: Hello Clojurists, Today I was surprised by the result of (flatten 1) which is '(). I was expecting '(1) or an error. Talking in some other people in #clojure @ clojurians.net, not everybody agrees that '(1) is a good result but that '() is somewhat surprising. Would it be better if it raised an error when the attribute is not sequential? From an array programming / core.matrix perspective '(1) would be the most logical result. Consider the logical sequence: [[[1]]] = 3 dimensional array with elements '(1) [[1]] = 2 dimensional array with elements '(1) [1] =1 dimensional array with elements '(1) 1 = 0 dimensional array (or scalar) with elements '(1) I am not saying that this is necessarily the best behaviour to follow for flatten, but it is an analogy worth considering. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to a topic in the Google Groups Clojure group. To unsubscribe from this topic, visit https://groups.google.com/d/topic/clojure/L6yf6iFPqe8/unsubscribe. To unsubscribe from this group and all its topics, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: More functional Quil
Hello Nikita, I think Quil should definitely provide a way to write functional style processing code. At the moment, my knowledge of both Clojure and Processing is not enough to evaluate these solutions. I'm certainly going to write my code following some of this and if someone proposes a solution to be part of Quil 2, I would happily adopt it and report back on my experiences. BTW, I noticed you had some discussions on IRC, you can find me there as Pupeno. On Monday, March 10, 2014 12:29:00 AM UTC, Nikita Beloglazov wrote: Hi Pablo You can find similar old thread on Quil github repo: https://github.com/quil/quil/pull/19 It may serve as good background what other people considered to make Quil more functional-style. I like your suggestion though I would split your :draw function to 2 fns: an :update function, which only purpose is to update state and :drawwhich draws state and doesn't change the world at all. If this approach is implemented - other handler functions like :mouse-move, :key-pressed are also need to become update-like functions - they should take state as argument and return new state. The only problem is that it is not backward compatible at all. But probably we still can do it... We can add option :fun-mode? true (stands for functional-mode) which enables all these changes - :draw takes state as argument, new :update function is added for modifying state, all handlers behave like :update. This option is enabled per-sketch. It requires additional work on Quil internals, but I think it is doable. This option can be implemented in coming quil 2.0 and it would be great feature to have. One more thing we could do to make it more functional-like - pass changed values to handlers directly. Currently when :key-pressedhandler is called - no argument is passed to the function and you need to use (key-code) or (raw-key) functions to identify which key was pressed. I think this parameters should be explicitly passed to the function. What do you think? Nikita On Sunday, March 9, 2014 1:21:58 PM UTC, J. Pablo Fernández wrote: On Sunday, March 9, 2014 1:02:52 PM UTC, Laurent PETIT wrote: Hello, To be honest I don't see any fundamental difference between your first attempt and the improvement: both share the fact that the mutation of the state happens within the draw function. So in both cases, you have a temporal coupling between updating the state of the app and rendering a new view of the app's state. Yes, what's happening in both cases is very similar, but the function draw in the functional style, in my opinion, is easier to read and maybe it's also easier to test. I would suggest that you don't swap! at all within draw, just deref and render the result of the dereffing. And, in another thread, at potentially a totally different pace than the redrawing's pace, update the application's state accordingly to business rules / constraints. Schematically, something like this: (def app-state (atom (init-state))) (defn draw [...] (let [app-snapshot (deref app-state)] ... call quil primitives to render the application state snapshot ...)) (future ... logic which updates the app-state atom depending on business rules / constraints, in a separate thread ...) I never worked with future, this is exciting, but I have some questions. Do you mean that future is completely separate from draw? I'm just getting started, but draw is not only a function to draw, but as a side effect is the clock of the app, as it's called according to the set frames per second and you normally *take a step* en each draw. Would draw create these futures for the next draw? -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
More functional Quil
Hello Clojurians, I'm starting to play with Processing and I want to use my favorite programming language for it, so I started using Quilhttps://github.com/quil/quil. The problem is that Processing has a imperative architecture and makes my Clojure code look bad. For those that don't know Processing/Quil, here's a little overview that's relevant to this email. Processing is a language and a library that makes it easy to draw on the screen to do generative art, simulations, etc. Processing programs have two methods, a setup method that is run once, at the beginning, and then a draw method that is run over and over. Literally something like: Walker w; void setup() { w = new Walker(); } void draw() { w.render(); w.walk(); } I'm using a hypothetical walker, an entity that walks around the screen. More or less taken from here: http://natureofcode.com/book/introduction/ My understanding is that the equivalent Clojure code using Quil would look like this: (defn setup [] (set-state! :walker (atom (create-walker (defn draw [] (render-walker @(state :walker)) (swap! (state :walker) walk)) Quil stores a map in the meta-data of the Processing applet and let's you access it. Since I need the state to change, I'm storing the walker in an atom. I found examples out there following more or less this structure. I'm not happy with this structure, it doesn't feel functional enough. When thinking about this, I got reminded of Erlang processes, specially with OTP, where you have a function that's called over and over to which the state is passed and which returns the next state. Following that structure I would like to implement it like this: (defn setup [] [(create-walker)]) (defn draw [walker] (render-walker walker) [(walk walker)]) The result of calling setup is a vector containing the attributes to draw, and the result of draw is a vector containing the attributes that will be used in the next call to draw. Does this make sense? Does it look cleaner to you guys? I achieved that by writing this wrappers for setup and draw: (defn setup-wrapper [] (set-state! :state (atom (setup (defn draw-wrapper [] (swap! (state :state) (fn [s] (apply draw s My concern with this is that now the whole state is in one single atom that I'm replacing on each frame and that might not be good. Is it copying the whole state or can Clojure use its copy-on-demand feature even for atoms? Is there a better way of doing this? Thanks. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: More functional Quil
On Sunday, March 9, 2014 1:02:52 PM UTC, Laurent PETIT wrote: Hello, To be honest I don't see any fundamental difference between your first attempt and the improvement: both share the fact that the mutation of the state happens within the draw function. So in both cases, you have a temporal coupling between updating the state of the app and rendering a new view of the app's state. Yes, what's happening in both cases is very similar, but the function draw in the functional style, in my opinion, is easier to read and maybe it's also easier to test. I would suggest that you don't swap! at all within draw, just deref and render the result of the dereffing. And, in another thread, at potentially a totally different pace than the redrawing's pace, update the application's state accordingly to business rules / constraints. Schematically, something like this: (def app-state (atom (init-state))) (defn draw [...] (let [app-snapshot (deref app-state)] ... call quil primitives to render the application state snapshot ...)) (future ... logic which updates the app-state atom depending on business rules / constraints, in a separate thread ...) I never worked with future, this is exciting, but I have some questions. Do you mean that future is completely separate from draw? I'm just getting started, but draw is not only a function to draw, but as a side effect is the clock of the app, as it's called according to the set frames per second and you normally *take a step* en each draw. Would draw create these futures for the next draw? -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Is The Joy if Clojure up to date?
Hello, I have a copy of The Joy of Clojure that I bought a couple of years ago. Is it still a good way to learn Clojure or is it out of date? Thanks. -- -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.
New Clojure Brush for Alex Gorbatchev's SyntaxHighlighter
Hello, I took Travis Whitton's brush for Clojure[1] for Alex Gorbatchev's SyntaxHighlighter[2] and put it in a git repo in GitHub, with an index file to easy development and trying it out. I also fixed some bugs and did some improvements. The new code is here: https://github.com/pupeno/clojure_brush Cheers! [1] http://travis-whitton.blogspot.com/2009/06/syntaxhighlighter-for-clojure.html?showComment=1317124626851#c3205000945287389700 [2] http://alexgorbatchev.com/SyntaxHighlighter/ -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: REPL and Leiningen checkouts
Thanks for the reply Chas. Does that mean that I have to create a Java project inside IntelliJ, instead of just opening the directory containing a Clojure/Lein project? -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Errors in Clojure
Hello Clojurians, I'm struggling to work with errors in Clojure. This is one example, one case, but I had many like these before: user= (load-file /Users/pupeno/Projects/mgr/src/lobos/migrations.clj) org.postgresql.util.PSQLException: FATAL: role lobos does not exist (config.clj:1) It just gives one line, no stack trace. config.clj looks like this: (ns lobos.config) (def db {:classname org.postgresql.Driver :subprotocol postgresql :subname //localhost:5432/mgr :user mgr :password chi1lie7Wai3ioP6aing3ooci}) What now? how do I start to unravel this? How would you do it? Thanks. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Errors in Clojure
Petr, I do not care about this particular error, but about how to deal with this one liners. Ambrose's reply is what I needed, and no, it's not PostgreSQL problem. It's a library trying to establish a connection when it shouldn't with credentials that should never be used because I never specified them anywhere, so, I kinda need the stack trace to track down the problem. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
REPL and Leiningen checkouts
Hello, I want to play around with a library I'm using so I started using the Leiningen checkouts feature and if I do lein repl it works. But when I'm running the REPL inside my editor I'm not running it through lein. Any ideas how to get my REPL to pick up checkouts like when I run it with lein? Thanks. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: REPL and Leiningen checkouts
I'm currently using La Clojure. Not sure if I can directly hook it to lein. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Uploaded Clinorm, an ORM-like system for Clojure
CLinorm Is Not an ORM. Basically because it is not object oriented. It's in its very very early stages of development. It's basically useless and I'm developed on a need-to-function basis for another project I'm doing which is not public yet. The reason to upload it is so that other people can take a look and give me the feedback about the design and my code (I'm not an expert Lisper) and in case anybody else needs such a system, collaboration is welcome. Clinorm comes with various parts. The two *external* ones are com.kvardekdu.clinorm and com.kvardekdu.clinorm.sql. Let's start with the first as it is the most important one. This package allows you to define models like this: (clinorm/defmodel :users [[:username :string] [:age :integer] [:email :string]]) that generates a structure called users with three fields, username, age and email and generates, for now, two functions (many, many more in the future), create-table-users and drop-table-users. These functions have very self-explanatory names. The table has all the fields defined there. The plan is to also contain an auto-increment id, but it'll be stored as meta-data in the structure objects. Many other functions will be generated in the function, such as (get-users ...), (delete-users ...), etc. I still don't know how relationships are going to be managed, but I have an idea in my mind. The second most important package, over which the previous one is built, is com.kvardekdu.clinorm.sql which allows you to connect using JDBC and a nice syntax like this: (clinorm.sql/connect { :type :derby :file-name /tmp/blah.db :create true})) Note: only derby supported at the moment, and not very extensively. That returns the connection, but also the sql package manages connections, maybe in a non-lispy way. There's a global default connection (many, many programs only talk to one and only one database) and also a map of named connections (some programs talk to a fixed set of databases, like two, very distinctive, like one is derby, the other is mysql, or one is production, the other is qa). But if that's not good enough for you, just take the connection returned by connect and manage it anyway you want. All SQL functions and methods should take an optional connection parameter. And it also allows you to run queries like this: (clinorm.sql/create-table :users [[:id :integer :auto-increment] [:username :string] [:age :intere]])) and it should also allow to run things like (clinorm.sql/select [:table1 :table2] [:where (= (user_id table1) (id table2))]) or similar; but only creating and dropping table is supported for now. This is heavily inspired in CL-SQL. It should be a portable SQL-like language that gets converted into various different SQLs in the back. So far only Derby is supported and no preparations for others have been made, the design is in-flux at the moment! Hey, this was only the work of my little free time in a week. Yes, feel free to consider this whole thing vapor-ware, you'd probably be right. Or you can help me build it ;) Note that I didn't say released, I only uploaded it to: http://github.com/pupeno/clinorm Enjoy! -- J. Pablo Fernández [EMAIL PROTECTED] http://pupeno.com signature.asc Description: This is a digitally signed message part
Compojure and Clojure 1094+
Hello, I've just forked Compojure and made it work with Clojure 1094+, the change is here: http://github.com/pupeno/compojure/commit/3cac756c89f63bbe009dcb6abbeb4646c252dee4 I haven't updated the clojure.jar and clojure-contrib.jar because I don't believe Compojure should distribute those or any other jars at all, so I'm moving my fork into the direction where it would be only a library. Nevertheless, that patch can be pulled in to have Clojure 1094+ in any repo. Enjoy! --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Concerned about Clojure's license choice.
One thing that might be doable and acceptable is dual licensing. If Clojure is realsed as CPL *and* GPL, it can be combined with GPL programs and it is not in any way more free than the CPL (say, like if you add BSD in the bag). In that way you can keep GPLists happy and still use CPL. On Nov 1, 6:33 pm, [EMAIL PROTECTED] [EMAIL PROTECTED] wrote: Hello. I am an open source programmer and fan of Clojure! I wanted to express my concern about your wonderful language project in the hopes it may help it succeed even more. Are you really sure you want/need to use the Common Public License for your language? The biggest problem I see with this license is that it is not compatible with the GPL. This means a lot to many people and I would hate to see you have to wasted time with discussing license issues when a new license would avoid all these problems. You may find this article informative http://www.dwheeler.com/essays/gpl-compatible.html Chris --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Concerned about Clojure's license choice.
Hello, On Nov 3, 7:54 pm, [EMAIL PROTECTED] [EMAIL PROTECTED] wrote: On Nov 3, 5:35 am, J. Pablo Fernández [EMAIL PROTECTED] wrote: One thing that might be doable and acceptable is dual licensing. If Clojure is realsed as CPL *and* GPL, it can be combined with GPL programs and it is not in any way more free than the CPL (say, like if you add BSD in the bag). In that way you can keep GPLists happy and still use CPL. It doesn't even have to be dual-licensed with the GPL. It just has to be dual licensed with a GPL *compatible* license. True, it can be LGPL, BSD, etc. I proposed GPL because is the one that leaves less freedom, thus changing as little as possible the current situation. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: offtopic - where are you come from? (poll)
I think it might be more important where people are, where they live, than where they come from. I live in Zürich, Switzerland. On Oct 17, 11:27 am, Rastislav Kassak [EMAIL PROTECTED] wrote: Hello Clojurians, I think after 1st year of Clojure life it's good to check how far has Clojure spread all over the world. So wherever are you come from, be proud and say it. I'm from Slovakia. :) RK --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---