Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Case for first character of string

I need to make a decision about a string based on the first character, and I have a method defined in this way:

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

Currently it always returns 3 even when the string starts with those characters. What am I doing wrong? Also, is there a more elegant way to implement this?

like image 683
Mantas Vidutis Avatar asked Sep 03 '25 09:09

Mantas Vidutis


1 Answers

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

(get "foo" 0) returns a char, not a string, so, if you want to use your check-first, you'll need to replace the strings with characters.

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

By the way, Clojure Library Coding Standards recommend using s as the argument name for functions requiring string input.

If you would prefer to use strings in place of chars: (str (first "foo")) or (subs "foo" 0 1) => "f"

Alternatively, one could write a case-indexed macro.

The following is a quick hack, and provides no option for a default expression:

(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)
    \+, \-, \*, \/))

I don't think I'd separate the clauses like this - it was just to keep the answer more concise.

I'd recommend extending case-indexed for default expressions if one were to use this, though. Also, check-first seems too general a name for this function; I've no better suggestions, but I'd think about changing it. (assuming it wasn't made-up for the purpose of this question.)

like image 51
MayDaniel Avatar answered Sep 05 '25 01:09

MayDaniel