How to explain scheme expression '(a 'b) - functional-programming

'(a 'b) gives out the answer (a 'b). How does this work when there is no binding for a (which is unquoted).

This is what happens when we evaluate the expression:
'(a 'b)
=> (a 'b)
The ' quote is shorthand for the quote special form, see the linked documentation for more details:
(quote (a 'b))
=> (a 'b)
As you can see, it prevents the quoted arguments from being evaluated, so it doesn't matter if a is undefined, because a is not interpreted as a variable inside a quoted expression. It's a different thing if we tried to build a list like this:
(list a 'b)
The above will produce an error, because a is an undefined variable, whereas b is a quoted expression. This will work, though - because both elements in the list are quoted:
(list 'a 'b)
=> (a b)
And here's another way to build the list shown in the question:
(list 'a ''b)
=> (a 'b)

The quote that prefixes the list expression prevents the evaluation of the components. If you were to write, say, (list a 'b), you'd end up with a problem if there was no binding.

'something is syntactic sugar for (quote something).
So '(a 'b) is (quote (a (quote b))).
quote is not a function; it is a special form that converts the literal expression to the right into a runtime structure that looks like that expression.
Quoting a number or string literal will evaluate to the same as that literal: (quote 42) evaluates to 42
Quoting an identifier will produce a symbol: (quote apple) evaluates to the same as (string->symbol "apple")
Quoting a parenthesized form will produce a list, whose elements are the result of quoting each of the items in the parentheses: (quote (x 5 (a b))) evaluates as (list (quote x) (quote 5) (quote (a b)))
In (quote (a (quote b))), the second "quote" is not treated specially from any other identifier, because the right side of the first quote is taken literally, and none of it is evaluated as Scheme code.
So, (quote (a (quote b))) evaluates to the same as (list (string->symbol "a") (list (string->symbol "quote") (string->symbol "b"))). In other words, it's a list of 2 elements, the first of which is the symbol "a", and second of which is another list of 2 elements, the first of which is the symbol "quote", and the second of which is the symbol "b".
Then we have to get into how the Scheme REPL prints out values.
When the value is a list, it prints parentheses (( )), with recursively printed result of each of the list items inside.
When the value is a symbol, it prints the string of the symbol.
As a special exception, if it would otherwise print (quote something) (which would happen if it is printing a list of 2 elements, the first of which is the symbol "quote"), it will instead print 'something.
Therefore, the above list, which if not for the exception would be printed as (a (quote b)), will actually be printed as (a 'b).

Related

Is it valid to have NIL as an argument in the string comparison functions?

I am wondering whether or not (string= "abc" nil) is valid in Common Lisp. I noticed that SBCL does not complain even though nil is not a string. (string= '() nil) returns T although both arguments are not strings ...
(SBCL version: 2.2.2)
In Common Lisp the string comparison operators accept “string designators”. According to the Reference Manual, we have:
string designator n. a designator for a string; that is, an object that denotes a string and that is one of: a character (denoting a singleton string that has the character as its only element), a symbol (denoting the string that is its name), or a string (denoting itself).
So the operators accept symbols, and compare their names.
On the other hand, the empty list is equivalent to the symbol NIL:
nil n. the object that is at once the symbol named "NIL" in the COMMON-LISP package, the empty list, the boolean (or generalized boolean) representing false, and the name of the empty type.
So the comparison is equivalent to testing the equality of the strings "NIL" and "NIL", which is obviously true.

Correcting the regex "\[([a-zA-Z0-9_-]+)]"

The following cl-ppcre regular expression generates an error:
(ppcre:scan-to-strings "\[([a-zA-Z0-9_-]+)]" "[has-instance]")
debugger invoked on a CL-PPCRE:PPCRE-SYNTAX-ERROR in thread
#<THREAD "main thread" RUNNING {10010B0523}>:
Expected end of string. at position 16 in string "[([a-zA-Z0-9_-]+)]"
What I was expecting as return values is:
“[has-instance]”
#(“has-instance”)
in order to get at the string within the brackets. Can someone provide a regex correction? Thanks.
The escape character (backslash) only escapes itself and double quotes (§2.4.5 Double-Quote):
If a single escape character is seen, the single escape character is discarded, the next character is accumulated, and accumulation continues.
That means that:
"\[([a-zA-Z0-9_-]+)]"
is parsed the same as the following, where backslash is not present:
"[([a-zA-Z0-9_-]+)]"
The PCRE syntax implemented by CL-PPCRE understands the opening square bracket as a special syntax for character classes, and ends at the next closing bracket.
Thus, the above reads the following as a class:
[([a-zA-Z0-9_-]
The corresponding regex tree is:
CL-USER> (ppcre:parse-string "[([a-zA-Z0-9_-]")
(:CHAR-CLASS #\( #\[ (:RANGE #\a #\z) (:RANGE #\A #\Z) (:RANGE #\0 #\9) #\_ #\-)
Note in particular that the opening parenthesis inside it is treated literally. When the parser encounters the closing parenthesis that follows the above fragment, it interprets it as the end of a register group, but no such group was started, hence the error message at position 16 of the string.
To avoid treating the bracket as a character class, it must be preceded by a literal backslash in the string, as you tried to do, but in order to do so you must write two backslash characters:
CL-USER> (ppcre:parse-string "\\[([a-zA-Z0-9_-]+)]")
(:SEQUENCE #\[
(:REGISTER
(:GREEDY-REPETITION 1 NIL
(:CHAR-CLASS (:RANGE #\a #\z) (:RANGE #\A #\Z) (:RANGE #\0 #\9) #\_ #\-)))
#\])
The closing square brackets needs no backslash.
I encourage you to write regular expressions in Lisp using the tree form, with :regex terms when it improves clarity: it avoids having to deal with the kind of problems that escaping brings. For example:
CL-USER> (ppcre:scan-to-strings
'(:sequence "[" (:register (:regex "[a-zA-Z0-9_-]+")) "]")
"[has-instance]")
"[has-instance]"
#("has-instance")
Double escape the square brackets.
You forgot to (double) escape the closing bracket, too.
(cl-ppcre:scan-to-strings "\\[([a-zA-Z0-9_-]+)\\]" "[has-instance]")
;; "[has-instance]" ;
;; #("has-instance")
For those who are new to common lisp, you import cl-ppcre using quicklisp:
(load "~/quicklisp/setup.list") ;; adjust path to where you installed your quicklisp
(ql:quickload :cl-ppcre)

auto-generate key for hash table in common lisp

I would like to generate sequential keys that I can use across a number of hash tables. I will call them 'id1','id2' etc. If ht is my hash table then I would like to make symbols from strings as keys. To add an entry to the hash table I want to so something like:
(setf (gethash (make-symbol "id1") ht) 1)
And then access it again with
(gethash 'id1 ht)
I don't think make-symbol is giving me what I want, and the key 'id1' sn't recognised.
What is the best way to make this key?
Error: symbol should be in a package and needs the correct case
In your case we have:
CL-USER 24 > (symbol-name (make-symbol "id0"))
"id0"
CL-USER 25 > (symbol-package (make-symbol "id0"))
NIL
Make sure that you think about the following:
intern the symbol in a package
intern the symbol in the correct package
make sure the symbol has the correct name with the correct case
write symbols with the case you intend to use, possibly you need to escape the symbol to preserve the case
Examples:
uppercased symbol and lowercase symbol name -> not eq
CL-USER 26 > (eq 'id0 (intern "id0" "CL-USER"))
NIL
uppercased symbol and uppercase symbol name -> is eq
CL-USER 27 > (eq 'id0 (intern "ID0" "CL-USER"))
T
an escaped&lowercase symbol and a lowercase symbol name -> is eq
CL-USER 28 > (eq '|id0| (intern "id0" "CL-USER"))
T
make-symbol creates uninterned symbols. It means you will have a unique symbol every time. To get an interned symbol use intern instead.

Left-aligned zero-padding

There's a format directive to zero-pad digits.
cl-user> (format nil "~12,'0d" 27)
"000000000027"
and there's a similar-ish directive to left-align strings while padding them
cl-user> (format nil "~12#<~d~>" 27)
"27 "
Is there a way to do both? That is:
cl-user> (format nil "~12,something,d" 27)
"270000000000"
The naive "~12,'0#<~d~>" does not seem to do what I want here.
cl-user> (format nil "~12,'0#<~d~>" 27)
"27 "
You're close with the last example, but you need some more commas, because tilde less-than takes four arguments, and the pad char is the fourth arguments, but you're passing it as the second. Just pass it as the fourth:
CL-USER> (format nil "~12,,,'0#<~d~>" 27)
"270000000000"
As an aside, it was pointed out in the comments that right padding changes the value that that doesn't seem like a useful operation. I'd say that it can be a useful operation. It might depend on whether these are integers or strings where the values happen to be digit characters. I've seen maintenance systems where upgrades have changed field width and the procedure for migrating old records is to right pad with 0's. The right padding was precisely because it changes the value. 000027 (six chars) can be written as 27, which isn't six chars wide, and 000027 could also be accidentally read (probably by machine, when a programmer isn't careful) as an octal. 270000, on the other hand, has to be six-digits, and won't be octal, since it doesn't start with a 0
Use ~A:
(format nil "~33,,,'0A" 27)
==> "270000000000000000000000000000000"

Stuck with Prolog

I just started learning Prolog. One of the exercise wants me to write backwards/2, a predicate that is true when the second list argument is the reverse of the first list argument. And I have to use a paste predicate to write backwards.
paste([], L, L).
paste([X|L1], L2, [X|L3]) :- paste(L1,L2,L3).
I worked on it for hours but still haven't gotten the answer.
Here's what I have:
backwards([H|T], Lrev) :- paste([X|T], X, Lrev).
backwards([],[]).
Prolog lists are a very simple data structure.
An empty list is denoted by the atom [].
A non-empty list is denoted by the structure '.'/2, where the first argument is the list's head and the second argument is the list's tail, another list, empty or non-empty.
The Prolog list notation is syntactic sugar over that data structure:
[] is the empty list in both notations.
For non-empty lists,
[a] is the structure '.'(a,[]).
[a,b] is the structure '.'(a,'.'(b,[]))
[a,b,c] is the structure '.'(a,'.'(b,'.'(c,[])))
[Head|Tail] is exactly equivalent to '.'(Head,Tail).
[a|[b,c]] is exactly equivalent to [a,b,c] and to '.'(a,'.'(b,'.'(c,[])))
It is easy to see why one might prefer a little syntactic sugar.
The structure of a list then, like a classic singly linked list in more ... conventional ... languages, makes it trivial to add and remove items from the head (left) end of an existing list.
One should note that if, one at a time you remove items from one list and add items to another, you produce the first list in reverse order.
A common Prolog idiom is the use of a helper or accumulator argument that carries state through the recursion. Often this helper will be seeded with an initial value. One might also note that most recursive problems have one or two special cases and the broader general case.
Such a predicate that reverses a list might look something like this:
paste( [] , Rs , Rs ) . % Special Case: if the source list is empty, unify the accumulator with the result.
paste( [X|Xs] , T , Rs ) :- % General Case:
T1 = [X|T] , % - prepend the current list head to the temporary, creating a new temporary, and
paste(Xs,T1,Rs) % - recurse down.
.
One might note that the second clause above could be refactored for simplicity to remove the explicit creation of the new temporary:
paste( [] , Rs , Rs ) . % Special Case: if the source list is empty, unify the accumulator with the result.
paste( [X|Xs] , T , Rs ) :- % General Case:
paste(Xs,[X|T],Rs) % - prepend the current head to the temporary and recurse down.
.
Either way, this predicate REQUIRES that the temporary be seeded with an initial empty list ([]).
Calling it thusly, then:
paste( [a,b,c] , [] , R ).
produces
R = [c,b,a]
Once you have your paste/3 predicate, creating your backwards/2 predicate is simplicity itself:
backwards( L , R ) :- paste( L , [] , R ) .
This exposes another common Prolog idiom: a trivial "public" predicate that invokes a "private" worker predicate that actually does all the work.

Resources