1

我有以下问题:

我确实理解函数式编程语言的概念不允许不可变变量,所以经典的变量赋值和用法就像

var foo = bar();

after that in another function...

var baz = funnything(foo);

是不可能的(如果是,请纠正我,我仍在尝试了解函数式编程背后的整个想法和概念)。

我正在尝试使用 Clojure 进行一些操作,并达到了我卡住的地步:

我想获取一个网页并将 DOM 保存到一个变量中以供以后使用。程序启动,出现提示,用户可以输入他想要获取的 URL。

在获取网站的 DOM 后,他可以通过 DOM 导航,例如获取标题、所有链接或其他内容。

问题:因为我不能使用像

; More or less pseudo-code
(def page nil)

(get-url [url]
  (page (browser/get url)))

(get-title
    (println (html/select page [:title])))

我必须使用以下构造:

(get-title [url]
    (println (html/select (browser/get url) [:title])))

由于这种构造,每当我想通过 访问网站的某个元素时get-titleget-links或者每当用户在命令提示符下输入其中一种方法时,我必须下载整个网页。

我在这里想念什么吗?Clojure 中有经典的分配吗?我是否做错了事,应该在动手实践和边做边学之前学习更多的函数式编程概念吗?

4

2 回答 2

2

您可以轻松地缓存 (browser/get url) 的值,这样您就不必在每次要检查它的属性时重新获取页面。见clojure.core/memoize。但这只能解决部分问题。

在您的特定情况下,您的程序需要某种全局(或会话范围)、可变、“当前页面”或至少“当前 url”的概念,因为这是您希望用户输入的内容和调整。Clojure 提供了多种结构来管理可变状态。

由于您一次只处理一页,因此最好使用原子进行建模。请参阅http://clojure.org/atomshttp://clojuredocs.org/clojure_core/clojure.core/swap!

于 2013-04-11T08:46:17.820 回答
2

你误解了clojure中的赋值。

(page (browser/get url))

不等价于:page = browser/get(url),它等价于 page(browser/get(url))。

我认为您实际上并不需要全局变量,只需要可组合的函数。您的示例可能如下所示:

(defn get-title [url]
  (let [page (browser/get url)]
    (println (html/select page [:title]))))

如果你想缓存 broser/get 的返回值,那并使用 memoize,就像 Joost 提到的那样。

于 2013-04-11T08:54:08.933 回答