【问题标题】:bug in clojure URL shortener during auto-generation of IDs自动生成 ID 期间 clojure URL 缩短器中的错误
【发布时间】:2013-07-09 22:16:18
【问题描述】:

我在 Clojure Programming 中遇到了一段 sn-p 代码,它有错误。我是 Clojure 的新手,无法弄清楚代码中的错误在哪里。

(ns ring-tutorial.core
  (:require [compojure.handler :as ch]
        [compojure.core :refer [GET PUT POST defroutes]]
        [compojure.route :as cr]
        [ring.util.response :as response]))

(def ^:private counter (atom 0))
(def ^:private mappings (ref {}))

(defn url-for
[id]
(@mappings id))

(defn shorten!
 "Stores the given URL under a new unique identifier and returns it as a string."
 ([url]
 (let [id (swap! counter inc)
       id (Long/toString id 36)] ;;convert to base 36 string
   (or (shorten! url id)
       (recur url))))
([url id] ;;url is provided with an id.
 (dosync
  (when-not (@mappings id)
    (alter mappings assoc id url)
    id))))

(defn retain
 [& [url id :as args]]
(if-let [id (apply shorten! args)]
{:status 201
  :headers {"Location" id}
 :body (list "URL " url " assigned the short identifier " id " \n")}
{:status 409 :body (format "Short URL %s is already taken \n " id)}))

(defn redirect
 [id]
(if-let [url (url-for id)]
(ring.util.response/redirect url) ;;Appropriately redirect the URL based on ethe ID.
{:status 404 :body (str "No such short URL: \n" id)})) ;;Return a 404 if no URL for the particular ID found.

(defroutes app*
 (GET "/" request "Hello World!")
 (PUT "/:id" [id url] (retain url id))
 (POST "/" [url ] (retain url))
 (GET "/:id" [id] (redirect id))
 (GET "/list/" [] (interpose "\n" (keys @mappings)))
 (cr/not-found "Its a 404!\n"))

(def app (ch/api #'app*))

当我运行 $ CURL -X POST 'localhost:8080/?url=http://www.yahoo.com/' 我得到 URL 已被赋予标识符 1 当我重新运行命令时,我得到'URL 已经被赋予了标识符 2,但它应该标记一个错误,说 yahoo.com 已经有标识符 1。

这是我可以看到的错误,它在缩短!功能但无法纠正。

谢谢!

【问题讨论】:

    标签: clojure compojure ring


    【解决方案1】:

    您的mappings 引用指向缩短 ID 到长 URL 的映射。在shorten! 函数中,您需要获取一个 URL 并查看是否已经分配了一个 ID。相反,您每次都会生成一个新 ID,并在地图中查找它以查看是否为它分配了一个 URL,但这种情况永远不会发生。

    要解决此问题,您需要维护第二个映射,即长 URL 到缩短 ID。在 dosync 块内,您首先在这个新地图中查找 URL,如果未找到该 URL,则生成一个 ID 并将 URL、ID 对添加到两个地图中。

    【讨论】:

    • 所以我应该创建一个名为 mappings2 {} 的新 Ref。然后(@mappings2 网址)。并且在dosync中还有另一个when-not?像 (dosync (when-not (@mappings2 url) something?) 我有点困惑,一些代码真的很有帮助。:)
    猜你喜欢
    • 2011-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-13
    • 2023-03-28
    • 1970-01-01
    • 2017-08-25
    相关资源
    最近更新 更多