2010-09-24 7 views
3

je dois prendre une décision sur une chaîne basée sur le premier caractère, et j'ai une méthode définie ainsi:cas pour le premier caractère de la chaîne

(defn check-first [string] 
    (case (get string 0) 
    "+" 1 
    "-" 2 
    3 
    )) 

Actuellement, il revient toujours 3 même lorsque la chaîne commence avec ces caractères. Qu'est-ce que je fais mal? Aussi, existe-t-il un moyen plus élégant de mettre en œuvre cela?

Répondre

9
(get "foo" 0) 
;; => \f 

(get "foo" 0) retourne un char, pas un string, donc, si vous voulez utiliser votre check-first, vous devrez remplacer les chaînes de caractères.

(defn check-first [s] 
    (case (first s) \+ 1, \- 2, 3)) 

Par ailleurs, Clojure Library Coding Standards recommandons l'utilisation de s comme nom d'argument pour les fonctions nécessitant l'entrée de chaîne.

Si vous préférez utiliser des chaînes de caractères en place: (str (first "foo")) ou (subs "foo" 0 1)=> "f"

Alternativement, on pourrait écrire un case-indexed macro.

Voici un hack rapide et ne fournit aucune option pour une expression par défaut:

(defmacro case-indexed [expr & clauses] 
    (list* 'case expr (interleave clauses (iterate inc 1)))) 

;; (case-indexed "foo" "bar" "baz" "foo") => 3 
;; (case-indexed (+ 5 1) 3 4 5 6 7) => 4 

(defn check-first [s] 
    (case-indexed (first s) 
    \+, \-, \*, \/)) 

Je ne pense pas que je séparer les clauses de ce genre - il était juste de garder la réponse plus concise .

Je recommanderais d'étendre case-indexed pour les expressions par défaut si l'une d'entre elles devait être utilisée. En outre, check-first semble un nom trop général pour cette fonction; Je n'ai pas de meilleures suggestions, mais je penserais à le changer. (En supposant qu'il n'a pas été maquillée aux fins de cette question.)

-3

Vouliez-vous utiliser cond?

http://clojure-notes.rubylearning.org/

(def x 10) 
(cond 
(< x 0) (println "Negative!") 
(= x 0) (println "Zero!")) 
; => nil 

(cond 
(< x 0) (println "Negative!") 
(= x 0) (println "Zero!") 
:default (println "Positive!")) 
; => Positive! 
+0

Non, 1) l'OP a une chaîne, pas un 2) numérique est plus approprié pour les ensembles finis comme celui-ci. –

2

Vous pouvez garder ce que vous avez et utilisez la méthode substring de Java dans votre cas état:

(defn check-first [s] 
    (case (.substring s 0 1) 
    "+" 1 
    "-" 2 
    3)) 

Edit: Il suffit de noter que MayDaniel avait déjà mentionné subs, qui fonctionne de la même manière que .substring. Désolé, il est tôt ici ...

Questions connexes