Clojure中全局变量的赋值和用法

时间:2013-04-11 08:11:54

标签: clojure

我遇到了以下问题:

我确实理解函数式编程语言的概念不允许不可变变量,因此经典变量赋值和使用如

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中有经典的配饰吗?我做错了什么并且应该在开始实践和边做边学之前学习更多功能性编程概念?

2 个答案:

答案 0 :(得分:2)

您可以轻松缓存(浏览器/获取网址)的值,这样您每次要检查其属性时都不必重新获取该页面。见clojure.core/memoize。但这只会解决部分问题。

在您的特定情况下,您的程序需要某种全局(或会话作用域),可变的"当前页面的概念"或至少,"当前网址",因为这是您期望用户输入和修改的内容。 Clojure提供了多种用于管理可变状态的构造。

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

答案 1 :(得分: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]))))

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