I am having a hard time reading/understanding the syntax of the pcase statement in emacs-lisp. Please help me figure out how to make the following a valid pcase statement.
(defun execute-play (str)
(setq parse (mapcar (lambda (s) (split-string s ":")) (split-string str " ")))
(pcase (string-to-char (caar parse))``
((pred (<= (string-to-char "5"))) (t-to-pparse))
((pred (<= (string-to-char "d"))) (f-to-p parse))
((string-to-char "w") (w-to-p parse))
(_ "bad input")))
Note that typical input is "1:2 3" or "a 5".
The error from emacs that I get is: 'edebug-signal: Unknown upattern '(string-to-char w)'
This is the second to last case, -- I thought that this would just match the value of (caar parse) against (string-to-char "w") if it did not already match a case before this. Note that I also tried replacing (string-to-char "w") with (SELFQUOTING (string-to-char "w")) since the documentation says that: SELFQUOTING matches itself. This includes keywords, numbers, and strings.
Please help me get this emacs-lisp pcase statement working -- Thanks for all the help!
There are multiple issues with your code:
Since you're not doing any binding or deconstruction in your patterns, you don't need pcase — the conditional is better written using cond.
You have a spurious pair of backquotes at the end of line 3.
You appear to have inverted the first two tests — the first clause will match if the expression is larger than ?5, so the remaining clauses will never match.
pcase doesn't seem to support matching against evaluated values, so third clause should be written (pred (equal (string-to-char "0"))).
Related
I have a list of elements following
("(aviyon" "213" "flyingman" "no))") as list
What i want is that I want to split this list containing strings using parentheses as splitter but also want to include these parentheses in a new list without breaking the order
My desired output of new list(or same list modified)
("(" "aviyon" "213" "flyingman" "no" ")" ")")
I am coming from imperative languages and this would be 15 minute job in Java or C++. But here i'm stuck what to do. I know i have to
1- Get a element from list in a loop
I think this is done with (nth 1 '(listname) )
2- separate without removing delimiter put in to a new list
I found functions such as SPLIT-SEQUENCE but i can't do without removing it and without breaking original order.
Any help would be appreciated.
You can use cl-ppcre library to do the job.
For example:
CL-USER> (ql:quickload :cl-ppcre)
CL-USER> (cl-ppcre:split "([\\(\\)])" "(aviyon" :with-registers-p t)
("" "(" "aviyon")
CL-USER> (cl-ppcre:split "([\\(\\)])" "no))" :with-registers-p t)
("no" ")" "" ")")
CL-USER>
However, it makes empty-strings in a list. Use remove-if function to get rid of them:
CL-USER> (defun empty-string-p (s) (string= s ""))
EMPTY-STRING-P
CL-USER> (remove-if 'empty-string-p
(list "no" ")" "" ")"))
("no" ")" ")")
Finally, you can construct a function which does both, and run it in an imperative loop (yes, Common Lisp is not functional as many think):
CL-USER> (defun remove-empty-strings (l)
(remove-if 'empty-string-p l))
REMOVE-EMPTY-STRINGS
CL-USER> (defun split (s)
(cl-ppcre:split "([\\(\\)])"
s
:with-registers-p t))
SPLIT
CL-USER> (defparameter *the-list* '("(aviyon" "213" "flyingman" "no))"))
*THE-LIST*
CL-USER> (loop for item in *the-list*
for splitted = (split item)
for cleaned = (remove-empty-strings splitted)
append cleaned)
("(" "aviyon" "213" "flyingman" "no" ")" ")")
Let's have another answer, without external libraries.
Like you already did, we can split in the problem into smaller parts:
define a function which builds a list of tokens from a string, all-tokens
apply this function on all strings in your input list, and concatenate the result:
(mapcan #'all-tokens strings)
The first part, taking a state and building a list from it, looks like an unfold operation (anamorphism).
Fold (catamorphism), called reduce in Lisp, builds a value from a list of values and a function (and optionally an initial value).
The dual operation, unfold, takes a value (the state), a function, and generate a list of values.
In the case of unfold, the step function accepts a state and returns new state along with the resulting list.
Here, let's define a state as 3 values: a string, a starting position in the string, and a stack of tokens parsed so far.
Our step function next-token returns the next state.
;; definition follows below
(declare (ftype function next-token))
The main function which gets all tokens from a string just computes a fixpoint:
(defun all-tokens (string)
(do (;; initial start value is 0
(start 0)
;; initial token stack is nil
(tokens))
;; loop until start is nil, then return the reverse of tokens
((not start) (nreverse tokens))
;; advance state
(multiple-value-setq (string start tokens)
(next-token string start tokens))))
We need an auxiliary function:
(defun parenthesisp (c)
(find c "()"))
The step function is defined as follows:
(defun next-token (string start token-stack)
(let ((search (position-if #'parenthesisp string :start start)))
(typecase search
(number
;; token from start to parenthesis
(when (> search start)
(push (subseq string start search) token-stack))
;; parenthesis
(push (subseq string search (1+ search)) token-stack)
;; next state
(values string (1+ search) token-stack))
(null
;; token from start to end of string
(when (< start (1- (length string)))
(push (subseq string start) token-stack))
;; next-state
(values string nil token-stack)))))
You can try with a single string:
(next-token "(aviyon" 0 nil)
"(aviyon"
1
("(")
If you take the resulting state values and reuse them, you have:
(next-token "(aviyon" 1 '("("))
"(aviyon"
NIL
("aviyon" "(")
And here, the second return value is NIL, which ends the generation process.
Finally, you can do:
(mapcan #'all-tokens '("(aviyon" "213" "flyingman" "no))"))
Which gives:
("(" "aviyon" "213" "flyingman" "no" ")" ")")
The above code is not fully generic in the sense that all-tokens knows too much about next-token: you could rewrite it to take any kind of state.
You could also handle sequences of strings using the same mechanism, by keeping more information in your state variable.
Also, in a real lexer you would not want to reverse the whole list of tokens, you would use a queue to feed a parser.
solution
Since you didn't understood Alexander's solution and since I anyway wrote my solution:
;; load two essential libraries for any common lisper
(ql:quickload :cl-ppcre)
(ql:quickload :alexandria)
;; see below to see how to install quicklisp for `ql:quickload` command
;; it is kind of pythons `import` and if not install `pip install`
;; in one command for common-lisp
(defun remove-empty-string (string-list)
(remove-if #'(lambda (x) (string= x "")) string-list))
(defun split-parantheses-and-preserve-them (strings-list)
(remove-empty-string
(alexandria:flatten
(mapcar #'(lambda (el) (cl-ppcre:split "(\\(|\\))"
el
:with-registers-p t))
strings-list))))
;; so now your example
(defparameter *list* '("(aviyon" "213" "flyingman" "no))"))
(split-parantheses-and-preserve-them *list*)
;; returns:
;; ("(" "aviyon" "213" "flyingman" "no" ")" ")")
how this works
(cl-ppcre:split "(\\(|\\))" a-string)
splits the string by ( or ). Because in regex pattern ( or ) are used for capturing the match - like here too (the outer parantheses captures) - you have to escape them. \\( or \\).
So with cl-ppcre:split you can split any string in common lisp by regex-pattern. Super cool and super efficient package written by Edi Weitz. He wrote several super sophisticated packages for common lisp - they are also called ediware or edicls in the community.
By the way - cl-ppcre is even more efficient and faster than gold-standard for regex: the perl regex engine!
:with-regiesters-p t option then preserves the matched delimiter - which has to be captured by parentheses like this: (<pattern>) in the pattern.
mapcar this over the list to apply it on each string element in your string list.
However, what you got after that is a list of lists.
(Each inner list containing the splitted result for each string-element of the list).
Flatten the list by alexandria:flatten.
For many functions not in the standard of lisp, but which you think they are basic - like flatten a list - look always first in alexandria - mostly it has a function you desire - it is a huge library. That is why you need it anyway as a common lisper ;) .
But still, there will be empty strings around to be removed.
That is why I wrote remove-empty-string which uses remove-if - which together with remove-if-not is the standard filtering function for lists.
It takes a predicate function - here (lambda (x) (string= x "")) which gives T if string is an empty string and NIL if not.
It removes all elements in the resulting flattened list in our function, which are empty strings.
In other languages it will be named filter but yeah - sometimes function names in common-lisp are not very well chosen. Sometimes I think we should create alias names and move over to them and keep the old names for backward-compatibility. Clojure has nicer names for functions ... Maybe cl people should overtake clojure function names ...
quicklisp
#Alexander Artemenko wrote exactly my solution - he came first. I will add:
If you are so new to common lisp, maybe you don't know how to use quicklisp.
Do in terminal (linux or macos):
wget https://beta.quicklisp.org/quicklisp.lisp
Otherwise manually download in windows from the address.
I put it into ~/quicklisp folder.
Then in clisp or sbcl do:
(load "~/quicklisp/quicklisp.lisp") ;; just path to where downloaded
;; quicklisp.lisp file is!
;; then install quicklisp:
(quicklisp-quickstart:install)
;; then search for cl-ppcre
(ql:system-apropos "cl-ppcre")
;; then install cl-ppcre
(ql:quickload "cl-ppcre")
;; and to autoload everytime you start sbcl or clisp
;; in linux or mac - sorry I don't now windows that well
;; I have the opinion every programmer should us unix
;; as their OS
;; you have to let quicklisp be loaded when they start
;; by an entry into the init file
;; mostly located in ~/.sbclrc or ~/.clisprc.slip or such ...
;; respectively.
;; quicklisp does an entry automatically if you do:
(ql:add-to-init-file)
;; after installation do:
(quit)
;; If you then restart sbcl or clisp and try:
(ql:quickload :cl-ppcre)
;; it should work, - if not, you have to manually load
;; quicklisp first
(load "~/quicklisp/setup.lisp") ;; or wherever quicklisp's
;; setup.lisp file has been stored in your system!
;; and then you can do
(ql:quickload :cl-ppcre)
;; to install alexandria package then, do
(ql:quickload :alexandria) ;; or "alexandria"
;; ql:quickload installs the package from quicklisp repository,
;; if it cannot find package on your system.
;; learn more about quicklisp, since this is the package
;; manager of common lisp - like pip for python
I am trying to emulate the single namespace of scheme within common lisp, with a macro (based on Doug Hoyte's) that expands to a lambda, where every use of an f! symbol (similar to Doug Hoyte's o! and g! symbols) in the function position expands to the same expression, but with funcall added in the function position of each invocation. For example:
(fplambda (f!z x) (f!z x x))
would expand to:
(LAMBDA (F!Z X) (FUNCALL F!Z X X))
The macro currently looks like this:
(defmacro fplambda (parms &body body)
(let ((syms (remove-duplicates
(remove-if-not #'f!-symbol-p
(flatten body)))))
`(lambda ,parms
(macrolet ,(mapcar
(lambda (f)
`(,f (&rest parmlist) `(funcall ,',f ',#parmlist)))
syms))
,#body)))
but given the above input, it expands (as far as I can see) to this:
(LAMBDA (F!F X)
(MACROLET ((F!F (&REST PARMLIST) `(FUNCALL ,'F!F ',#PARMLIST))))
(F!F X X))
In the macrolet definition, F!F should not be quoted or unquoted, and parmlist should just be unquoted. What is going on?
Thanks in advance!
Your definition is mostly right. You just made two pretty simple mistakes. The first one being a mismatched paren. The macrolet does not include the body (in the output the macrolet and the body are at the same level of indentation).
As for the nested backquote, the only mistake is the quote before parmlist. Other than that everything else is correct. The comma and quote before F!F is actually correct. From the hyperspec:
"An implementation is free to interpret a backquoted form F1 as any form F2 that, when evaluated, will produce a result that is the same under equal as the result implied by the above definition". Since the inner backquote has not been expanded yet, it does not have to be free of quotes and unquotes. The expression `(,'x) is actually the same as `(x).
Nested backquotes are notoriously complicated. What is probably the easiest way to understand them is to read Steele's explanation of them.
Edit:
The answer to your question about whether it is possible to use a fplambda expression in the function position is no. From the part of the hyperspec that deals with the evaluation of code: "If the car of the compound form is not a symbol, then that car must be a lambda expression, in which case the compound form is a lambda form.". Since the car of the form, (fplambda ...), is not a lambda expression, your code is no longer valid Common Lisp code.
There is a workaround to this that I figured out, but it's kind of ugly. You can define a reader macro that will allow you to write something like ([fplambda ...] ...) and have it read as
((LAMBDA (&REST #:G1030) (APPLY (FPLAMBDA ...) #:G1030)) ...)
which would do what you want. Here is code that will allow you to do that:
(set-macro-character #\[ 'bracket-reader)
(set-macro-character #\] (get-macro-character #\)))
(defun bracket-reader (stream char)
"Read in a bracket."
(declare (ignore char))
(let ((gargs (gensym)))
`(lambda (&rest ,gargs)
(apply ,(read-delimited-list #\] stream t)
,gargs))))
The only other solution I can think of would be to use some sort of code walker (I can't help you there).
The Lisp forum thread Define macro alias? has an example of creating function alias using a form such as
(setf (symbol-function 'zero?) #'zerop)
This works fine, making zero? a valid predicate. Is it possible to parametrize this form without resorting to macros? I'd like to be able to call the following and have it create function?:
(define-predicate-alias 'functionp)`
My take was approximately:
(defun defalias (old new)
(setf (symbol-function (make-symbol new))
(symbol-function old)))
(defun define-predicate-alias (predicate-function-name)
(let ((alias (format nil "~A?" (string-right-trim "-pP" predicate-function-name))))
(defalias predicate-function-name alias)))
(define-predicate-alias 'zerop)
(zero? '())
This fails when trying to call zero? saying
The function COMMON-LISP-USER::ZERO? is undefined.
make-symbol creates an uninterned symbol. That's why zero? is undefined.
Replace your (make-symbol new) with e.g. (intern new *package*). (Or you may want to think more carefully in which package to intern your new symbol.)
Your code makes a symbol, via MAKE-SYMBOL, but you don't put it into a package.
Use the function INTERN to add a symbol to a package.
To expand on Lars' answer, choose the right package. In this case the default might be to use the same package from the aliased function:
About style:
Anything that begins with DEF should actually be a macro. If you have a function, don't use a name beginning with "DEF". If you look at the Common Lisp language, all those are macro. For example: With those defining forms, one would typically expect that they have a side-effect during compilation of files: the compiler gets informed about them. A function can't.
If I put something like this in a file
(define-predicate-alias zerop)
(zero? '())
and then compile the file, I would expect to not see any warnings about an undefined ZERO?. Thus a macro needs to expand (define-predicate-alias 'zerop) into something which makes the new ZERO? known into the compile-time environment.
I would also make the new name the first argument.
Thus use something like MAKE-PREDICATE-ALIAS instead of DEFINE-PREDICATE-ALIAS, for the function.
There are already some answers that explain how you can do this, but I'd point out:
Naming conventions, P, and -P
Common Lisp has a naming convention that is mostly adhered to (there are exceptions, even in the standard library), that if a type name is multiple words (contains a -), then its predicate is named with -P suffix, whereas if it doesn't, the suffix is just P. So we'd have keyboardp and lcd-monitor-p. It's good then, that you're using (string-right-trim "-pP" predicate-function-name)), but since the …P and …-P names in the standard, and those generated by, e.g., defstruct, will be using P, not p, you might just use (string-right-trim "-P" predicate-function-name)). Of course, even this has the possible issues with some names (e.g., pop), but I guess that just comes with the territory.
Symbol names, format, and *print-case*
More importantly, using format to create symbol names for subsequent interning is dangerous, because format doesn't always print a symbol's name with the characters in the same case that they actually appear in its name. E.g.,
(let ((*print-case* :downcase))
(list (intern (symbol-name 'foo))
(intern (format nil "~A" 'foo))))
;=> (FOO |foo|) ; first symbol has name "FOO", second has name "foo"
You may be better off using string concatenation and extracting symbol names directly. This means you could write code like (this is slightly different use case, since the other questions already explain how you can do what you're trying to do):
(defmacro defpredicate (symbol)
(flet ((predicate-name (symbol)
(let* ((name (symbol-name symbol))
(suffix (if (find #\- name) "-P" "P")))
(intern (concatenate 'string name suffix)))))
`(defun ,(predicate-name symbol) (x)
(typep x ',symbol)))) ; however you're checking the type
(macroexpand-1 '(defpredicate zero))
;=> (DEFUN ZEROP (X) (TYPEP X 'ZERO))
(macroexpand-1 '(defpredicate lcd-monitor))
;=> (DEFUN LCD-MONITOR-P (X) (TYPEP X 'LCD-MONITOR))
Generally, I can use the excellent rx macro to create readable regular expressions and be sure that I've escaped the correct metacharacters.
(rx (any "A-Z")) ;; "[A-Z]"
However, I can't work out how to create shy groups, e.g. \(?:AB\). rx sometimes produces them in its output:
(rx (or "ab" "bc")) ;; "\\(?:ab\\|bc\\)"
but I want to explicitly add them. I can do:
(rx (regexp "\\(?:AB\\)"))
but this defeats the point of rx.
In a perfect world, I'd like to be able to write:
(rx (shy-group "A"))
I'd settle for something like this (none of these work):
;; sadly, `regexp` only accepts literal strings
(rx (regexp (format "\\(?:%s\\)" (rx WHATEVER))))
;; also unfortunate, `eval` quotes the string it's given
(rx (eval (format "\\(?:%s\\)" (rx WHATEVER))))
How can I create regular expressions with shy groups using rx?
I think the structure of a rx form eliminates any need to explicitly create shy groups -- everything that a shy group could be needed for is accounted for by other syntax.
e.g. your own example:
(rx (or "ab" "bc")) ;; "\\(?:ab\\|bc\\)"
For other cases, it is also possible to extend the keywords used by rx.
Example (taken from EmacsWiki link above):
(defmacro rx-extra (&rest body-forms)
(let ((add-ins (list
`(file . ,(rx (+ (or alnum digit "." "/" "-" "_"))))
`(ws0 . ,(rx (0+ (any " " "\t"))))
`(ws+ . ,(rx (+ (any " " "\t"))))
`(int . ,(rx (+ digit))))))
`(let ((rx-constituents (append ',add-ins rx-constituents nil)))
,#body-forms)))
For example if I have the text:
Sum of items is (+ 1 2 3)
I want to move to the end of the line, evaluate the expression and replace it with the result, so that it reads:
Sum of items is 6
With the cursor at the end of the line, C-u C-x C-e will insert the value of the preceding parenthesized expression into the buffer. You could do that, then manually back up and delete the original expression. If that's too much work, here's a command that evaluates the preceding expression and replaces it with its value:
(defun replace-last-sexp ()
(interactive)
(let ((value (eval (preceding-sexp))))
(kill-sexp -1)
(insert (format "%S" value))))
Related to this, you might like Luke Gorrie's "lively.el", which provides live replacement of emacs lisp expressions within a text buffer. It's a neat hack.
I was having a go at a solution for this when I came across one in a Google search result.
(defun fc-eval-and-replace ()
"Replace the preceding sexp with its value."
(interactive)
(backward-kill-sexp)
(prin1 (eval (read (current-kill 0)))
(current-buffer)))
http://emacs.wordpress.com/2007/01/17/eval-and-replace-anywhere/
replace-regex functions can execute lisp to generate the replacements.
In the trivial instance where the sexp in question is on a single line, and is the only thing containing parenthesis, then you could match "(.+)" and replace with "\,(eval (read \&))".
If you are using emacs starter kit by technomancy there is "esk-eval-and-replace" function which evaluates the elisp sexp and replace them. Its bind to C-c e by default.
look to the function eval-print-last-sexp, you can build something using it
My emacs-fu isn't so strong, so I don't know if there's a single command to do this, but you can make yourself a (somewhat fragile) macro for it ... drop these lines in your .emacs:
(fset 'eval-sexp-in-place
[?\M-x ?e ?v ?a ?l ?- ?p ?r ?i ?n tab return ?\M-^ ?\M-^ ?\C-\M-b ?\C-\M-k ?\C-d])
(global-set-key [(control x) (control a)] 'eval-sexp-in-place)
This works fine, but there's one issue with it: you need to be at the end of the sexp (i.e. after the last right paren) to get it to work.
Also, I picked a random unbound key (C-x C-a) -- feel free to change that to something more to your liking.