Re: [ClojureScript] Re: [ANN] Silk, an isomorphic routing library for Clojure and ClojureScript
On Saturday, April 11, 2015 at 8:40:07 AM UTC-7, kovas boguta wrote: On Sat, Apr 11, 2015 at 10:46 AM, Malcolm Sparks mal...@juxt.pro So, in summary, I think it would be useful to have a single 'default' routing library in Clojure that supported isomorphism and was built on protocols, as a minimum. Now that Clojure is attracting so many new users, it would be great to discuss the outstanding differences between all the routing libraries and try to drive some consensus as to what a combined library would include. I'm on board with most of this post (and the Bidi approach in particular), I'm not sure consensus is necessary but I'll throw in my 2 cents. - Please, no more defroute etc macros - Routing should be composable. I want to take some routes and just plug them in at some level of my existing hierarchy. - Middleware should be decoupled from the routes as much as possible. The process for associating middleware to the request should be parallel/complementary to resolving the resource. Maybe middleware is not the best concept to begin with. I'm definitely in agreement that the approach Bidi and Silk have taken is much better than what exists on master in Secretary. Most of the undesirable aspects pointed out about Secretary have largely been resolved on the 2.0.0 branch for Secretary. The other desirable qualities found in Silk (unsure about Bidi) have been in existence in Secretary for sometime but the library was not oriented properly to make those features idiomatic. I do not agree that defroute etc macros should be eliminated from the picture. There is nothing inherently wrong with authoring and/or encouraging their use. It is only an issue when those macros are the only way to use a library effectively. People enjoy using DSL's (until they hit a wall with them) and for small to medium scale projects they are completely appropriate and just as effective as the it's just data style of routing for getting shit done. I will also say the same about middleware. Although I do not like the middleware pattern I do not believe it is worth throwing out the window just because it is not the best concept. It is a familiar pattern and sometimes that familiarity is worth avoiding the friction of learning a something else for some individuals and teams. tl;dr retaining features that people enjoy using and are familiar with is fine so long as there is a composable API underneath it that can be used alternatively. -- 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: [ClojureScript] Re: [ANN] Silk, an isomorphic routing library for Clojure and ClojureScript
Author of bidi here. In his blog article, REST Litmus Test for Web Frameworks - https://www.innoq.com/blog/st/2010/07/rest-litmus-test-for-web-frameworks/ - Stefan Tilkov asks of REST libraries: Is there an easy way to produce links that point back resources identified by whatever means the framework exposes (such as some form of routing)? The idea of bidi came out of a discussion I had with Philipp Meier about Liberator's support for hyperlinks, to meet Stefan's litmus test. Philipp argued that while he felt Liberator should remain independent of the URI routing layer, any routing layer that was part of a proper REST API should make it easy, and reliable, to produce hyperlinks. Now that REST APIs are a mission-critical part of many websites, I believe that producing reliable working hyperlinks is too important to be left to *ad-hoc* string concatenation, however disciplined. If the community are to standardise on a routing library, I feel it should be one that support isomorphism (as Pedestal, bidi and Silk do) The design of bidi was heavily influenced by my experiences with Pedestal routing, which demonstrated the value of a data structure over macros. Unfortunately, I felt that Pedestal's integration of routing with its interceptor definitions meant that you couldn't extract an independent routing library from it. I also didn't really like the terse versus expanded format, and wanted bidi to have a single format, one that would strike the balance between being easy to write by hand and easy to generate. I'm still a fan of Pedestal but wish it had been offered from the beginning as a set of independent libraries which worked well together. 'All or nothing' is never a great choice. Silk was heavily influenced by bidi, as Dom has described earlier in this thread, and if you compare their source code they are very similar. Now that bidi supports ClojureScript, the key difference is in syntax and the fact that bidi routing is hierarchical, whereas Silk allows you to dispatch at a number of levels, as far as I can tell. The syntax differences are such that you could probably create some records and record constructors, satisfying the bidi protocols, that allowed you to layer Silk's syntax over bidi, a sort of 'silk-flavored-bidi' if you will. The hierarchical design of bidi was driven by the desire to support modularity- when you have multiple people or teams working on different parts of a website, it helps to be able to 'remount' one of the parts without anything breaking. Also, bidi excludes support for dispatching on differences in query parameters, as I believe that query parameters shouldn't, by definition, determine which resource is identified by the URI. Opinionated? Maybe! Until recently, the way that you did isomorphism in bidi was to use a handler as an argument to path-for, which would return the route. That required URI-forming code (like views) to have access to all the handlers in the system - not great. I played around with using keywords, with some funky record injection in the route structure to convert them to handlers during dispatch, but then I looked at Secretary's 'named routes' and slapped myself very hard on the forehead (doh!). Since then, bidi has a 'tag' function that you use to tag a handler with a keyword, from then on you can use that keyword when forming routes instead of the handler itself. bidi will undergo some rework when the new reader conditionals of Clojure 1.7 arrive out of beta, which I expect will replace its use of cljx. Otherwise, bidi itself is going to remain fairly stable. It is relied on by many production websites, such as https://www.onthemarket.com/, so can't change radically. However, building on protocols opens up numerous ways of extending bidi. For example, we're working on a new REST library (http://yada.juxt.pro) which combines bidi routing structures with resource maps to generate published Swagger definitions. This is achieved by adding a couple of new small records which satisfy bidi's protocols, demonstrating the endless flexibility of Clojure's protocols feature. So I'd hope that a 'standard' routing library would be built on protocols too. So, in summary, I think it would be useful to have a single 'default' routing library in Clojure that supported isomorphism and was built on protocols, as a minimum. Now that Clojure is attracting so many new users, it would be great to discuss the outstanding differences between all the routing libraries and try to drive some consensus as to what a combined library would include. On Saturday, April 11, 2015 at 1:08:30 AM UTC+1, Daniel Jomphe wrote: This thread over Silk, Bidi and Secretary has been very interesting. I looked at the three projects to see how they evolved after this thread started. Any cross-pollination or progress worth sharing now that I've missed? From what I could gather: * Secretary is evolving
Re: [ClojureScript] Re: [ANN] Silk, an isomorphic routing library for Clojure and ClojureScript
On Sat, Apr 11, 2015 at 10:46 AM, Malcolm Sparks malc...@juxt.pro So, in summary, I think it would be useful to have a single 'default' routing library in Clojure that supported isomorphism and was built on protocols, as a minimum. Now that Clojure is attracting so many new users, it would be great to discuss the outstanding differences between all the routing libraries and try to drive some consensus as to what a combined library would include. I'm on board with most of this post (and the Bidi approach in particular), I'm not sure consensus is necessary but I'll throw in my 2 cents. - Please, no more defroute etc macros - Routing should be composable. I want to take some routes and just plug them in at some level of my existing hierarchy. - Middleware should be decoupled from the routes as much as possible. The process for associating middleware to the request should be parallel/complementary to resolving the resource. Maybe middleware is not the best concept to begin with. -- 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: [ClojureScript] Re: [ANN] Silk, an isomorphic routing library for Clojure and ClojureScript
This thread over Silk, Bidi and Secretary has been very interesting. I looked at the three projects to see how they evolved after this thread started. Any cross-pollination or progress worth sharing now that I've missed? From what I could gather: * Secretary is evolving towards a conservative 2.0 and won't, after all, be re-implemented on top of Silk. This may be a good thing: not bringing more transitive dependencies in all projects using Secretary. Thus, Secretary would remain the first stop for Compojure-like easy routing in ClojureScript apps. * Bidi was already quite mature and comparable to Silk and remains as attractive as it was, especially with regard to its established production usage and corporate backing. * Silk's development slowed for some time and this may make for a good occasion to reflect on its state and the value of its ambitions (which seemed quite interesting to me). * I would add, from distant memory, that Pedestal's isomorphic routing is planned to be extracted into a self-contained library. Judging from the advent of Clojure 1.7's reader conditionals and Om's model 2 for which I'm expecting an announcement in a few weeks, I suppose Cognitect may start providing again their leadership on the front-end. Either they start recommending something like Bidi or Silk, or they (more probably) reader-cond-port their routing lib to ClojureScript. I'm watching this space and thanks for any comments. On Sunday, October 12, 2014 at 11:28:13 PM UTC-4, Dom Kiva-Meyer wrote: Thanks for the experience reports, Dylan! Colin, Silk is Ring-compatible and meant to be used as a single replacement for both Compojure and Secretary (or any other server/browser routing combination with incompatible syntax and semantics). But, as Dylan said, it's totally fine to use it in conjunction with Compojure instead of replacement. Silk should also work fine with all Ring middleware. In the next version, Silk will have a more familiar and mostly Compojure-compatible syntax for defining routes. My hope is that this will make it easier to translate Compojure examples/code to Silk. -- 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: [ClojureScript] Re: [ANN] Silk, an isomorphic routing library for Clojure and ClojureScript
Thanks both. On 13 October 2014 04:27, Dom Kiva-Meyer li...@domkm.com wrote: Thanks for the experience reports, Dylan! Colin, Silk is Ring-compatible and meant to be used as a single replacement for both Compojure and Secretary (or any other server/browser routing combination with incompatible syntax and semantics). But, as Dylan said, it's totally fine to use it in conjunction with Compojure instead of replacement. Silk should also work fine with all Ring middleware. In the next version, Silk will have a more familiar and mostly Compojure-compatible syntax for defining routes. My hope is that this will make it easier to translate Compojure examples/code to Silk. On Fri, Oct 10, 2014 at 9:25 AM, Dylan Butman dbut...@gmail.com wrote: I’ve been using silk in conduction with compojure. Most middleware aren’t compojure specific, but I’ve just found it easier to stick with base level compojure routes and then pass uris to silk for pattern matching. This is mostly because there is such a wealth of documentation and examples to draw from with compojure. For example, session management, login flows with friends, etc have already been solved and there is plenty of code to strip. Silk wouldn’t complicated them (in some cases it might simplify), but when the wheel rolls, push it. I’ve been approaching silk solely as a library for pattern matching within the specific domain of urls, which it does very cleanly. More importantly, it’s currently the only one that does it in both clojure and clojurescript, which makes it possible to have the same routing code used on client and server, which is necessary if you want to do server rendering, or more complicated websocket updates. -- Note that posts from new members are moderated - please be patient with your first post. --- You received this message because you are subscribed to the Google Groups ClojureScript group. To unsubscribe from this group and stop receiving emails from it, send an email to clojurescript+unsubscr...@googlegroups.com. To post to this group, send email to clojurescr...@googlegroups.com. Visit this group at http://groups.google.com/group/clojurescript. -- 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/D95anPmhNhU/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: [ClojureScript] Re: [ANN] Silk, an isomorphic routing library for Clojure and ClojureScript
Thanks for the experience reports, Dylan! Colin, Silk is Ring-compatible and meant to be used as a single replacement for both Compojure and Secretary (or any other server/browser routing combination with incompatible syntax and semantics). But, as Dylan said, it's totally fine to use it in conjunction with Compojure instead of replacement. Silk should also work fine with all Ring middleware. In the next version, Silk will have a more familiar and mostly Compojure-compatible syntax for defining routes. My hope is that this will make it easier to translate Compojure examples/code to Silk. On Fri, Oct 10, 2014 at 9:25 AM, Dylan Butman dbut...@gmail.com wrote: I’ve been using silk in conduction with compojure. Most middleware aren’t compojure specific, but I’ve just found it easier to stick with base level compojure routes and then pass uris to silk for pattern matching. This is mostly because there is such a wealth of documentation and examples to draw from with compojure. For example, session management, login flows with friends, etc have already been solved and there is plenty of code to strip. Silk wouldn’t complicated them (in some cases it might simplify), but when the wheel rolls, push it. I’ve been approaching silk solely as a library for pattern matching within the specific domain of urls, which it does very cleanly. More importantly, it’s currently the only one that does it in both clojure and clojurescript, which makes it possible to have the same routing code used on client and server, which is necessary if you want to do server rendering, or more complicated websocket updates. -- Note that posts from new members are moderated - please be patient with your first post. --- You received this message because you are subscribed to the Google Groups ClojureScript group. To unsubscribe from this group and stop receiving emails from it, send an email to clojurescript+unsubscr...@googlegroups.com. To post to this group, send email to clojurescr...@googlegroups.com. Visit this group at http://groups.google.com/group/clojurescript. -- 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: [ClojureScript] Re: [ANN] Silk, an isomorphic routing library for Clojure and ClojureScript
Thanks for putting that together, Dylan. Looking forward to seeing what you're building. :) Olli, please feel free to reach out to me (email, Twitter, GitHub issue, whatever) if you have any questions. Thanks for trying it out! On Tue, Oct 7, 2014 at 12:05 PM, Dylan Butman dbut...@gmail.com wrote: Sorry i don't have time to really explain any of this... but here's some code I pulled out of a recent project. maybe it'll be helpful to you. unfortunately I can't share the whole project. https://gist.github.com/pleasetrythisathome/7adbdc9c8b7ab689df45 -- Note that posts from new members are moderated - please be patient with your first post. --- You received this message because you are subscribed to the Google Groups ClojureScript group. To unsubscribe from this group and stop receiving emails from it, send an email to clojurescript+unsubscr...@googlegroups.com. To post to this group, send email to clojurescr...@googlegroups.com. Visit this group at http://groups.google.com/group/clojurescript. -- 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: [ClojureScript] Re: [ANN] Silk, an isomorphic routing library for Clojure and ClojureScript
Good stuff, Marc! Thanks for the feedback. That behavior in `composite` is a bug. Thanks for reporting. Sorting the query map seems reasonable. Good suggestion! Thanks again, Marc. On Sat, Aug 9, 2014 at 8:05 PM, marc marc.bosc...@gmail.com wrote: I've been playing and like Silk a lot! However the following I find curious as I'm wondering what the intended behaviour should be: user= (silk/match (silk/composite [user- (silk/integer :id) -fred ( silk/option :this that) s]) user-42-fredjs) {:id 42, :this j} user= (silk/match (silk/composite [user- (silk/integer :id) -fred ( silk/option :this that) s]) user-42-freds) nil I would have thought the last one would have produced: user= (silk/match (silk/composite [user- (silk/integer :id) -fred ( silk/option :this that) s]) user-42-freds) {:id 42, :this that} My only other suggestion, not worthy of a pull request, is the following: (defn domkm.silk/encode-query Takes a query map. Returns a string of query pairs encoded and joined. [query] (- query (apply into sorted-map) ; ensure consistent ordering to improve cache-ability of URLs... (map (fn [[k v]] (str (encode k) = (encode v (str/join ))) Regards, Marc On Sunday, 10 August 2014 05:00:50 UTC+10, DomKM wrote: Hi Allen, Thanks for the feedback! 1) This, and precompiling regexes where possible, is my intention with Silk. 2) I'm not convinced that requiring fully-qualified routes would be a feature. Let's say we have route A which should match /foo/bar and route B which should match /foo/*. If these routes are unordered, route B would have to additionally be constrained with `(not= * bar)`. It seems like this could make route definition very painful when working in a large application with many routes that match on multiple parts of the URL. On Sat, Aug 9, 2014 at 10:06 AM, Allen Rohner aro...@gmail.com wrote: I'd like to thank everyone in the community for both Silk, and Secretary. I'll throw out some (uninvited) feature requests I'd love to see in a future route-matching library. 1) Make trie-based route dispatching possible. A feature pedestal has/will soon have, is to compile the routing table into trie, rather than the compojure-style wrapped functions. This can have a nice speedup on busy applications. I'm not asking anyone to write this code, just consider the design such that it's possible to add this behavior in the future. 2) I'll claim that making route definition order is a misfeature. Routes should always be fully qualified, such that re-arranging them doesn't affect routing behavior (and therefore, the route table should be an unordered collection, like a map or set, not a vector). One nice readability reason for this is that if your route order does matter, than at least one route definition is lying about which routes it actually dispatches on. Just things to consider :-) Thanks, Allen On Thursday, August 7, 2014 9:31:56 PM UTC-5, DomKM wrote: Thanks for your feedback, Dylan! If you define routes with :path and :query, will the route match/unmatch with undefined query keys? If so, how are they handled? If not, I'd suggest making query matching optional, where nils are substituted. I'm not entirely sure what you mean, but I'll give it a shot. Please provide some example code if I answered the wrong question. `nil` is a pattern that matches anything. If your URL pattern query is `nil` then the URL query will not be checked. A map is a pattern that matches its values against the values of another map. Therefore, `nil` and `{}` are equivalent when used as a query pattern. You can make a query value pattern optional by wrapped it with `silk/option`. It's a little unclear how your matching functions relate to route. It looks like Silk always breaks at / in path and matches, is that correct? Yes. There is a URL type in Silk and matching is done against instances of it. The path is represented as a vector of segments. The readme is currently very deficient and I apologize for that. There are some really good things in secretary. What do you think about them? Splat, regex, format matchers. In terms of regex matching, Silk used to have a built-in regex pattern but I removed it when I made a big architectural change. I forget why I removed it, but I'll re-add it since it does seem like a very common requirement. Currently, part of Secretary's splat exists as a built-in Silk pattern. For example, `(silk/composite [foo :* bar])` would match fooanythingbar and return `{:* anything}`. The `:*` isn't special; it's just a keyword. Format is just a specific case of composite: `(silk/composite [:* . :format])`. Unlike Secretary, Silk does not have a built-in special syntax for string patterns. This is because special syntax strings are not composable and, since Silk matches against unencoded strings, who am I to say you can't have : or * in your URL paths? ;)
Re: [ClojureScript] Re: [ANN] Silk, an isomorphic routing library for Clojure and ClojureScript
I'd like to thank everyone in the community for both Silk, and Secretary. I'll throw out some (uninvited) feature requests I'd love to see in a future route-matching library. 1) Make trie-based route dispatching possible. A feature pedestal has/will soon have, is to compile the routing table into trie, rather than the compojure-style wrapped functions. This can have a nice speedup on busy applications. I'm not asking anyone to write this code, just consider the design such that it's possible to add this behavior in the future. 2) I'll claim that making route definition order is a misfeature. Routes should always be fully qualified, such that re-arranging them doesn't affect routing behavior (and therefore, the route table should be an unordered collection, like a map or set, not a vector). One nice readability reason for this is that if your route order does matter, than at least one route definition is lying about which routes it actually dispatches on. Just things to consider :-) Thanks, Allen On Thursday, August 7, 2014 9:31:56 PM UTC-5, DomKM wrote: Thanks for your feedback, Dylan! If you define routes with :path and :query, will the route match/unmatch with undefined query keys? If so, how are they handled? If not, I'd suggest making query matching optional, where nils are substituted. I'm not entirely sure what you mean, but I'll give it a shot. Please provide some example code if I answered the wrong question. `nil` is a pattern that matches anything. If your URL pattern query is `nil` then the URL query will not be checked. A map is a pattern that matches its values against the values of another map. Therefore, `nil` and `{}` are equivalent when used as a query pattern. You can make a query value pattern optional by wrapped it with `silk/option`. It's a little unclear how your matching functions relate to route. It looks like Silk always breaks at / in path and matches, is that correct? Yes. There is a URL type in Silk and matching is done against instances of it. The path is represented as a vector of segments. The readme is currently very deficient and I apologize for that. There are some really good things in secretary. What do you think about them? Splat, regex, format matchers. In terms of regex matching, Silk used to have a built-in regex pattern but I removed it when I made a big architectural change. I forget why I removed it, but I'll re-add it since it does seem like a very common requirement. Currently, part of Secretary's splat exists as a built-in Silk pattern. For example, `(silk/composite [foo :* bar])` would match fooanythingbar and return `{:* anything}`. The `:*` isn't special; it's just a keyword. Format is just a specific case of composite: `(silk/composite [:* . :format])`. Unlike Secretary, Silk does not have a built-in special syntax for string patterns. This is because special syntax strings are not composable and, since Silk matches against unencoded strings, who am I to say you can't have : or * in your URL paths? ;) Looking at the Secretary readme, there appear to be two ways to use splat that Silk currently does not have built-in support for. In Secretary, /foo/* would match /foo/bar/baz and return `{:* bar/baz}`. Also, /*/* would match /a/b and return `{:* [a b]}`. I keep saying built-in because, while multi-segment path patterns and binding the same parameter key to multiple path segments does not currently exist in Silk, it is very easy to extend Silk with that functionality. You could easily create a pattern that did exactly what Secretary and Clout do by default and use it to match a path instead of a vector. However, I do question the utility of these two features. Are either of these common requirements and, if so, could I see some examples of why they are necessary or helpful? This isn't rhetorical; please let me know if Silk is missing something that is within its scope and is useful to most consumers. protocol based render function for multiple arity unmatching. this is really great. I don't think I fully understand the use cases for this protocol. Do you want to be able to look routes up by types? If so, since route names in Silk can be anything, you could use a type as a name. Anyway, I put together this little gist https://gist.github.com/DomKM/26658b53a50e48f0be70 of ways in which Silk could be used similarly to how I *think* someone might use Secretary's IRenderRoute. Do these cover the use cases for that protocol? I also agree with everything in Joel's response and look forward to working with him on improving the routing story. :) On Thu, Aug 7, 2014 at 2:52 PM, Joel Holdbrooks cjhold...@gmail.com javascript: wrote: I'm in agreement that Silk is a step in the right direction. I've reached out to Dom and I think we can learn a lot from each other and work together to improve the routing story in Clojure
Re: [ClojureScript] Re: [ANN] Silk, an isomorphic routing library for Clojure and ClojureScript
Hi Allen, Thanks for the feedback! 1) This, and precompiling regexes where possible, is my intention with Silk. 2) I'm not convinced that requiring fully-qualified routes would be a feature. Let's say we have route A which should match /foo/bar and route B which should match /foo/*. If these routes are unordered, route B would have to additionally be constrained with `(not= * bar)`. It seems like this could make route definition very painful when working in a large application with many routes that match on multiple parts of the URL. On Sat, Aug 9, 2014 at 10:06 AM, Allen Rohner aroh...@gmail.com wrote: I'd like to thank everyone in the community for both Silk, and Secretary. I'll throw out some (uninvited) feature requests I'd love to see in a future route-matching library. 1) Make trie-based route dispatching possible. A feature pedestal has/will soon have, is to compile the routing table into trie, rather than the compojure-style wrapped functions. This can have a nice speedup on busy applications. I'm not asking anyone to write this code, just consider the design such that it's possible to add this behavior in the future. 2) I'll claim that making route definition order is a misfeature. Routes should always be fully qualified, such that re-arranging them doesn't affect routing behavior (and therefore, the route table should be an unordered collection, like a map or set, not a vector). One nice readability reason for this is that if your route order does matter, than at least one route definition is lying about which routes it actually dispatches on. Just things to consider :-) Thanks, Allen On Thursday, August 7, 2014 9:31:56 PM UTC-5, DomKM wrote: Thanks for your feedback, Dylan! If you define routes with :path and :query, will the route match/unmatch with undefined query keys? If so, how are they handled? If not, I'd suggest making query matching optional, where nils are substituted. I'm not entirely sure what you mean, but I'll give it a shot. Please provide some example code if I answered the wrong question. `nil` is a pattern that matches anything. If your URL pattern query is `nil` then the URL query will not be checked. A map is a pattern that matches its values against the values of another map. Therefore, `nil` and `{}` are equivalent when used as a query pattern. You can make a query value pattern optional by wrapped it with `silk/option`. It's a little unclear how your matching functions relate to route. It looks like Silk always breaks at / in path and matches, is that correct? Yes. There is a URL type in Silk and matching is done against instances of it. The path is represented as a vector of segments. The readme is currently very deficient and I apologize for that. There are some really good things in secretary. What do you think about them? Splat, regex, format matchers. In terms of regex matching, Silk used to have a built-in regex pattern but I removed it when I made a big architectural change. I forget why I removed it, but I'll re-add it since it does seem like a very common requirement. Currently, part of Secretary's splat exists as a built-in Silk pattern. For example, `(silk/composite [foo :* bar])` would match fooanythingbar and return `{:* anything}`. The `:*` isn't special; it's just a keyword. Format is just a specific case of composite: `(silk/composite [:* . :format])`. Unlike Secretary, Silk does not have a built-in special syntax for string patterns. This is because special syntax strings are not composable and, since Silk matches against unencoded strings, who am I to say you can't have : or * in your URL paths? ;) Looking at the Secretary readme, there appear to be two ways to use splat that Silk currently does not have built-in support for. In Secretary, /foo/* would match /foo/bar/baz and return `{:* bar/baz}`. Also, /*/* would match /a/b and return `{:* [a b]}`. I keep saying built-in because, while multi-segment path patterns and binding the same parameter key to multiple path segments does not currently exist in Silk, it is very easy to extend Silk with that functionality. You could easily create a pattern that did exactly what Secretary and Clout do by default and use it to match a path instead of a vector. However, I do question the utility of these two features. Are either of these common requirements and, if so, could I see some examples of why they are necessary or helpful? This isn't rhetorical; please let me know if Silk is missing something that is within its scope and is useful to most consumers. protocol based render function for multiple arity unmatching. this is really great. I don't think I fully understand the use cases for this protocol. Do you want to be able to look routes up by types? If so, since route names in Silk can be anything, you could use a type as a name. Anyway, I put together this little gist
Re: [ClojureScript] Re: [ANN] Silk, an isomorphic routing library for Clojure and ClojureScript
I've been playing and like Silk a lot! However the following I find curious as I'm wondering what the intended behaviour should be: user= (silk/match (silk/composite [user- (silk/integer :id) -fred (silk /option :this that) s]) user-42-fredjs) {:id 42, :this j} user= (silk/match (silk/composite [user- (silk/integer :id) -fred (silk /option :this that) s]) user-42-freds) nil I would have thought the last one would have produced: user= (silk/match (silk/composite [user- (silk/integer :id) -fred (silk /option :this that) s]) user-42-freds) {:id 42, :this that} My only other suggestion, not worthy of a pull request, is the following: (defn domkm.silk/encode-query Takes a query map. Returns a string of query pairs encoded and joined. [query] (- query (apply into sorted-map) ; ensure consistent ordering to improve cache-ability of URLs... (map (fn [[k v]] (str (encode k) = (encode v (str/join ))) Regards, Marc On Sunday, 10 August 2014 05:00:50 UTC+10, DomKM wrote: Hi Allen, Thanks for the feedback! 1) This, and precompiling regexes where possible, is my intention with Silk. 2) I'm not convinced that requiring fully-qualified routes would be a feature. Let's say we have route A which should match /foo/bar and route B which should match /foo/*. If these routes are unordered, route B would have to additionally be constrained with `(not= * bar)`. It seems like this could make route definition very painful when working in a large application with many routes that match on multiple parts of the URL. On Sat, Aug 9, 2014 at 10:06 AM, Allen Rohner aro...@gmail.com javascript: wrote: I'd like to thank everyone in the community for both Silk, and Secretary. I'll throw out some (uninvited) feature requests I'd love to see in a future route-matching library. 1) Make trie-based route dispatching possible. A feature pedestal has/will soon have, is to compile the routing table into trie, rather than the compojure-style wrapped functions. This can have a nice speedup on busy applications. I'm not asking anyone to write this code, just consider the design such that it's possible to add this behavior in the future. 2) I'll claim that making route definition order is a misfeature. Routes should always be fully qualified, such that re-arranging them doesn't affect routing behavior (and therefore, the route table should be an unordered collection, like a map or set, not a vector). One nice readability reason for this is that if your route order does matter, than at least one route definition is lying about which routes it actually dispatches on. Just things to consider :-) Thanks, Allen On Thursday, August 7, 2014 9:31:56 PM UTC-5, DomKM wrote: Thanks for your feedback, Dylan! If you define routes with :path and :query, will the route match/unmatch with undefined query keys? If so, how are they handled? If not, I'd suggest making query matching optional, where nils are substituted. I'm not entirely sure what you mean, but I'll give it a shot. Please provide some example code if I answered the wrong question. `nil` is a pattern that matches anything. If your URL pattern query is `nil` then the URL query will not be checked. A map is a pattern that matches its values against the values of another map. Therefore, `nil` and `{}` are equivalent when used as a query pattern. You can make a query value pattern optional by wrapped it with `silk/option`. It's a little unclear how your matching functions relate to route. It looks like Silk always breaks at / in path and matches, is that correct? Yes. There is a URL type in Silk and matching is done against instances of it. The path is represented as a vector of segments. The readme is currently very deficient and I apologize for that. There are some really good things in secretary. What do you think about them? Splat, regex, format matchers. In terms of regex matching, Silk used to have a built-in regex pattern but I removed it when I made a big architectural change. I forget why I removed it, but I'll re-add it since it does seem like a very common requirement. Currently, part of Secretary's splat exists as a built-in Silk pattern. For example, `(silk/composite [foo :* bar])` would match fooanythingbar and return `{:* anything}`. The `:*` isn't special; it's just a keyword. Format is just a specific case of composite: `(silk/composite [:* . :format])`. Unlike Secretary, Silk does not have a built-in special syntax for string patterns. This is because special syntax strings are not composable and, since Silk matches against unencoded strings, who am I to say you can't have : or * in your URL paths? ;) Looking at the Secretary readme, there appear to be two ways to use splat that Silk currently does not have built-in support for. In Secretary, /foo/* would match /foo/bar/baz and return `{:* bar/baz}`. Also, /*/* would
Re: [ClojureScript] Re: [ANN] Silk, an isomorphic routing library for Clojure and ClojureScript
Thanks for your feedback, Dylan! If you define routes with :path and :query, will the route match/unmatch with undefined query keys? If so, how are they handled? If not, I'd suggest making query matching optional, where nils are substituted. I'm not entirely sure what you mean, but I'll give it a shot. Please provide some example code if I answered the wrong question. `nil` is a pattern that matches anything. If your URL pattern query is `nil` then the URL query will not be checked. A map is a pattern that matches its values against the values of another map. Therefore, `nil` and `{}` are equivalent when used as a query pattern. You can make a query value pattern optional by wrapped it with `silk/option`. It's a little unclear how your matching functions relate to route. It looks like Silk always breaks at / in path and matches, is that correct? Yes. There is a URL type in Silk and matching is done against instances of it. The path is represented as a vector of segments. The readme is currently very deficient and I apologize for that. There are some really good things in secretary. What do you think about them? Splat, regex, format matchers. In terms of regex matching, Silk used to have a built-in regex pattern but I removed it when I made a big architectural change. I forget why I removed it, but I'll re-add it since it does seem like a very common requirement. Currently, part of Secretary's splat exists as a built-in Silk pattern. For example, `(silk/composite [foo :* bar])` would match fooanythingbar and return `{:* anything}`. The `:*` isn't special; it's just a keyword. Format is just a specific case of composite: `(silk/composite [:* . :format])`. Unlike Secretary, Silk does not have a built-in special syntax for string patterns. This is because special syntax strings are not composable and, since Silk matches against unencoded strings, who am I to say you can't have : or * in your URL paths? ;) Looking at the Secretary readme, there appear to be two ways to use splat that Silk currently does not have built-in support for. In Secretary, /foo/* would match /foo/bar/baz and return `{:* bar/baz}`. Also, /*/* would match /a/b and return `{:* [a b]}`. I keep saying built-in because, while multi-segment path patterns and binding the same parameter key to multiple path segments does not currently exist in Silk, it is very easy to extend Silk with that functionality. You could easily create a pattern that did exactly what Secretary and Clout do by default and use it to match a path instead of a vector. However, I do question the utility of these two features. Are either of these common requirements and, if so, could I see some examples of why they are necessary or helpful? This isn't rhetorical; please let me know if Silk is missing something that is within its scope and is useful to most consumers. protocol based render function for multiple arity unmatching. this is really great. I don't think I fully understand the use cases for this protocol. Do you want to be able to look routes up by types? If so, since route names in Silk can be anything, you could use a type as a name. Anyway, I put together this little gist https://gist.github.com/DomKM/26658b53a50e48f0be70 of ways in which Silk could be used similarly to how I *think* someone might use Secretary's IRenderRoute. Do these cover the use cases for that protocol? I also agree with everything in Joel's response and look forward to working with him on improving the routing story. :) On Thu, Aug 7, 2014 at 2:52 PM, Joel Holdbrooks cjholdbro...@gmail.com wrote: I'm in agreement that Silk is a step in the right direction. I've reached out to Dom and I think we can learn a lot from each other and work together to improve the routing story in Clojure overall. There are some really good things in secretary. What do you think about them? Splat, regex, format matchers. protocol based render function for multiple arity unmatching. this is really great. These are definitely nice things and I'm willing to bet Silk would be capable of supporting some of them. It's obvious to me to that if we can iron out the details with Silk, Secretary could built on top of it as a higher level interface while at the same time taking advantage of what Silk has to offer. It might mean some breaking changes in Secretary but those were already slated anyway. -- Note that posts from new members are moderated - please be patient with your first post. --- You received this message because you are subscribed to the Google Groups ClojureScript group. To unsubscribe from this group and stop receiving emails from it, send an email to clojurescript+unsubscr...@googlegroups.com. To post to this group, send email to clojurescr...@googlegroups.com. Visit this group at http://groups.google.com/group/clojurescript. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send
Re: [ClojureScript] Re: [ANN] Silk, an isomorphic routing library for Clojure and ClojureScript
Hi Joel, Thanks for your feedback. Off topic, but Garden is awesome and Ankha has been indispensable when developing Om applications! Thanks for those. I didn't complain or suggest a patch because, aside from Bidi, I didn't find a Clojure or ClojureScript routing library that I could conceive of fitting *my criteria* without fundamental, completely breaking alterations -- alterations that warrant a new library, not a new version number. I care about compatibility, extensibility, bidirectionally, purity, transparency, and decoupling -- which is why I wrote Silk. Since you brought up Secretary as a routing library that could potentially be made isomorphic, I'll compare it to Silk as I did with Bidi. I am not as familiar with Secretary as I am with Bidi, and it looks to have changed since I last used it, so please do correct me if I say anything incorrect or misleading. In terms of commonalities with Silk, Secretary obviously works in ClojureScript and has named routes. It is also somewhat extensible via protocols. In terms of differences, Secretary is obviously incompatible with Clojure, couples route definition with route handling, uses a complex macro to define routes instead of using data structures, can only match URL paths, and is impure. While I value all of these features that Secretary lacks, I think that last one, impurity, is the most significant. I love Clojure's pragmatic philosophy; it is mostly pure but very practical. Mutation is always possible, but uncontrolled mutation is frowned upon and intentionally difficult. Where we draw the line between functional purity and impurity is unclear and very open to interpretation, but it is my strong opinion that route creation and matching should sit firmly on the pure side. The public interface for defining routes in Secretary is `defroute`, a macro which only sometimes defines something but *always* mutates a global atom. When using Secretary, how does one know the order in which routes are matched? I assume it is in dependency order as determined by the Google Closure compiler, but it is unclear to me. What about if Secretary is ported to Clojure and you hot reload namespaces as you develop with it? You could potentially change the routing order from what it would be at runtime. Component https://github.com/stuartsierra/component is extremely useful for development and its popularity is well warranted, but Secretary's design fundamentally precludes compatibility with Component or anything that requires that mutation be limited and controllable. Silk is also, in many ways, lower level than Secretary. Secretary could be built on top of Silk without much additional effort since extending Silk to match paths specified with Clout/Secretary syntax (/path/to/:param) would be trivial. On the other hand, building Silk on top of Secretary would be extremely difficult. It is not my intention to lambast Secretary and I hope it doesn't come across that way. Solving front-end routing problems is difficult and is a different beast altogether from back-end routing because it lacks the established Ring model (adapters, requests, etc.) and even lacks the HTTP request/response model. Secretary did a good job at solving these difficult problems. We share a desire to bring an end to the saturation of routing libraries. I just don't think that retrofitting a library designed for one paradigm will work without causing significant pain to users. At some point, it just makes sense to start fresh. Silk is designed from the ground up to work on both platforms, be extremely extensible, and include all of the best parts of the various routing libraries that I have used and examined. These strict flexibility requirements led to a design which, I think, is very simple and fairly low-level while remaining reasonably convenient. I appreciate your invitation to help you work toward the goal of making Secretary isomorphic and would be happy to talk to you about it. However, I don't think that Secretary or any other routing library can easily replace Silk. Therefore, I also invite you to help improve any deficiencies you see in Silk. I would greatly appreciate constructive criticism. I'll take you up on your offer to email you privately. :) Cheers, Dom On Tue, Aug 5, 2014 at 7:35 PM, Joel Holdbrooks cjholdbro...@gmail.com wrote: Awesome work. It's fantastic to see a library that's interested in targeting both the front-end and the back-end. This is the type of attitude I would love to see more often in the Clojure community. OTOH, it would have been awesome to have heard your thoughts WRT the concept of isomorphic routing on the Secretary issue tracker. You said you couldn't find something suitable, why didn't you complain or suggest a patch? We would have been happy to have supported your endeavor in making that possible and your ideas. In fact, we would have been willing to make breaking changes for them! Many of us want this! Originally, several
Re: [ClojureScript] Re: [ANN] Silk, an isomorphic routing library for Clojure and ClojureScript
Dom, We’re actually well aware of many of the flaws you have pointed out with Secretary. In fact, we even have open issues for some of them. While I value all of these features that Secretary lacks, I think that last one, impurity, is the most significant... Mutation is always possible, but uncontrolled mutation is frowned upon and intentionally difficult It is not as if we don’t understand the benefits of immutability or know Clojure idioms. There’s no need to school anyone. We're not n00bs here. :-) When I became a committer to the library I did what I could to improve what was already there. Personally, I do not like the overly complex macro that we have nor do I like the global state. These are just implementation details and it wouldn’t require too much effort to switch to something that’s immutable with a minimum amount of breaking change. We already have several vanilla functions for adding/removing routes that could easily be made stateless. The three of us (myself, Gianni, and Joel) have been busy and just haven’t had the chance to fix it. Anyway, you’ve done a great job enumerating your reasons for writing Silk and flaws about Secretary; some of it is accurate, some of it is misguided. I’m not going to return fire by addressing them because I don’t think it will make much of a difference. Really, what we need to do is work together. We can continue this discussion elsewhere. Joel -- 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.