{"action":"created","issue":{"url":"https://api.github.com/repos/juxt/bidi/issues/5","labels_url":"https://api.github.com/repos/juxt/bidi/issues/5/labels{/name}","comments_url":"https://api.github.com/repos/juxt/bidi/issues/5/comments","events_url":"https://api.github.com/repos/juxt/bidi/issues/5/events","html_url":"https://github.com/juxt/bidi/issues/5","id":25443315,"number":5,"title":"Limitations when using same handler for different routes","user":{"login":"ragnard","id":882,"avatar_url":"https://avatars.githubusercontent.com/u/882?v=3","gravatar_id":"","url":"https://api.github.com/users/ragnard","html_url":"https://github.com/ragnard","followers_url":"https://api.github.com/users/ragnard/followers","following_url":"https://api.github.com/users/ragnard/following{/other_user}","gists_url":"https://api.github.com/users/ragnard/gists{/gist_id}","starred_url":"https://api.github.com/users/ragnard/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ragnard/subscriptions","organizations_url":"https://api.github.com/users/ragnard/orgs","repos_url":"https://api.github.com/users/ragnard/repos","events_url":"https://api.github.com/users/ragnard/events{/privacy}","received_events_url":"https://api.github.com/users/ragnard/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":null,"milestone":null,"comments":4,"created_at":"2014-01-11T13:22:30Z","updated_at":"2015-12-30T15:19:05Z","closed_at":"2015-12-30T08:48:40Z","body":"Hi,\r\n\r\nFirst of all, thanks for a fantastic library, really enjoying using bidi with Liberator. The bi-directionality and routes as data is great!\r\n\r\nI encountered a few issues when defining a route structure that has the same handler occurring multiple times. I'm not sure whether this is because it's a bad idea to do that, but let me show you the example I'm using:\r\n\r\n ```clojure\r\n(def routes\r\n  [\"/\" [[\"posts\" 'posts-handler]\r\n        [[\"users/\" :user \"/posts\"] 'posts-handler]]])\r\n```\r\n\r\nIn this case, `posts-handler` understands queries both for all posts (first route), and for a specific users posts (second route). \r\n\r\nGiven this route structure, I would like to be able to generate URLs both for all posts, and a specific users posts like so:\r\n\r\n```clojure\r\n(path-for routes 'posts-handler)\r\n;; => \"/posts\"\r\n(path-for routes 'posts-handler :user \"blahonga\")\r\n;; => \"/users/blahonga/posts\"\r\n```\r\n\r\nie. if params are given, routes where the params occur should be preferred. It may even make sense to fail completely if all params supplied are not used. I'm not sure.\r\n\r\nCurrently the unmatching takes the first route matching the given handler. However, the first case in the above `path-for` example actually blows up with `clojure.lang.ExceptionInfo: Cannot form URI without a value given for :user parameter` (full stack trace below). I believe this is due to non-lazyness (or lazy-seq chunking),  `unresolve-handler` for PersistentVectors uses:\r\n\r\n```clojure\r\n(first (keep #(match-pair % m) this))\r\n```\r\n\r\nWhich seems to be not lazy for `PersistentVectors`.\r\n\r\nFull stack trace:\r\n\r\n```\r\nclojure.lang.ExceptionInfo: Cannot form URI without a value given for :user parameter\r\n at clojure.core$ex_info.invoke (core.clj:4327)\r\n    bidi.bidi$eval28675$fn__28678.invoke (bidi.clj:56)\r\n    bidi.bidi$eval28612$fn__28624$G__28599__28631.invoke (bidi.clj:33)\r\n    bidi.bidi$eval28811$fn__28812$fn__28813.invoke (bidi.clj:133)\r\n    clojure.core$map$fn__4207.invoke (core.clj:2485)\r\n    clojure.lang.LazySeq.sval (LazySeq.java:42)\r\n    clojure.lang.LazySeq.seq (LazySeq.java:60)\r\n    clojure.lang.RT.seq (RT.java:484)\r\n    clojure.core$seq.invoke (core.clj:133)\r\n    clojure.core$apply.invoke (core.clj:617)\r\n    bidi.bidi$eval28811$fn__28812.invoke (bidi.clj:133)\r\n    bidi.bidi$eval28711$fn__28725$G__28700__28732.invoke (bidi.clj:80)\r\n    bidi.bidi$unmatch_pair.invoke (bidi.clj:152)\r\n    bidi.bidi$eval28898$fn__28899$fn__28900.invoke (bidi.clj:160)\r\n    clojure.core$keep$fn__6349.invoke (core.clj:6599)\r\n    clojure.lang.LazySeq.sval (LazySeq.java:42)\r\n    clojure.lang.LazySeq.seq (LazySeq.java:60)\r\n    clojure.lang.LazySeq.first (LazySeq.java:82)\r\n    clojure.lang.RT.first (RT.java:577)\r\n    clojure.core$first.invoke (core.clj:55)\r\n    bidi.bidi$eval28898$fn__28899.invoke (bidi.clj:160)\r\n    bidi.bidi$eval28754$fn__28768$G__28743__28775.invoke (bidi.clj:87)\r\n    bidi.bidi$unmatch_pair.invoke (bidi.clj:151)\r\n    bidi.bidi$path_for.doInvoke (bidi.clj:207)\r\n    clojure.lang.RestFn.invoke (RestFn.java:425)\r\n    bidi.bidi$eval32697.invoke (form-init1346470612871071144.clj:1)\r\n    clojure.lang.Compiler.eval (Compiler.java:6619)\r\n    clojure.lang.Compiler.eval (Compiler.java:6582)\r\n    clojure.core$eval.invoke (core.clj:2852)\r\n    clojure.main$repl$read_eval_print__6588$fn__6591.invoke (main.clj:259)\r\n    clojure.main$repl$read_eval_print__6588.invoke (main.clj:259)\r\n    clojure.main$repl$fn__6597.invoke (main.clj:277)\r\n    clojure.main$repl.doInvoke (main.clj:277)\r\n    clojure.lang.RestFn.invoke (RestFn.java:1096)\r\n    clojure.tools.nrepl.middleware.interruptible_eval$evaluate$fn__675.invoke (interruptible_eval.clj:56)\r\n    clojure.lang.AFn.applyToHelper (AFn.java:159)\r\n    clojure.lang.AFn.applyTo (AFn.java:151)\r\n    clojure.core$apply.invoke (core.clj:617)\r\n    clojure.core$with_bindings_STAR_.doInvoke (core.clj:1788)\r\n    clojure.lang.RestFn.invoke (RestFn.java:425)\r\n    clojure.tools.nrepl.middleware.interruptible_eval$evaluate.invoke (interruptible_eval.clj:41)\r\n    clojure.tools.nrepl.middleware.interruptible_eval$interruptible_eval$fn__716$fn__719.invoke (interruptible_eval.clj:171)\r\n    clojure.core$comp$fn__4154.invoke (core.clj:2330)\r\n    clojure.tools.nrepl.middleware.interruptible_eval$run_next$fn__709.invoke (interruptible_eval.clj:138)\r\n    clojure.lang.AFn.run (AFn.java:24)\r\n    java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1145)\r\n    java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:615)\r\n    java.lang.Thread.run (Thread.java:744)\r\n```\r\n\r\n\r\n\r\n\r\n"},"comment":{"url":"https://api.github.com/repos/juxt/bidi/issues/comments/168018008","html_url":"https://github.com/juxt/bidi/issues/5#issuecomment-168018008","issue_url":"https://api.github.com/repos/juxt/bidi/issues/5","id":168018008,"user":{"login":"isaksky","id":607986,"avatar_url":"https://avatars.githubusercontent.com/u/607986?v=3","gravatar_id":"","url":"https://api.github.com/users/isaksky","html_url":"https://github.com/isaksky","followers_url":"https://api.github.com/users/isaksky/followers","following_url":"https://api.github.com/users/isaksky/following{/other_user}","gists_url":"https://api.github.com/users/isaksky/gists{/gist_id}","starred_url":"https://api.github.com/users/isaksky/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/isaksky/subscriptions","organizations_url":"https://api.github.com/users/isaksky/orgs","repos_url":"https://api.github.com/users/isaksky/repos","events_url":"https://api.github.com/users/isaksky/events{/privacy}","received_events_url":"https://api.github.com/users/isaksky/received_events","type":"User","site_admin":false},"created_at":"2015-12-30T15:19:05Z","updated_at":"2015-12-30T15:19:05Z","body":"Sounds good, thank you!"}}