从 clojure 映射中的动态键获取值

get value from dynamic key in clojure map

我有一个 clojure 映射

1
2
+  69 (def names {:production"prayag"                                                                    
+  70             :staging   "upd"})

我需要从一个动态的键变量 environment 中获取一个值。

类似下面的东西会抛出异常,

1
2
3
4
5
+  72 (defn get-name [environment]                                                                                  
+  73   (let [
+  74        name (:(environment) names)]                                                                
+  75        println name                                                                          
+  76     ))

堆栈跟踪

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Caused by: java.lang.RuntimeException: Invalid token: :
    at clojure.lang.Util.runtimeException(Util.java:219)
    at clojure.lang.LispReader.interpretToken(LispReader.java:326)
    at clojure.lang.LispReader.read(LispReader.java:211)
    at clojure.lang.LispReader.readDelimitedList(LispReader.java:1157)
    at clojure.lang.LispReader$ListReader.invoke(LispReader.java:982)
    at clojure.lang.LispReader.readDelimitedList(LispReader.java:1148)
    at clojure.lang.LispReader$VectorReader.invoke(LispReader.java:1083)
    at clojure.lang.LispReader.readDelimitedList(LispReader.java:1148)
    at clojure.lang.LispReader$ListReader.invoke(LispReader.java:982)
    at clojure.lang.LispReader.readDelimitedList(LispReader.java:1148)
    at clojure.lang.LispReader$ListReader.invoke(LispReader.java:982)
    at clojure.lang.LispReader.read(LispReader.java:185)
    at clojure.lang.Compiler.load(Compiler.java:7060)
    ... 55 more

在下面的代码中,

1
2
3
4
5
+  72 (defn get-name [env]                                                                                    
+  73   (let [                                                                              
+  74        name (keyword(":" env) names)]                                                                                                  
+  75        println name                                                                          
+  76     ))

1
2
3
4
5
6
Caused by: java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IFn
    at nepleaks_engine.util.utility$fn__3885.invoke(utility.clj:74)
    at clojure.lang.AFn.applyToHelper(AFn.java:159)
    at clojure.lang.AFn.applyTo(AFn.java:151)
    at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:3458)
    ... 58 more

1
2
3
4
5
+  72 (defn get-name [env]                                                                                    
+  73   (let [                                                                              
+  74        name (.get names env)]                                                              
+  75        println name                                                                          
+  76     ))

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
java.lang.NullPointerException
    at nepleaks_engine.util.utility$util.invoke(utility.clj:81)
    at nepleaks_engine.core$_main.invoke(core.clj:14)
    at clojure.lang.Var.invoke(Var.java:411)
    at user$eval5$fn__7.invoke(form-init336568295343421746.clj:1)
    at user$eval5.invoke(form-init336568295343421746.clj:1)
    at clojure.lang.Compiler.eval(Compiler.java:6619)
    at clojure.lang.Compiler.eval(Compiler.java:6609)
    at clojure.lang.Compiler.load(Compiler.java:7064)
    at clojure.lang.Compiler.loadFile(Compiler.java:7020)
    at clojure.main$load_script.invoke(main.clj:294)
    at clojure.main$init_opt.invoke(main.clj:299)
    at clojure.main$initialize.invoke(main.clj:327)
    at clojure.main$null_opt.invoke(main.clj:362)
    at clojure.main$main.doInvoke(main.clj:440)
    at clojure.lang.RestFn.invoke(RestFn.java:421)
    at clojure.lang.Var.invoke(Var.java:419)
    at clojure.lang.AFn.applyToHelper(AFn.java:163)
    at clojure.lang.Var.applyTo(Var.java:532)
    at clojure.main.main(main.java:37)


(:(environment) names) 不是有效的形式。除非 environment 是一个没有参数的函数,否则将其package在括号中会出错。使用 : 创建关键字是在读取时完成的,在评估 (environment) 之前,因此您看不到前面的错误,并且阅读器尝试自行解析 :,这不是有效的输入读者。

(keyword(":" env) names) 尝试调用字符串 ":",就好像它是一个函数一样。它不是一个。间距也让我相信您希望 keyword(arg) 像在 Algol 家族语言中一样工作。它不会。正确的用法是 (keyword arg).

这是可行的,为方便起见,提供了一些等效的语法(它们都做同样的事情):

1
2
3
4
5
6
7
8
9
10
user> (def names {:production"prayag" :staging   "upd"})
#'user/names
user> (def environment"staging")
#'user/environment
user> (names (keyword environment))
"upd"
user> ((keyword environment) names)
"upd"
user> (get names (keyword environment))
"upd"