简体   繁体   English

如何在Clojure中使用地图功能?

[英]How to use map function in clojure?

I have a function named f which supposed to be mapped onto a vector in my main function. 我有一个名为f的函数,应该在我的主要函数中映射到一个向量上。 However when I lein run my code nothing happens... 但是,当我lein run我的代码时,什么也没有发生……

(ns my-proj.core
  (:gen-class))

(def f
  (fn
    [x]
    (println x)))

(def -main
  (fn
    [& args]
    (map f args)))

(-main [1 2 3 4 5])

The code seems correct according to the docs . 根据文档 ,代码似乎是正确的。 But what am I missing? 但是我想念什么? Plz help. 请帮助。

Since map is lazy, you'll need to use a different approach if you want side effects. 由于map是懒惰的,因此如果需要副作用,则需要使用其他方法。 In this case, you could use run! 在这种情况下,您可以使用run! :

(run! println [1 2 3 4 5])
;; 1
;; 2
;; 3
;; 4
;; 5
;;=> nil

Your function f is returning nil because println returns nil . 您的函数f返回nil因为println返回nil The function identity returns the value that it is given. 函数identity返回给定的值。 Here I have commented out your println call so that f effectively becomes identity : 在这里,我已经注释掉了您的println调用,以便f有效地成为identity

(def f
  (fn
    [x]
    ;(println x)
    x
    ))

(defn -main [& args]
  (apply map f args))

(defn so []
  (-main [1 2 3 4 5])) 

To test the above just call (so) . 要测试以上内容,只需致电(so) I added in apply to get rid of the double wrapping of the result. 我添加了apply来消除结果的双重包装。 You could substitute identity for the above call to f (ie (apply map identity args) ). 您可以用identity代替上述对f调用(即(apply map identity args) )。

If you do want to println and return a value you can do that as well: 如果您确实要println并返回一个值,您也可以这样做:

(defn probe
  ([x]
   (println x)
   x)
  ([x msg]
    (println msg x)
    x))

Just call probe instead of f or identity (ie (apply map probe args) ). 只需调用probe而不是fidentity (即(apply map probe args) )。 probe is a side-effecting identity function, where the side effect is to print the return value. probe是一个具有副作用的identity函数,其中的副作用是打印返回值。

As a side note, if you do ever suspect that laziness is causing problems then wrap the return value in seq , or use mapv instead of map . 附带说明一下,如果您确实怀疑懒惰导致了问题,则将返回值包装在seq ,或者使用mapv代替map

There are several problems with your code: 您的代码有几个问题:

  1. -main is variadic, and the variadic variable ( args ) is what you're passing to map . -main是可变参数,可变参数( args )是您要传递给map But you're calling -main as (-main [1 2 3 4 5]) . 但是您将-main称为(-main [1 2 3 4 5]) So args will be ([1 2 3 4 5]) . 所以args将是([1 2 3 4 5]) So you are map ing not over a vector, but over a sequence containing a vector. 因此,您的map不是在矢量上,而是在包含矢量的序列上。

    Either define -main to take a single argument, or call -main as (-main 1 2 3 4 5) . 定义-main以接受单个参数,或将-main称为(-main 1 2 3 4 5)

  2. You make the classic error of mixing side-effects and laziness. 您会产生混合副作用和懒惰的经典错误。 Sometimes this is useful, but often it's a mistake. 有时这很有用,但通常是错误的。 In your case, it's a mistake -- nothing will happen, because you never realize any of the values (which will all be nil , but the println will at least be executed as a side-effect). 在您的情况下,这是一个错误-不会发生任何事情,因为您永远不会意识到任何值(全都是nil ,但是println至少会作为副作用执行)。

    You can force the sequence via do-all . 您可以通过do-all强制执行序列。 However, since the result is a sequence of nil s, you are really only interested in performing the side-effects rather than the actual values produced. 但是,由于结果是nil的序列,因此您实际上只对执行副作用感兴趣,而不是对产生的实际值感兴趣。 So dorun probably makes more sense. 所以dorun可能更有意义。 But the most idiomatic way would be to use doseq instead of map . 但是,最惯用的方法是使用doseq而不是map doseq is similar to for (which is basically logically equivalent to some syntactic sugar around map ), except doseq is not lazy and does not produce a sequence -- it's purely for side-effects. doseq类似于for (这基本上是逻辑上等同于周围的一些语法糖map ),不同之处doseq 懒惰并且不产生的序列-它是纯粹为副作用。

My code was incorrect, for starters I should not have passed a vector into the main; 我的代码不正确,对于初学者来说,我不应该将向量传递给主体。 then all I had to do was add doall . 然后我要做的就是添加doall So here's what I wanted in case you also need the map to work. 所以这就是我想要的,以防您也需要map才能工作。

(ns my-proj.core
  (:gen-class))

(defn f
  [x]
  (println (+ x 1)))

(defn -main
  [& args]
  (doall
    (map f args)))

(-main 1 2 3 4 5)

I think what happens is: a vector will be passed as a single argument, so if you add doall the map will work but it will only print out your vector as one thing. 我认为发生的事情是:向量将作为单个参数传递,因此,如果添加doallmap将起作用,但只会将向量打印为一件事。 I thought it would be unwrapped by the map. 我以为它将被地图解开。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM