Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Clojure for循环不返回atom的更新值_Clojure - Fatal编程技术网

Clojure for循环不返回atom的更新值

Clojure for循环不返回atom的更新值,clojure,Clojure,我试图写一个函数,计算给定字符串中元音和辅音的数量。返回值是一个带有两个键的映射,元音和辅音。每个键的值只是计数 到目前为止,我能够开发的功能是 (defn count-vowels-consenants [s] (let [m (atom {"vowels" 0 "consenants" 0}) v #{"a" "e" "i" "o" "u"}] (for [xs s] (if (contains? v (str xs))

我试图写一个函数,计算给定字符串中元音和辅音的数量。返回值是一个带有两个键的映射,
元音
辅音
。每个键的值只是计数

到目前为止,我能够开发的功能是

(defn count-vowels-consenants [s]
  (let [m (atom {"vowels" 0 "consenants" 0})
        v #{"a" "e" "i" "o" "u"}]
    (for [xs s]
      (if
          (contains? v (str xs))
            (swap! m update-in ["vowels"] inc)
            (swap! m update-in ["consenants"] inc)
       ))
    @m))
但是
(计算元音同音词“sldkfjlskjwe”)
返回
{“元音”:0“同音词”:0}

我做错了什么


编辑:将我的输入从
str
更改为
s
,因为
str
是Clojure中的一个函数。

我认为
for
是懒惰的,所以在你尝试实现它之前,你不会真正做任何事情。我在
for
循环中添加了一个
first
,该循环实现了列表,并导致了一个错误,您使用
str
字符串覆盖了
str
函数。理想情况下,您可以在没有原子繁琐的情况下执行此操作

(defn count-vowels-consonants [s]
  (let [v #{\a \e \i \o \u}
        vowels (filter v s)
        consonants (remove v s)]
    {:consonants (count consonants)
     :vowels (count vowels)}))

如果原子是您想要的,那么使用
doseq
而不是
for
,它将为字符串中的所有内容更新原子。还要确保在函数绑定中使用
str
函数时不会覆盖该函数

我认为
for
是懒惰的,所以在你尝试实现之前,你不会真正做任何事情。我在
for
循环中添加了一个
first
,该循环实现了列表,并导致了一个错误,您使用
str
字符串覆盖了
str
函数。理想情况下,您可以在没有原子繁琐的情况下执行此操作

(defn count-vowels-consonants [s]
  (let [v #{\a \e \i \o \u}
        vowels (filter v s)
        consonants (remove v s)]
    {:consonants (count consonants)
     :vowels (count vowels)}))

如果原子是您想要的,那么使用
doseq
而不是
for
,它将为字符串中的所有内容更新原子。还要确保在函数绑定中使用
str
函数时不会覆盖该函数

正如@Brandon H所提到的,for是懒惰的。如果需要,可以使用循环递归。在这里,我改变为循环重现

(defn count-vowels-consenants [input]
  (let [m (atom {"vowels" 0 "consenants" 0})
        v #{"a" "e" "i" "o" "u"}]
    (loop [s input]
      (when (> (count s) 0)
      (if
          (contains? v (first (str s) ))
            (swap! m update-in ["vowels"] inc)
            (swap! m update-in ["consenants"] inc)
       ))
       (recur (apply str (rest s))))
    @m))

正如@Brandon H所提到的,for是懒惰的。如果需要,可以使用循环递归。在这里,我改变为循环重现

(defn count-vowels-consenants [input]
  (let [m (atom {"vowels" 0 "consenants" 0})
        v #{"a" "e" "i" "o" "u"}]
    (loop [s input]
      (when (> (count s) 0)
      (if
          (contains? v (first (str s) ))
            (swap! m update-in ["vowels"] inc)
            (swap! m update-in ["consenants"] inc)
       ))
       (recur (apply str (rest s))))
    @m))

如果这种副作用方案是不可避免的(我想是出于简单的教育原因),只需将
for
替换为
for
(顺便说一句:您的初始代码中有一个错误:您使用
str
作为输入参数名,然后尝试将其用作函数。因此,您在clojure.core中隐藏def,只是尽量避免使用与核心函数类似的参数名):

否则,您可以这样做:

user> (reduce #(update %1
                       (if (#{\a \e \i \o \u} %2) 
                         "vowels" "consonants")
                       (fnil inc 0))
              {} "qwertyui")
;;{"consonants" 5, "vowels" 3}

或者这个(如果你擅长用
true/false
代替“元音/辅音”):


如果这种副作用方案是不可避免的(我想是出于简单的教育原因),只需将
for
替换为
for
(顺便说一句:您的初始代码中有一个错误:您使用
str
作为输入参数名,然后尝试将其用作函数。因此,您在clojure.core中隐藏def,只是尽量避免使用与核心函数类似的参数名):

否则,您可以这样做:

user> (reduce #(update %1
                       (if (#{\a \e \i \o \u} %2) 
                         "vowels" "consonants")
                       (fnil inc 0))
              {} "qwertyui")
;;{"consonants" 5, "vowels" 3}

或者这个(如果你擅长用
true/false
代替“元音/辅音”):


这个问题和所有现存的答案都假设每个字符都是元音或辅音:不是这样。即使在ASCII码中,也有小写和大写字母。我会这样做的

(defn count-vowels-consonants [s]
  (let [vowels  #{\a \e \i \o \u
                  \A \E \I \O \U}
        classify (fn [c]
                   (if (Character/isLetter c)
                     (if (vowels c) :vowel :consonant)))]
    (map-v count (dissoc (group-by classify s) nil))))
。。。其中
map-v
是一个函数,该函数将
map
的值映射为:

(defn map-v [f m] (reduce (fn [a [k v]] (assoc a k (f v))) {} m))
比如说,

(count-vowels-consonants "s2a Boo!")
;{:vowel 3, :consonant 2}

这只遍历字符串一次

这个问题和所有现存的答案都假设每个字符都是元音或辅音:不是这样。即使在ASCII码中,也有小写和大写字母。我会这样做的

(defn count-vowels-consonants [s]
  (let [vowels  #{\a \e \i \o \u
                  \A \E \I \O \U}
        classify (fn [c]
                   (if (Character/isLetter c)
                     (if (vowels c) :vowel :consonant)))]
    (map-v count (dissoc (group-by classify s) nil))))
。。。其中
map-v
是一个函数,该函数将
map
的值映射为:

(defn map-v [f m] (reduce (fn [a [k v]] (assoc a k (f v))) {} m))
比如说,

(count-vowels-consonants "s2a Boo!")
;{:vowel 3, :consonant 2}

这只遍历字符串一次

更新atom是一项要求吗?@jmargolisvt不,对atom没有特殊要求。在我看来,这是用Clojure改变状态的自然方式,但我完全愿意接受其他选择。虽然你已经收到了问题的答案,但我想强调一下你现在可能已经意识到的基本误解——Clojure中没有“for loop”
for
是一个用于创建列表的构造,因此它不会“循环”(正如您所看到的,
loop
的名称是恰当的)。在循环上下文中使用这个词的命令式语言可能会让人困惑,但这在clojure中不是这个意思。更新atom是一种需求吗?@jmargolisvt不,对atom没有特定的需求。在我看来,这是用Clojure改变状态的自然方式,但我完全愿意接受其他选择。虽然你已经收到了问题的答案,但我想强调一下你现在可能已经意识到的基本误解——Clojure中没有“for loop”
for
是一个用于创建列表的构造,因此它不会“循环”(正如您所看到的,
loop
的名称是恰当的)。在循环上下文中,命令式语言的一词可能会让人困惑,但这在clojure中并不是什么意思。仅供参考,
groupby
可能更好,因为它只会对字符串/seq进行一次迭代。@Brandon H ahhh,很好地掌握了
str
,这对我来说太草率了。这肯定比我的解决方案更优雅。谢谢你给我指点
doseq
。仅供参考,
groupby
可能更好,因为它只对字符串/seq进行一次迭代。@Brandon H ahhh,对
str
的理解很好,这对我来说太草率了。这肯定比我的解决方案更优雅。谢谢你指给我看<