common lisp format: call function with slash in name using ~/ directive - io

The format function in common lisp has a ~/name/ directive which allows you to call an arbitrary function to format a value. However, according to the docs, the name cannot have a / in it. However, #/ is a valid character in a symbol, and therefore a function name. So, is there any way to escape a #/ in a function name passed to the ~// directive?

Not really.
But you could write a function with a legal name, which calls the function, which then needs to be passed with the argument. Similar to this example:
(defun foo (&rest args)
(apply (first (second args))
(first args)
(second (second args))
(cddr args)))
CL-USER 52 > (defun ba/r (&rest args) (print args))
BA/R
CL-USER 53 > (format t "~/foo/" '(ba/r (1 2)))
(#<LW-XP::XP-STRUCTURE 41C00D8B1B> (1 2) NIL NIL)
NIL

22.3.5.4 Tilde Slash: Call Function
~/name/
User defined functions can be called from within a format string by
using the directive ~/name/. The colon modifier, the at-sign modifier,
and arbitrarily many parameters can be specified with the ~/name/
directive. name can be any arbitrary string that does not contain a
"/". All of the characters in name are treated as if they were upper
case. If name contains a single colon (:) or double colon (::), then
everything up to but not including the first ":" or "::" is taken to
be a string that names a package. Everything after the first ":" or
"::" (if any) is taken to be a string that names a symbol. The
function corresponding to a ~/name/ directive is obtained by looking
up the symbol that has the indicated name in the indicated package. If
name does not contain a ":" or "::", then the whole name string is
looked up in the COMMON-LISP-USER package.
There are lots of symbols that you won't be able to call using the tilde-slash directive; symbols containing a #\/ are just one kind. Others are those with colons in their names, or that have lower case letters.

Related

Convert string to title case - Emacs Lisp

I am looking for an elisp function that accepts a string and returns the same in title case (i.e., all words capitalized, except for "a", "an", "on", "the", etc.).
I found this script, which requires a marked region.
Only, I need a function that accepts a string variable, so I can use it with replace-regex. I would love to see a version of the above script that can accept either or...
Something like this?
(progn
(defun title-case (input) ""
(let* (
(words (split-string input))
(first (pop words))
(last (car(last words)))
(do-not-capitalize '("the" "of" "from" "and" "yet"))) ; etc
(concat (capitalize first)
" "
(mapconcat (lambda (w)
(if (not(member (downcase w) do-not-capitalize))
(capitalize w)(downcase w)))
(butlast words) " ")
" " (capitalize last))))
(title-case "the presentation of this HEADING OF my own from my keyboard and yet\n"))
I'd say that the script you linked to does a good job at title casing. You can use it as-is.
That leaves us with two more questions:
How can we make it accept a string?
How can we write a function which accepts both a string or a (marked) region?
Working with strings in Emacs is idiomatically done in temporary buffers which are not displayed. You could write a wrapper like this:
(defun title-capitalization-string (s)
(with-temp-buffer
(erase-buffer)
(insert s)
(title-capitalization (point-min)
(point-max))
(buffer-substring-no-properties (point-min)
(point-max))))
Now, for a function which magically does what you mean, consider something like this:
(defun title-capitalization-dwim (&optional arg)
(interactive)
(cond
(arg
(title-capitalization-string arg))
((use-region-p)
(title-capitalization-string
(buffer-substring-no-properties (region-beginning)
(region-end))))
(t
(title-capitalization-string
(buffer-substring-no-properties (point-at-bol)
(point-at-eol))))))
It accepts an optional argument, or an active region or falls back to the text on the current line. Note that this function is not really useful when used interactively, because it doesn't show any effects. Hat tip also to https://www.emacswiki.org/emacs/titlecase.el
License
I put all this code under the Apache License 2.0 and the GPL 2.0 (or later at your option) in addition to the site's default license.
Use M-x
upcase-initials-region is an interactive built-in function in ‘C
source code’.
(upcase-initials-region BEG END)
Upcase the initial of each word in the region. This means that each
word’s first character is converted to either title case or upper
case, and the rest are left unchanged. In programs, give two
arguments, the starting and ending character positions to operate on.

Search function in lisp

How can i retrieve a list of items (string) which contain a specific word from another list. Here is an Example :
(setq l '("word1_jj" "word2_mm" "word3_jj" "word4_kk"))
I wanna extract all string in which figure "_jj.
You should make ends-with-p that takes the word and an ending. To do that you find out how many characters there is in the two strings and use subseq to make a string consisting of the last letters of the word. You can use equal to check it with the supplied argument it should match.
When you have that you can do this:
(remove-if-not (lambda (x) (ends-with-p x "_jj"))
'("word1_jj" "word2_mm" "word3_jj" "word4_kk"))
; ==> ("word1_jj" "word3_jj")
Alternatively you could make a make-end-predicate that returns a lambda that takes a word:
(remove-if-not (make-end-predicate "_jj")
'("word1_jj" "word2_mm" "word3_jj" "word4_kk"))
; ==> ("word1_jj" "word3_jj")

String.format and gsub in Lua

function string:split(sep)
local sep, fields = sep or ":", {}
local pattern = string.format("([^%s]+)", sep)
self:gsub(pattern,function (c)fields[#fields + 1] = c end)
print(c)
return fields
end
I have above block of code.
string.format function has separator as its second argument. Why is that? We generally have the blob of text as second argument which needs to be formatted.
gsub function usually replace a given pattern. what is he role of function(c) in gsub? How is it being called and used here? Where is c coming from in function(c) ?
In the example code, the format specifier of string.format() is "([^%s]+)", in which %s expects a string, thus the second argument sep is a string.
For instance, if sep has a value of ",", then pattern becomes ([^,]+) (one or more occurrences of non-commas), which means the function string:split is splitting strings by commas (,)
string.gsub() can take three types as the second argument, a string, a function, or a table. When it's a function, it is called every time a match occurs, with all captured substrings passed as arguments, in order. For more details, see string.gsub().

String length in Scheme

I am not able to understand the error with the code below which simply prints the length of the string:
(define codeLen (read))
(display codeLen)
(define code (read))
(display code)
(string-length code)
I am getting an error: string-length: expects argument of type <string>; given a
You've probably entered a. read reads an arbitrary piece of s-expression, and in this case, it reads the symbol a. If you enter "a" instead, you will get a string.
But more likely you will want to use the read-line function.

Call function based on a string

I am passing in command line arguments to my Lisp program and they are formatted like this when they hit my main function:
("1 1 1" "dot" "2 2 2")
I have a dot function (which takes two vectors as arguments) and would like to call it directly from the argument, but this isn't possible because something like (funcall (second args)...) receives "dot" and not dot as the function name.
I tried variations of this function:
(defun remove-quotes (s)
(setf (aref s 0) '""))
to no avail, before realizing that the quotes were not really a part of the string. Is there a simple way to do this, or should I just check each string and then call the appropriate function?
"1 1 1" is a string of five characters: 1, space, 1, space and 1. The double quotes are not part of the string.
("1 1 1" "dot" "2 2 2") is a list of three strings.
There are no " characters above. The " are used to delimit strings in s-expressions.
If you have a dot function you need to tell us what kind of input data it expects.
Does it expect two lists of numbers? Then you have to convert the string "1 1 1" into a list of numbers.
(with-input-from-string (in "1 1 1")
(loop for data = (read in nil in)
until (eq data in)
collect data)))
To get the function DOT from the string "dot" first find the symbol DOT and then get its symbol function.
(symbol-function (find-symbol (string-upcase "dot")))
For find-symbol one might need to specify also the package, if there is a special package where the symbol is in.
Converting a list to a vector then is the next building block.
So you need to convert the arguments for your function to vectors (probably first converting them to lists as I showed above). Then you need to find the function (see above). If you have then the function and the arguments, then you can call the function using FUNCALL or APPLY (whatever is more convenient).
The question is a bit unclear, but as far as I understand it you want, when given the list ("1 1 1" "dot" "2 2 2") as input to evaluate the expression (dot "1 1 1" "2 2 2"). In that case you can do this:
(defun apply-infix (arg1 f arg2)
(apply (intern (string-upcase f)) (list arg1 arg2)))
(defun apply-list-infix (lst)
(apply 'apply-infix lst))
(apply-list-infix '("1 1 1" "dot" "2 2 2"))
funcall does not accept a string as a function designator. You need to give it a symbol instead. What you probably want to do is:
Convert the string to upper case (Lisp symbols are usually upper case, and even though it may look like Lisp is case-insensitive, that's just because the reader upcases all symbols it reads by default) (string-upcase).
Create or find a symbol with the given name (intern). Note that, if *package* is not set according to the package your function's name lives in, you need to supply the package name as the second argument to intern.
For instance (for a function named dot in package cl-user:
(funcall (intern (string-upcase "dot") 'cl-user) ...)

Resources