Is there a way to change delimiters of documentation string in Common Lisp? - documentation

I sometimes put examples of function calls and their output in the documentation string of a function definition.
(defun js-[] (&rest args)
"Javascript array literal statement.
(js-[] 1 2 3)
> \"[1, 2, 3]\"
"
(format nil "[~{~A~^, ~}]" (mapcar #'js-expr args)))
But sometimes the output of the function is a string. So I have to escape the double quotes in the example output. This becomes tedious very quickly.
Is there a way to change the docstring delimiter from double quotes to something else so I don't have to keep escaping them?
Please note that sometimes it's worse than just escaping once:
(defun js-~ (str)
"Javascript string statement. This is needed so that double quotes are inserted.
(js-~ \"string\")
> \"\\\"string\\\"\"
"
(format nil "\"~A\"" str))
Here there is an additional problem. Reading the docstring is difficult.

TL;DR
Yes, you can, no, you do not want to do it.
No, CL has just one syntax for strings
The only way to represent a string in Common Lisp is to use
Double-Quote ".
Yes, you can modify the reader so that something else denotes a string
E.g., suppose you want to a string to be started and stopped by, say, #.
(This is an ordinary character rarely used in symbol names,
in contrast to % and $ which are often used in implementation-internal symbols.)
Set the properties of # from ":
(multiple-value-bind (function non-terminating-p)
(get-macro-character #\")
(set-macro-character #\# function non-terminating-p))
Now:
(read-from-string "#123#")
==> "123" ; 5
(read-from-string #"123"#)
==> "123" ; 5
Do not forget to restore the input syntax to standard Common Lisp syntax:
(setq *readtable* (copy-readtable nil))
See Reader.
You might be able to modify the printer
The standard does not require that the printing of standard objects
(such as a string) to be
used-modifiable.
You can try defining a print-object method:
(defmethod print-object ((o string) (d stream))
...)
however,
implementing this correctly is not easy
this is non-conforming code (defining a method for a standardized generic function which is applicable when all of the arguments are direct instances of standardized classes)
thus many implementations will signal errors on this code,
even if you disable package locks &c, the implementation is free to ignore your method.
No, you do not want to do that
The code exists for people to read it.
Changing Lisp syntax will make it harder for others to read your code.
It will also confuse various tools you use (editor &c).
CL has many warts, but this is not one of them ;-)
PS. See also documentation and describe, as well as comment syntax Sharpsign Vertical-Bar and Semicolon.

You could make a reader macro that slurps in a multi line string like this:
(defun hash-slash-reader (stream slash arg)
(declare (ignore slash arg))
(loop :with s := (make-string-output-stream)
:for c := (read-char stream)
:if (and (eql #\/ c) (eql #\# (peek-char nil stream)))
:do (read-char stream) (return (get-output-stream-string s))
:if (eql #\Newline c)
:do (peek-char t stream)
:do (princ c s)))
(set-dispatch-macro-character #\# #\/ #'hash-slash-reader)
Now you can do:
(defun js-~ (str)
#/ --------------------------
Javascript string statement.
This is needed so that double quotes are inserted.
(js-~ "string")
> "\"string\""
-------------------------- /#
(format nil "\"~A\"" str))
The documentation string will be added just as if you'd written it with double quotes. This is effectively the same as changing the delimiter for strings!. In fact, it is an additional way to delimit strings.
Which is why you can use it (not recommended though) in regular lisp code, and not just for documentation purposes.
Using / as the sub-character of the dispatch macro, helps keep it conceptually close to the multiline comment, but avoids being ignored by the reader altogether.

Another idea. Write your docstrings as usual, without examples.
(defun js-~ (str)
"Javascript array literal statement."
...)
Define tests. That can be as simple as:
(defparameter *tests*
'(((js-~ "string") . "\"string\"")
...))
Use that list to perform tests:
(loop for (form . expected) in *tests*
for (fn . args) = form
for actual = (apply fn args)
do (assert (equalp actual expected)))
... and to update the documentation. Be careful, this appends to the existing documentation string, so don't run it twice.
(loop for (form . expected) in *tests*
for (fn . args) = form
do (setf (documentation fn 'function)
(format nil
"~a~%~% ~S~% => ~S"
(documentation fn 'function)
form
expected)))

You can (ab)use cl-interpol. Although the purpose of the library is to enable string interpolation it also allows custom string delimiters, if you don't mind preprending the string with #?. e.j.
CL-USER> (cl-interpol:enable-interpol-syntax)
; No values
CL-USER> #?'foo'
"foo"
CL-USER> #?/foo/
"foo"
CL-USER> #?{foo}
"foo"
CL-USER>
so after enabling the interpol reader macro you could write
(defun js-[] (&rest args)
#?'Javascript array literal statement.
(js-[] 1 2 3)
> "[1, 2, 3]"
'

Related

buffer-local values for SQL query parameters

Using sql-send-buffer, I can send a SQL query from a file to an open SQL REPL. Many of my queries have parameter placeholders (in Postgres syntax, $1, $2 &c.) . Does anyone have code analogous to sql-send-buffer that will prompt for values to fill in for these parameters? Ideally, I'd like it to store the values I provide, and not prompt again unless I add parameters or close the file.
Currently I either:
replace the parameters in the file, try to remember not to commit or deploy these test values (error prone)
copy the query into the REPL, replace parameters there (tedious)
Something like this, perhaps:
(defvar my-sql-replacements nil)
(make-variable-buffer-local 'my-sql-replacements)
(defun my-sql-send-buffer-replace ()
(interactive)
(let ((string (buffer-substring-no-properties (point-min) (point-max))))
(while (string-match "[$][0-9]" string)
(let* ((placeholder (match-string 0 string))
(replacement (or (cdr (assoc placeholder my-sql-replacements))
(read-string (format "Replacement for %s: " placeholder)))))
(unless (assoc placeholder my-sql-replacements)
(push (cons placeholder replacement) my-sql-replacements))
(setq string (replace-regexp-in-string (regexp-quote placeholder) replacement string))))
(sql-send-string string)))
I haven't tested it with an actual SQL server, but from tracing sql-send-string it looks like it should work. It stores the replacements in a buffer-local variable.

Assign and print an input string to a variable. Lisp

I want my program to ask for an expression, assign an inputted string to a variable 'exp' and then print the expression.
However I am having some trouble. I first tried using (read)
(princ "Enter a expression to be evaluated.")
(setf exp (read))
(princ exp)
However when i use this code, this happens.
Hello this is an expression ;This is what I input
Enter a expression to be evaluated.HELLO
T
I then tried to use (read-line), but when I do this, I don't seem to be asked for an input at all.
(princ "Enter a expression to be evaluated.")
(setf exp (read-line))
(princ exp)
gets
Enter a expression to be evaluated.
T
The program just ends.
After some answers I have come up with this
(defun get-input (prompt)
(clear-input)
(write-string prompt)
(finish-output)
(setf exp (read-line)))
(get-input "Enter an expression: ")
(princ exp)
However when i run this the following happens
My first sentence ;My first input
Enter an expression: My second sentence ;it then asks for input, i do so
My second sentence ;my second input is printed back at me
T
This is kind of a FAQ.
Output can be buffered. Use FINISH-OUTPUT to make sure that the output has actually reached its destination.
READ reads Lisp s-expressions. It returns the corresponding data-structure. It's only useful when you enter a valid s-expression.
READ-LINE reads a line and returns a string.
Example:
*
(defun ask (&optional (message "Input: "))
(clear-input) ; get rid of pending input
(write-string message) ;
(finish-output) ; make sure output gets visible
(read-line)) ; read a line as a string
ASK
* (ask "Name: ")
Name: Rainer
"Rainer"
NIL
File p.lisp:
(defun get-input (prompt)
(clear-input)
(write-string prompt)
(finish-output)
(read-line))
(write-string (get-input "Enter a sentence: "))
(finish-output)
Output
* (load "/tmp/p.lisp")
Enter a sentence: foo is not a bar
foo is not a bar
T

how to avoid WHERE to be seen as attribute in parsing sql using haskell

I am parsing SQL in Haskell using Parsec. How can I ensure that a statement with a where clause will not treat the WHERE as a table name? Find below some part of my coding. The p_Combination works but it sees the WHERE as part of the list of attributes instead of the where clause.
--- from clause
data Table_clause = Table {table_name :: String, alias :: Maybe String} deriving Show
p_Table_clause:: Parser Table_clause
p_Table_clause = do
t <- word
skipMany (space <?> "require space at the Table clause")
a <- optionMaybe (many1 (alphaNum)) <?> "aliase for table or nothing"
return $ Table t a
newtype From_clause = From [Table_clause] deriving Show
p_From_clause :: Parser From_clause
p_From_clause = do
string "FROM" <?> "From";
skipMany1 (space <?> "space in the from clause ")
x <- sepBy p_Table_clause (many1(char ',' <|> space))
return $ From x
-- where clause conditions elements
data WhereClause = WhereFCondi String deriving Show
p_WhereClause :: Parser WhereClause
p_WhereClause = do
string "WHERE"
skipMany1 space
x <- word
return $ WhereFCondi x
data Combination = FromWhere From_clause (Maybe WhereClause) deriving Show
p_Combination :: Parser Combination
p_Combination = do
x <- p_From_clause
skipMany1 space
y <- optionMaybe p_WhereClause
return $ FromWhere x y
Normal SQL parsers have a number of reserved words, and they’re often not context-sensitive. That is, even where a where might be unambiguous, it is not allowed simply because it is reserved. I’d guess most implementations do this by first lexing the source in a conceptually separate stage from parsing the lexed tokens, but we do not need to do that with Parsec.
Usually the way we do this with Parsec is by using Text.Parsec.Token. To use it, you first create a LanguageDef defining some basic characteristics about the language you intend to parse: how comments work, the reserved words, whether it’s case sensitive or not, etc. Then you use makeTokenParser to get a record full of functions tailored to that language. For example, identifier will not match any reserved word, they are all careful to require whitespace where necessary, and when they are skipping whitespace, comments are also skipped.
If you want to stay with your current approach, using only Parsec primitives, you’ll probably want to look into notFollowedBy. This doesn’t do exactly what your code does, but it should provide some inspiration about how to use it:
string "FROM" >> many1 space
tableName <- many1 alphaNum <* many1 space
aliasName <- optionMaybe $ notFollowedBy (string "WHERE" >> many1 space)
>> many1 alphaNum <* many1 space
Essentially:
Parse a FROM, then whitespace.
Parse a table name, then whitespace.
If WHERE followed by whitespace is not next, parse an alias name then whitespace.
I guess the problem is that p_Table_clause accepts "WHERE". To fix this, check for "WHERE" and fail the parser:
p_Table_clause = do
t <- try (do w <- word
if w == "WHERE"
then unexpected "keyword WHERE"
else return w)
...
I guess there might be a try missing in sepBy p_Table_clause (many1 (char ',' <|> space)). I would try sepBy p_Table_clause (try (many1 (char ',' <|> space))).
(Or actually, I would follow the advice from the Parsec documentation and define a lexeme combinator to handle whitespace).
I don't really see the combinator you need right away, if there is one. Basically, you need p_Combination to try (string "WHERE" >> skipMany1 space) and if it succeeds, parse a WHERE "body" and be done. If it fails, try p_Table_clause, if it fails be done. If p_Table_clause succeeds, read the separator and loop. After the loop is done prepend the Table_clause to the results.
There's some other problems with your parser, too. many1 (char ',' <|> space) matches " ,,, , ,, " which is not a valid separator between tables in a from clause, for example. Also, SQL keywords are case-insensitive, IIRC.
In general, you want to exclude keywords from matching identifiers, with something like:
keyword :: Parser Keyword
keyword = string "WHERE" >> return KW_Where
<|> string "FROM" >> return KW_From
<|> string "SELECT" >> return KW_Select
identifier :: Parser String
identifier = try (keyword >> \kw -> fail $ "Expected identifier; got:" ++ show kw)
<|> (liftA2 (:) identiferStart (many identifierPart))
If two (or more) or your keywords have common prefixes, you'll want to combine them for more efficiency (less backtracking) like:
keyword :: Parser Keyword
keyword = char 'D' >> ( string "ROP" >> KW_Drop
<|> string "ELETE" >> KW_Delete
)
<|> string "INSERT" >> return KW_Insert

List all Emacs variables containing regexp

How do I find all variables containing "directory" in their name in Emacs?
M-x apropos-variable RET directory
If you simply want to find all variables containing a string, check out the correct answer. Here i created the list of pairs in the form (<variable> . <value>).
Explanation of functions used
mapatoms is a map-style function to operate on obarray, variable that contains all symbols used by Emacs.
prin1-to-string returns a string with the printed representation of an object.
string-match finds a regexp in a string, returns index or nil if not found.
push inserts element into a head of a list in-place.
remove-if is equivalent to inverted filter
mapcar is an ordinary map function
boundp returns t if variable's value is not void.
symbol-value returns value of a variable.
Final code
(let ((matching-variables
(let ((result '()))
;; result will contain only variables containing "directory"
(mapatoms (lambda (variable)
(let* ((variable-string (prin1-to-string variable))
(match (string-match "directory" variable-string)))
(if match
(push variable result)))))
result)))
;; returns list of pairs (variable-name . variable-value)
(remove-if #'null
(mapcar (lambda (variable)
(if (boundp variable)
(cons variable (symbol-value variable))
nil))
matching-variables)))
References
https://stackoverflow.com/a/8031385/596361

An efficient collect function in Common Lisp

I'm learning Lisp and have written the following function to collect a list of results.
(defun collect (func args num)
(if (= 0 num)
()
(cons (apply func args)
(collect func args (- num 1)))))
It produced similar output to the built in loop function.
CL-USER> (collect #'random '(5) 10)
(4 0 3 0 1 4 2 1 0 0)
CL-USER> (loop repeat 10 collect (random 5))
(3 3 4 0 3 2 4 0 0 0)
However my collect function blows the stack when I try to generate a list 100,000 elements long
CL-USER> (length (collect #'random '(5) 100000))
Control stack guard page temporarily disabled: proceed with caution
Whereas the loop version doesn't
CL-USER> (length (loop repeat 100000 collect (random 5)))
100000
How can I make my version more space efficient, are there alternatives to consing? I think it's tail recursive. I'm using sbcl. Any help would be great.
No, it is not tail recursive. Neither ANSI Common Lisp says anything about it nor your code:
(defun collect (func args num)
(if (= 0 num)
()
(cons (apply func args)
(collect func args (- num 1)))))
If you look at your code, there is a CONS around your call to COLLECT. This CONS receives the value of the recursive call to COLLECT. So COLLECT can't be tail recursive. It's relatively simple to rewrite your function to something that looks tail recursive by introducing an accumulator variable. The various Lisp or Scheme literature should describe that.
In Common Lisp the default way to program an iterative computation is by using one of the several iterative constructs: DO, DOTIMES, DOLIST, LOOP, MAP, MAPCAR, ...
The Common Lisp standard does not provide tail call optimization (TCO). It would have to be specified what TCO should do in the presence of several other language features. For example dynamic binding and special variables have an effect on TCO. But the Common Lisp standard says simply nothing about TCO in general and about possible effects of TCO. TCO is not a part of the ANSI Common Lisp standard.
Several Common Lisp implementations have a way to enable various tail call optimizations with compiler switches. Note that both the way to enable those and the limitations are implementation specific.
Summary: In Common Lisp use iteration constructs and not recursion.
(defun collect (func args num)
(loop repeat num
collect (apply #'func args)))
Added bonus: it is easier to read.
Common Lisp implementations are not required by the ANSI standard to do tail call optimization; however, most that worth their salt (including SBCL) do optimize.
Your function, on the other hand, is not tail recursive. It can be turned into one by using the common trick of introducing an extra parameter for accumulating the intermediate result:
(defun collect (func args num)
(labels ((frob (n acc)
(if (= 0 n)
acc
(frob (1- n) (cons (apply func args) acc)))))
(frob num nil)))
(The original parameters FUNC and ARGS are eliminated in the local function since they are constant with recpect to it).
Well, the alternative to recursion is iteration.
You should know that Common Lisp does not require tail recursion from its implementors, unlike Scheme.
(defun mycollect (func args num)
(let ((accumulator '())) ; it's a null list.
(loop for i from 1 to num
do
;;destructively cons up the accumulator with the new result + the old accumulator
(setf accumulator
(cons (apply func args) accumulator)))
accumulator)) ; and return the accumulator