5

I'd like to be able to set case from a single quote, but that does not seem possible.

(format nil "The value is: ~a" 'foo)
"The value is: FOO"

(format nil "The value is: ~a" 'FOO)
"The value is: FOO"

(format nil "The value is: ~a" "Foo")
"The value is: Foo"
Tunaki
  • 132,869
  • 46
  • 340
  • 423
Jiminion
  • 5,080
  • 1
  • 31
  • 54

5 Answers5

14

Quoting

The quote has nothing to do with case. A quote prevents evaluation.

quoting a symbol:

CL-USER 1 > 'foo
FOO

quoting a list:

CL-USER 2 > '(1 2 3 foo)
(1 2 3 FOO)

You can put a quote in front of many things. For example in front of a string:

CL-USER 3 > '"a b c"
"a b c"

Since strings evaluate to themselves, quoting them or not makes no difference:

CL-USER 4 > "a b c"
"a b c"

Symbols are by default read as uppercase:

CL-USER 5 > 'FooBar
FOOBAR

CL-USER 6 > (symbol-name 'FooBar)
"FOOBAR"

But that has nothing to do with quoting and is a feature of the reader.

CL-USER 7 > (read-from-string "foo")
FOO
3

Downcase

If you want the string in lowercase, you need to convert the string to lowercase:

CL-USER 8 > (string-downcase (symbol-name 'FooBar))
"foobar"

Symbols with mixed case

But you can create symbols with lowercase names or mixed case. You need to escape them:

CL-USER 9 > '|This is a symbol With spaces and mixed case|
|This is a symbol With spaces and mixed case|

CL-USER 10 > 'F\o\oB\a\r
|FooBar|

Downcasing output using FORMAT

You can also tell FORMAT to print in lowercase:

CL-USER 11 > (format nil "The value is: ~(~a~)" 'foo) 
"The value is: foo"
Rainer Joswig
  • 136,269
  • 10
  • 221
  • 346
  • Thanks for the answer! Very helpful. – Jiminion Aug 11 '15 at 14:22
  • So it is bad for code to use 'value is a string? I think I am running into that in a few places. – Jiminion Aug 11 '15 at 14:25
  • 1
    @Jiminion: can you explain what you mean with your question? I'm not sure I understand what you are asking. – Rainer Joswig Aug 11 '15 at 14:30
  • I have seen code that uses 'int for example. "int" has no context as a symbol and is purely used as a string. So I am wondering if better style would be to use double-quotes "int" for items which are purely used as strings, and do not represent an unevaluated symbol (meta-code). – Jiminion Aug 11 '15 at 14:51
  • @Jiminion: often symbols can be entered unquoted. '(int char byte) vs. '("int" "char" "byte") . Also symbols can be compared for equality faster: eq vs. string-equal . Symbols are interned, so can save space sometimes. – Rainer Joswig Aug 11 '15 at 14:56
  • 1
    `'int` is a symbol. It takes less space because it's interned, while a string isn't necessarily so. Comparing symbols is as fast as comparing pointers; while comparing strings involves O(n) in the worst case. Symbols are mostly internal: you use them where you'd use magic numbers or constants in other languages; they're not meant to be printed, usually. Is there any reason to prefer a string over a symbol? What do you expect to gain? – Tordek Aug 11 '15 at 14:59
  • Last addition to your answer was very useful. I guess I am thinking of a lisp symbol as a variable (in other programming languages) and just using the symbol's name to hold a string seems a bit odd. – Jiminion Aug 11 '15 at 15:03
  • 2
    The last part would also work for all data types. In [Practical Common Lisp :: A few format recipes](http://www.gigamonkeys.com/book/a-few-format-recipes.html) there are additional 3 other variations on case fixing. (search for "fox" on the page) – Sylwester Aug 11 '15 at 15:51
  • @tordek: 'int is a not a symbol. It's a list with two elements: QUOTE and INT. ;-) – Rainer Joswig Aug 11 '15 at 15:59
1

'foo means "suppress the evaluation of the symbol FOO, leaving only the symbol FOO". Common Lisp tends towards upcasing symbol names by default (so the symbols expressed as 'foo, 'Foo and 'FOO are all the same symbol, with the symbol name "FOO").

To see exactly what your implementation will do, you can check the readtable case of the current readtable see CLHS, ch 23.1.2, effect of readtable case by calling (readtabe-case *readtable*).

Some lisp implementations will start with the readtable-case as :preserve.

As for if you should use symbols or strings, it's one of those "it depends". If you're not worried about cse preservation, using interned symbols gives you less storage and quicker comparison, at the (possible) price of case-mangling. But if case is important, the balance is probably further towards the "use strings throughout" end of the scale.

Vatine
  • 20,782
  • 4
  • 54
  • 70
  • That seems to sound like pre-optimization, which seems to be frowned upon by many in Stack Overflow. – Jiminion Aug 12 '15 at 14:07
  • Think of it, rather, as semantic over presentation. A symbol is a "value," like a constant or an `enum` field. A string is (more often) a presentation form. The symbol happens to have a legible representation that is easier for a programmer to understand than, say, `#xff4023b5` or so, but it is, itself, an unique value that can be quickly compared, but has no (useful) arithmètic value. – BRPocock Aug 12 '15 at 14:52
1

For understanding what's going on, see Rainer Joswigs answer. Just one thing to add: You can control the case of a printed symbol (without vertical bar syntax) with *print-case*:

CL-USER 1 > (let ((*print-case* :downcase))
              (format nil "The value is: ~a" 'foo))
"The value is: foo"

CL-USER 2 > (let ((*print-case* :capitalize))
              (format nil "The value is: ~a" 'foo))
"The value is: Foo"

CL-USER 3 > (let ((*print-case* :upcase)) ; default
              (format nil "The value is: ~a" 'foo))
"The value is: FOO"
Frank Zalkow
  • 3,850
  • 1
  • 22
  • 23
  • Does the value of *print-case* revert to its old value after these calls? – Jiminion Aug 12 '15 at 14:08
  • 1
    Yes, `*print-case*` is temporarily redefined by rebinding it with `LET`. If you want to change it permanently, you can set the value of the global variable by `(setf *print-case* :downcase)`. – Frank Zalkow Aug 12 '15 at 14:15
0

Lisp symbols, like 'a, are case insensitive. You can check that by doing...

(eq 'a 'A)

They are the same symbol.

If you need to differentiate case, you should use strings or characters, as appropriate.

In order to make format print symbols in a particular case, you can set the *print-case* global variable to :upcase, :downcase or :capitalize depending on your needs.

Tordek
  • 10,628
  • 3
  • 36
  • 67
  • http://clhs.lisp.se/Body/v_pr_cas.htm You can set the `*print-case*` global to `:downcase`. – Tordek Aug 11 '15 at 13:57
  • 3
    -1 Symbols *are* case sensitive; consider `|a|` and `A`, for example. The reason `'a` is equal to `'A` is because the *reader* upcases symbol names by default. – coredump Aug 11 '15 at 15:54
-1

OK, this works:

(format nil "The value is: ~a" (string-downcase 'foo))
"The value is: foo"

Even better (from Rainer)

 (format nil "The value is: ~(~a~)" 'foo)

I am still thinking one shouldn't use 'foo instead of "foo" if the intent is to represent a string.

Jiminion
  • 5,080
  • 1
  • 31
  • 54
  • I'm using lispworks. I guess downcase is common with other lisps. – Jiminion Aug 11 '15 at 14:12
  • If you're gonna do a self-answer, which is totally fine and even encouraged on this site, try to make it a little more informative and not just "oh here is how I got my solution to work for just me". What did you *learn* from this? –  Aug 11 '15 at 17:14