2017-05-13 4 views
1

저는 Clojure에서 새로 왔고 leib 명령 줄 args에 문제가 있습니다. 내 응용 프로그램은 매우 간단합니다 :Leiningen 명령 args 구문 분석

(defn -main 
    [& args] 
    (println (apply hash-map args)) 
    (let [{:keys [f w h]} (apply hash-map args)] 
    (println f w h) 
;  (init-frame w h) 
;  (draw-values f w h) 
)) 

터미널 출력 : 나는 REPL에서 - 주요 실행하면 잘 작동

lein run :f bit-xor :w 200 :h 200 
{:w 200, :h 200, :f bit-xor} 
nil nil nil 

. core.clj 내부에 hashmap을 정의하면 잘 작동합니다.

(def my-args (hasmap :f "bit-xor" :w 200 :h 200)) 

내 'f', 'w'및 'h'가없는 이유는 무엇인지 알 수 없습니다. 누구든지 도와 줄 수 있습니까?

나는 테스트 용으로 특별한 작은 앱을 만들었습니다.

(ns cmdargs.core 
(:gen-class)) 

(defn -main 
[& args] 
(println "args: " args) 
(println "args map: " (apply hash-map args)) 
(println "param keys: " (keys (apply hash-map args))) 
(println "param vals: " (vals (apply hash-map args))) 
(let [{:keys [param1 param2]} (apply hash-map args)] 
    (println "param1: " param1) 
    (println "param2: " param2))) 

REPL 출력 :

cmdargs.core> (-main :param1 200 :param2 300) 
args: (:param1 200 :param2 300) 
args map: {:param2 300, :param1 200} 
param keys: (:param2 :param1) 
param vals: (300 200) 
param1: 200 
param2: 300 
nil 
cmdargs.core> 

터미널/lein 출력 :

cmdargs$ lein run :param1 200 :param2 300 
Java HotSpot(TM) Client VM warning: TieredCompilation is disabled in this release. 
Java HotSpot(TM) Client VM warning: TieredCompilation is disabled in this release. 
args: (:param1 200 :param2 300) 
args map: {:param1 200, :param2 300} 
param keys: (:param1 :param2) 
param vals: (200 300) 
param1: nil 
param2: nil 
+0

이 오타입니다''(... 내-인수를 defn이)? 대신에 'def'여야합니다 – Shlomi

+0

Thanks @Shlomi! 나는 고쳤다. 하지만 (def my-args ...) 'let'에서 구조 조정 작업을 확인하기 위해 정의 된 것입니다. – tkircsi

답변

1

:keys 키워드 만 작동 destructuring, 그리고 당신이 생각하는 어떤 키워드 -main을 통해 들어오는 실제로는 키워드가 아니라 문자열이며 각각은 콜론으로 시작합니다. .

: : 함수에서 제공되는 매개 변수에 대한 type이 사용을 확인하려면 https://clojure.org/guides/destructuring에서

을 나는이 인용 발견 키를 키 키워드 키 연관 값입니다

당신이 만약 들어오는 인수를 키워드로 변환해야합니다. keyword :

(keyword (subs ":f" 1)) 
(map (comp keyword #(subs % 1)) [":f" ":w" ":h"]) 

을 대신 [":f" ":w" ":h"] 당신은 args있을 것입니다 :3210 그래서 귀하의 경우이 같은 그것을 할 수 있습니다.

물론 Clojure 리더 외부에서 의미가없는 콜론을 생략하기로 결정한 경우 조금 더 간단 해집니다. https://clojure.org/reference/reader.

+0

감사! REPL과 Lein이 'args'를 차별적으로 해석한다는 것은 다소 혼란 스러웠습니다. – tkircsi

+0

예. 우리가 REPL에있을 때 우리는 Clojure Reader에 있다고 생각합니다. 반면에 명령 행 인수가 문자열로만 갈 수 있다는 것은 그다지 놀라운 일이 아닙니다. –

0

감사! REPL과 Lein이 'args'를 차별적으로 해석한다는 것은 다소 혼란 스러웠습니다. '자바에 Lein

lein run :param1 200

clojure.lang.Keyword

으로 만에

-main :param1 200

에서'PARAM1를 '

REPL 해석. 랭.String '.

나는 다음을 시도했다 : 대신에 : keys 대신에 : keys하지만 콜론을 잊었다. 이것은 작동 중입니다 :

(defn -main 
[& args] 
(let [{:strs [:param1 :param2]} (apply hash-map args)] 
(println "param1: " param1) 
(println "param2: " param2))) 

물론이 경우에는 param 이름 앞에 콜론이 아무 의미도 없습니다.

의 경우 : 키 내가했던 다음

(defn -main 
    [& args] 

    (let [{:keys [param1 param2]} 
    (into {} (for [[k v] (apply hash-map args)] 
        [(keyword (apply str (rest k))) v]))] 
    (println "param1: " param1) 
    (println "param2: " param2))) 
+0

또한 Lein은 커맨드 라인에서'java'를 호출하는 것과는 다른 큰 일을하지 않습니다. –

+0

아니요. 당신 말이 맞아요. 'lang'은 'L'대신에 작은 'l'입니다. java.lang.String 및 cojure.lang.Keyword가 올바른 것입니다. – tkircsi