I'm currently trying to get an output of ... \hline in GNU Common lisp 2.49, but I can't get the format to work. This is what I've tried so far to get a single backslash:
(format nil "\ ") => " "
(format nil "\\ ") => "\\ "
(format nil "\\\ ") => "\\ "
I thought that the double backslash would make it work, why isn't the backslash escaping just the other backslash?
See for example:
CL-USER> (write "\\" :escape nil)
\
"\\"
Here above, the first backslash is your string, printed without escaping backslashes. The returned value is the string, printed by the REPL with the standard io syntax (http://clhs.lisp.se/Body/m_w_std_.htm), which escapes strings.
So, your string contains a single backslash, but is printed in such a way that it can be read back, hence the need to escape the backslash in the output string.
Note also that calling format with NIL and a single string returns the same string.
You can inspect your strings, for example by mapping each character to its name:
(loop
for input in '("\ "
"\\ "
"\\\ ")
collect (list :input input
:characters (map 'list #'char-name input)))
This gives:
((:INPUT " " :CHARACTERS ("Space"))
(:INPUT "\\ " :CHARACTERS ("REVERSE_SOLIDUS" "Space"))
(:INPUT "\\ " :CHARACTERS ("REVERSE_SOLIDUS" "Space")))
Or, simply use inspect:
CL-USER> (inspect "\\hline")
The object is a VECTOR of length 6.
0. #\\
1. #\h
2. #\l
3. #\i
4. #\n
5. #\e
Note the difference between creating a string and actually doing output to a stream:
CL-USER 69 > (format nil "\\ ")
"\\ " ; result
CL-USER 70 > (format t "\\ ")
\ ; output
NIL ; result
CL-USER 71 > (format *standard-output* "\\ ")
\ ; output
NIL ; result
Related
Let's say I have a string s.
And this string s could contain this:
asdf-asdfasdfasf-fasdf-asdfasdfasdf
or this:
asf-asdfaf
but also this:
aasdaf
How do I count the number of dashes (-) in this string using Emacs Lisp and store this number in some variable e.g. count-of-dashes?
The following function should do it:
(defun count-chars (char str)
(let ((s (char-to-string char))
(count 0)
(start-pos -1))
(while (setq start-pos (string-search s str (+ 1 start-pos)))
(setq count (+ 1 count)))
count))
You call it like this:
(count-chars ?- "---") ==> 3
(count-chars ?- "foo-bar") ==> 1
(count-chars ?- "-foo-bar-baz") ==> 3
(count-chars ?- "foobarbaz") ==> 0
To set a variable to the number found, you just use
setq:
(setq count-of-chars (count-chars ?- "foo-bar-baz"))
Basically, we loop looking for the first dash: if we find it we remember where so that we start looking at the place just to the right of it the next time around the loop. The loop body then just counts every one we see. When we can't find any more, string-search (and the setq) returns nil and the loop exits, whereupon we return the accumulated count. See the doc string of the function string-search with C-h f string-search for the details.
Another method is more akin to the split string method of python: split-string splits a string on a separator into a list of parts. We then count the parts (the length of the list) and subtract 1: "a-b-c" is split into ("a" "b" "c") so there are three parts but only two separators.
(defun count-chars (char str)
(let ((s (char-to-string char)))
(- (length (split-string str s)) 1)))
Again, see the doc string of split-string (C-h f split-string) for all the details.
In both cases, we converted the character argument to a string argument, because both string-search in the first case and split-string in the second expect a string argument (to search for in the first case and to use as a separator in the second case - in fact, split-string can use a regular expression as a separator). Characters and strings are different data types in Emacs Lisp, so the conversion is necessary if you really want a character s the first argument of count-chars. But you could make it a string instead:
(defun count-seps (sep str)
(- (length (split-string str sep)) 1))
and then you would call it like this instead:
(count-seps "-" "abc-def-ghi-")
which is simpler and more general:
(count-seps "-;-" "abc-;-def") ==> 1
but you do have to worry about special characters in the separator string:
(count-seps "-*-" "abcd-------def") ==> 1
since the regular expression -*- matches one or more dashes so it matches all seven dashes: there is only one separator. Whether that's what you want is debatable. If you don't want it, you'd need to escape the special characters in the separator string:
(defun count-chars (sep str)
(let ((qsep (regexp-quote sep)))
(- (length (split-string str qsep)) 1)))
How do you convert a list into a string? I am trying to use parse-int to take a list of numbers and convert them to decimal, but i end up getting an error saying "The control-string must be a string, not (contents)".
I'm using format, but I'm not sure if I'm using it incorrectly.
Here's my code:
(princ "Enter a or list of hexadecimal numbers: ")
(setq numList (read-from-string (concatenate 'string "(" (read-line) ")")))
(defun hextodec(nums)
(setq numString (format "%s" nums))
(setq newNum (parse-integer numString :radix 16))
(write nums)
(princ " = ")
(write newNum)
) ;This will format the number that the user enters
(hextodec numList)
Since you're using read-from-string anyway, you can just tell Lisp's reader to read base 16 integers:
;; CLISP session
[1]> (let ((*read-base* 16)) (read-from-string "(9 A B C F 10)"))
(9 10 11 12 15 16) ;
14
read-from-string is a potential security hole if the contents of the string are untrusted input, because of the hash-dot evaluation notation.
When using the Lisp reader on untrusted data, be sure bind *read-eval* to nil.
[2]> (read-from-string "(#.(+ 2 2))")
(4) ;
11
Note how the #. notation causes the + function specified in the string data to be executed. That could be any function, such as something that whacks files in your filesystem, or sends sensitive data to a remote server.
Format's first argument is the stream to print to. You seem to intend to return the string instead of printing, so you should put nil there: (format nil "~s" nums)
The format control string "%s" does not contain any format directives. The entire format form does not make much sense here, as you seem to intend to loop over the given nums instead. You should employ some looping construct for that, e. g. loop, do, map, mapcar ….
This question is about sbcl -- or so I thought originally. The question: When is a character not a character? Consider the following code:
(defconstant +asc-lf+ #\Newline)
(defconstant +asc-space+ #\Space)
(prin1 (type-of #\Newline )) (terpri)
(prin1 (type-of #\Space )) (terpri)
(prin1 (type-of +asc-lf+ )) (terpri)
(prin1 (type-of +asc-space+)) (terpri)
As expected, it produces:
STANDARD-CHAR
STANDARD-CHAR
STANDARD-CHAR
STANDARD-CHAR
Now consider this code:
(defun st (the-string)
(string-trim '(#\Newline #\Space) the-string))
(princ "\"")
(princ (st " abcdefgh "))
(princ "\"")
(terpri)
It produces:
"abcdefgh"
But consider this code:
(defconstant +asc-lf+ #\Newline)
(defconstant +asc-space+ #\Space)
(defun st (the-string)
(string-trim '(+asc-lf+ +asc-space+) the-string))
(princ "\"")
(princ (st " abcdefgh "))
(princ "\"")
(terpri)
When you load it using sbcl, it gives you:
While evaluating the form starting at line 6, column 0
of #P"/u/home/sbcl/experiments/type-conflict.d/2.lisp":"
debugger invoked on a TYPE-ERROR:
The value
+ASC-LF+
is not of type
CHARACTER
Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [RETRY ] Retry EVAL of current toplevel form.
1: [CONTINUE] Ignore error and continue loading file "/u/home/sbcl/experiments/type-conflict.d/2.lisp".
2: [ABORT ] Abort loading file "/u/home/sbcl/experiments/type-conflict.d/2.lisp".
3: Exit debugger, returning to top level.
((FLET SB-IMPL::TRIM-CHAR-P :IN SB-IMPL::GENERIC-STRING-TRIM) #\ )
0]
At first, I was anticipating being able to report that clisp does the appropriate call to #'string-trim, with the anticipated returned value, or maybe errors out. But it does neither of these. The function returns the same string that was passed to it, without any trimming.
Is this what should be happening? What am I missing?
EDIT approx. 2017-10-21 08:50 UTC
The fine answer by PuercoPop inspires a follow-up question. If I should post this as a separate question, just give the word and I will.
Why is it that (at least with sbcl and clisp) this:
(defconstant +asc-lf+ #\Newline)
(defconstant +asc-space+ #\Space)
(prin1 (type-of (first (list #\Newline #\Space))))
(terpri)
(prin1 (type-of (first '(#\Newline #\Space))))
(terpri)
yields this?
STANDARD-CHAR
STANDARD-CHAR
With PuercoPop's answer, I would have expected it to yield something about a symbol, not a character, for the second expression.
The main confusion comes from
the dual purpose of lists: data and code. For evaluation (+ a b) is code, here a function call. Both (quote (+ a b)) and '(+ a b) is data, as they evaluate to the quoted literal data.
reading already creates objects. #\newline is already read as a character object. It is built-in syntax: Sharpsign Backslash It is not a string, not a symbol and not some yet unknown piece of data. It is read as an object of type character (I use the wording character object for that here, one could also just say character).
These are symbols:
foo
bar
+foo+
*the-foo*
When symbols get evaluated, they evaluate to their value.
These are character objects:
#\f
#\O
#\o
#\newline
When character objects get evaluated, they evaluate to themselves.
Thus '#\foo, (quote #\foo) and #\foo evaluate all to the same object.
These are lists
(newline #\newline) ; the first item is a symbol, the second a character object
(#\a #\b #\c) ; a list of character objects
(a b c) ; a list of symbols
What happens if we evaluate lists:
(+ a b) ; the sum of the values of A and B
(list a b) ; a list gets computed, with the values of variables a and b
(list 'a 'b) ; a list gets computed, with the symbols A and B
'(a b) ; a literal list of the symbols A and B
'(#\a #\b) ; a literal list of the character objects #\a and #\b
'(a #\a) ; a literal list of the symbol A and the character object #\a
(#\a #\b) ; an error, #\a is not a function/macro/special-form
(+ a 'b) ; an error, a symbol B is not a number
Evaluating backquoted lists:
`(a ,a #\a ,#\a) ; a list of the symbol a, the value of the variable a,
; the character object a and again the character object a
Your error:
'(+asc-lf+ +asc-space+) evaluates to a list of symbols.
The function STRING-TRIM expects a sequence of characters.
You need to write something like this:
(list +asc-lf+ +asc-space+) ; calling the function list
`(,+asc-lf+ ,+asc-space+) ; a backquoted list with comma for evaluation
(vector +asc-lf+ +asc-space+) ; the constructed vector is also a sequence
Also:
(list #\Newline #\Space) and '(#\Newline #\Space) evaluate both to a list of characters. The #\ syntax is a built-in feature of the Lisp reader to construct character objects. Thus #\newline is converted at read-time into a character-object:
CL-USER 82 > (describe (read))
#\Newline ; we type the nine characters #\Newline
#\Newline is a CHARACTER
Name "Newline"
Code 10
The problem is that you are quoting the "character list". So instead of a list of characters it is a list of symbols. That is
(defun st (the-string)
(string-trim (list +asc-lf+ +asc-space+) the-string))
The error message hints at this when it says
The value
+ASC-LF+ is not of type
CHARACTER
and not
The value
#\Newline is not of type
CHARACTER
Following code from https://www.rosettacode.org/wiki/Tokenize_a_string#Common_Lisp splits a string at commas and send a list.
(defun comma-split (string)
(loop for start = 0 then (1+ finish)
for finish = (position #\, string :start start)
collecting (subseq string start finish)
until (null finish)
)
)
However, the substrings will have blank spaces around them if they are there in original string.
> (comma-split " a, b ,c , d , e")
(" a" " b " "c " " d " " e")
How can I add string-trim function to remove these spaces here. I cannot see a string variable that is being returned in the function.
I tried to have a local variable but it does not work:
(defun comma-split2 (string)
(let* ( (onestr "")
)
(loop for start = 0 then (1+ finish)
for finish = (position #\, string :start start)
(onestr (subseq string start finish))
(onestr (string-trim onestr))
collecting onestr
until (null finish)
)
))
Error on loading file:
*** - LOOP: illegal syntax near (ONESTR (SUBSEQ STRING START FINISH)) in
(LOOP FOR START = 0 THEN (1+ FINISH) FOR FINISH = (POSITION #\, STRING :START START) (ONESTR (SUBSEQ STRING START FINISH))
(ONESTR (STRING-TRIM ONESTR)) COLLECTING ONESTR UNTIL (NULL FINISH))
The following restarts are available:
Even trimming the outlist in a second function is not working:
(defun comma-split2 (string)
(let ( (outlist (list))
(setf outlist (comma-split string))
(dolist (str outlist)
(push (string-trim str) outlist)
)
(nreverse outlist)
)))
> (comma-split2 " a, b ,c , d , e")
*** - LET: illegal variable specification (SETF OUTLIST (COMMA-SPLIT STRING))
The following restarts are available:
The COLLECTING-statement is what is creating the list. So you need to put the call to STRING-TRIM around what is being collected.
(defun comma-split (string)
(loop for start = 0 then (1+ finish)
for finish = (position #\, string :start start)
collecting (string-trim " " (subseq string start finish))
until (null finish)))
You shouldn't put the closing parentheses on their own line.
Without proper indenting Lisp code you won't get very far.
Don't:
(defun foo (a)
(let ((b )
b
))
)
Write
(defun foo (a)
(let (b)
b))
Additionally: trying to write Lisp code without understanding Lisp syntax is also not a good idea.
Trying to use a complex language by googling random code, trying to randomly modify the code and then posting the error messages to Stackoverflow isn't a very promising approach.
Read one or more of the basic Lisp books:
COMMON LISP: A Gentle Introduction to Symbolic Computation
Practical Common Lisp
Use a Lisp reference: Common Lisp Hyperspec
LOOP: illegal syntax near
Read about LOOP, first.
LET: illegal variable specification
Caused by lack of indentation and violation of Lisp syntax. Check the syntax of LET.
How can I add string-trim function to remove these spaces here
How do you add functions at all?
Given this expression:
(sin 3.0)
How do you add a function to compute the square root?
Solution:
(sqrt (sin 3.0))
You call the function on the result of the the first one.
Simple as that. Why would you need additional variables?
Your code is not valid LOOP syntax.
Either you use the simple syntax, which is like a PROGN but loops, or you use LOOP keywords, in which case you need to prefix statements with DO:
(loop
for i in list
do
(print i)
(sleep 1))
You probably only need to do:
(loop for start = 0 then (1+ finish)
for finish = (position #\, string :start start)
collect (string-trim " "
(subseq string
start
finish))
until (null finish))
Alternatively, with regular expressions (see http://weitz.de/cl-ppcre/):
(ppcre:split " *, *" string)
You can use the method string-trim .
For example
(string-trim '(#\Space #\Tab #\Newline) " Test Test") => "Test Test" .
For more information you can go here.
I hope this will help you! :)
I am trying to concat strings in lisp, using clisp on linux.
I run following code:
(defun bingo ()
(strcat "Correct! You guessed " (itoa *count*) " times."))
but, get following error:
EVAL: undefined function STRCAT
EVAL: undefined function ITOA
Any suggestion?
CL-USER 1 > (format nil "This is too easy. ~a day I'll learn Lisp." 1)
"This is too easy. 1 day I'll learn Lisp."