Clojure和Varags打招呼
输入:“Michael”“Julia”“Joe”“Sam” 输出:嗨,Michael,Julia,Joe和Sam(注意逗号和单词“and”) 输入:无 输出:嗨,世界 这是我的第一次尝试:Clojure和Varags打招呼,clojure,Clojure,输入:“Michael”“Julia”“Joe”“Sam” 输出:嗨,Michael,Julia,Joe和Sam(注意逗号和单词“and”) 输入:无 输出:嗨,世界 这是我的第一次尝试: (defn say-hi [& name] (print "Hi," name)) user> (say-hi "Michael") Hi, (Michael) nil user> (say-hi "Michael" "Julia") Hi, (Michael Julia) nil
(defn say-hi [& name]
(print "Hi," name))
user> (say-hi "Michael")
Hi, (Michael)
nil
user> (say-hi "Michael" "Julia")
Hi, (Michael Julia)
nil
问题:
首先,Clojure支持多个arity函数,因此您可以这样做以实现默认行为:
(defn say-hi
([] (say-hi "World"))
([& names] ...))
然后,您要做的是获取一个seq并将它包含的所有字符串连接在一起,中间使用“,”
。clojure.string
名称空间包含许多字符串操作函数,其中一个是clojure.string/join
:
(require '[clojure.string :as string])
(string/join ", " ["Michael", "Julia"])
;; => "Michael, Julia"
(use '[clojure.string :only [join]])
(defn sentencify [& elems]
(->>
[(join ", " (butlast elems)) (last elems)]
(remove empty?)
(join " and ")))
(defn say-hi [& name]
(print "Hi," (if name
(sentencify name)
"World!")))
但是seq的最后一个元素应该使用和“
作为分隔符连接起来,因此您将得到如下结果:
(require '[clojure.string :as string])
(defn say-hi
([] (say-hi "World"))
([& names]
(if (next names)
(format "Hi, %s, and %s!"
(string/join ", " (butlast names))
(last names))
(format "Hi, %s!" (first names)))))
请注意,您必须区分单个名称和多个名称的情况,并且(下一个名称)
基本上检查seq是否包含多个元素。(您可以通过向函数添加另一个arity来实现这一点。)
您可以使用
clojure.string/join
:
(require '[clojure.string :as string])
(string/join ", " ["Michael", "Julia"])
;; => "Michael, Julia"
(use '[clojure.string :only [join]])
(defn sentencify [& elems]
(->>
[(join ", " (butlast elems)) (last elems)]
(remove empty?)
(join " and ")))
(defn say-hi [& name]
(print "Hi," (if name
(sentencify name)
"World!")))
简明的解决方案:
(defn say-hi [& names]
(let [names (case (count names)
0 ["world"]
1 names
(concat (butlast names) (list (str "and " (last names)))))]
(->> names, (cons "Hi"), (interpose ", "), (apply str))))
(say-hi)
;"Hi, world"
(say-hi "Michael")
;"Hi, Michael"
(say-hi "Michael" "Julia" "Joe" "Sam")
;"Hi, Michael, Julia, Joe, and Sam"
对于长的名称列表
,您可能希望避免使用计数
、最后一个
、和但是最后一个
,可以先将名称
倒入向量中
要打印(如问题所示)而不是返回格式化字符串,请将
print
附加到最终表单:
(->> names, (cons "Hi"), (interpose ", "), (apply str), print)
我担心判刑部分不起作用:
(打声招呼“Michael”)IllegalArgumentException不知道如何从以下位置创建ISeq:clojure.core$name clojure.lang.RT.seqFrom(RT.java:505)
修复了打字错误<代码>判刑也应该接受varargs。非常感谢您的解释——它非常清晰易懂。多重算术函数使代码易于阅读。和(如果(下一个名称)…
检查工作得很好!也许返回输出而不是打印它?谢谢!它是有效的,这个概念甚至适用于更大的问题。顺便问一下,如何配置REPL输出以分号开头?它真的很方便复制和过去。(我在使用Emacs+Cider-nrepl。)@Nick我伪造了输出布局。我在LightTable instarepl上做的。