I'm trying to branch out and learn lisp. One of the basics would be to implement a simple stack. Everything works but my pop function.
;Returns and removes the first element of the stack
(defun my-pop ()
(let (temp (car *stack*))
(setq *stack* (cdr *stack*))
temp))
This correctly removes the "top" of the stack, but does not return it. Earlier, I had this:
;Returns and removes the first element of the stack
(defun my-pop ()
(print (car *stack*)
(setq *stack* (cdr *stack*)))
But I'd rather return the top.
What am I doing wrong? (I assume this has something to do with scope...)
Nothing to do with scope, it's a syntax problem. The syntax of LET is:
(let ((var1 val1)
(var2 val2)
...)
body)
Additionally, a (varN valN) may be abbreviated to just varN, which is equivalent to (varN nil). So what you wrote is equivalent to:
(let ((temp nil) ; bind TEMP to NIL
(car *stack*)) ; bind CAR to value of *STACK*
(setq *stack* (cdr *stack*))
temp)
You need an extra set of parentheses in your LET-bindings:
(let ((temp (car *stack*)))
(setq *stack* (cdr *stack*))
temp)
You could also use the built-in operator PROG1:
(prog1
(car *stack*)
(setq *stack* (cdr *stack)))
Related
How to achieve this in Common lisp?
(logselect (t nil t) (list1 list2 list3)) ---> (list1 list2)
I have coded the below function but I think there is a better way (maybe a built-in function?).
(defun logselect (loglist lista)
(let ((listaL) (maskL) (toremove))
(setq listaL (mapcar #'list lista))
(setq maskL (mapcar #'cons loglist listaL))
(setq toremove (mapcar #'(lambda (x) (car (and (car x) (cdr x)))) maskL))
(remove nil toremove)
)
)
Thank you in advance.
This is easily done using LOOP:
(defun logselect (loglist lista)
(loop for test in loglist
for value in lista
when test collect value))
If you prefer a more "lispy" solution, you can do it with mapcan:
(defun logselect (loglist lista)
(mapcan #'(lambda (test value)
(when test (list value)))
loglist lista))
mapcan is a useful function when you want to use a mapping function to add list elements conditionally. The function returns a list, and they're all concatenated to create the final result, so it can return an empty list if it doesn't want to add something.
So I'm making this function in lisp, and in the cond part basically if a condition is met, I return a list with 2 values, and if the condition is not met, I would like to not return anything at all! Here it is:
(defun lista-dos-aprovados (turma)
(mapcar (lambda (aluno)
(cond ((> (media-notas (notas aluno)) 9.5)
(list (first aluno) (second aluno)))
(t nil)))
turma))
the names are in portuguese but I think it doesn't really matter here. What I'd like to do is when the code reaches the (t nil) part, I don't want it to write NIL inside my list. I tried not having the T condition or leaving it empty after the T, still it always writes NIL.
You can remove the nil in the result of mapcar, like in:
(defun lista-dos-aprovados (turma)
(remove nil
(mapcar (lambda (aluno)
(cond ((> (media-notas (notas aluno)) 9.5)
(list (first aluno) (second aluno)))
(t nil)))
turma)))
and note that you can simplify the function as:
(defun lista-dos-aprovados (turma)
(remove nil
(mapcar (lambda (aluno)
(when (> (media-notas (notas aluno)) 9.5)
(list (first aluno) (second aluno))))
turma)))
or you can use a loop:
(defun lista-dos-aprovados (turma)
(loop for aluno in turma
when (> (media-notas (notas aluno)) 9.5)
collect (list (first aluno) (second aluno))))
I am trying to incorporate the name of a buffer-local variable into the dolist cycle, and change the value of that buffer-local variable. setq and setq-local reject all of the variable name variations that I have tried. In the dolist cycle, the variable name is (car (car (cdr test))).
The same variable name will be used in more than one buffer, with each buffer having a different value.
This project is related two (2) other recent threads of mine, but I believe this is a somewhat unique issue. The related threads are as follows: How to use `setcdr` with buffer-local variables and How to use a cons cell to define and later remove overlays with `dolist`
I have tried all of the following, and a few other variations, without success:
(setq (car (car (cdr test))) newlist)
(setq var newlist)
(setq (make-symbol (car (car (cdr test)))) newlist)
(setq (intern (car (car (cdr test)))) newlist)
I have also tried modifying the list to use a string, e.g., '("variable-one" ,variable-one)
Here is the test code:
(defvar variable-one '(a t))
(make-variable-buffer-local 'variable-one)
(defvar variable-two '(c t))
(make-variable-buffer-local 'variable-two)
(defvar variable-three '(e t))
(make-variable-buffer-local 'variable-three)
(dolist (test `(
'(variable-one ,variable-one)
'(variable-two ,variable-two)
'(variable-three ,variable-three) ))
(let* (
(var (car (car (cdr test))))
(newlist (copy-list (car (cdr (car (cdr test)))))) )
(setcdr newlist nil)
(message "var: %s | newlist: %s" var newlist)
;; (setq (car (car (cdr test))) newlist)
))
EDIT (August 26, 2014): The following revision is based upon the helpful suggestions provided by everyone in this thread -- greatly appreciated! :) I still need to conduct some buffer-local tests with multiple buffers later on today, but the suggestions made by the forum participants seem to work with the test outline below.
(defvar variable-one '(a t))
(make-variable-buffer-local 'variable-one)
(defvar variable-two '(c t))
(make-variable-buffer-local 'variable-two)
(defvar variable-three '(e t))
(make-variable-buffer-local 'variable-three)
(dolist (test `(
(variable-one ,variable-one)
(variable-two ,variable-two)
(variable-three ,variable-three) ))
(let* (
(var (car test))
(newlist (copy-list (car (cdr test)))) )
(setcdr newlist nil)
(message "var: %s | newlist: %s" var newlist)
(set (car test) newlist) ))
I don't know what you mean by the "dolist cycle".
The root of your problem is that setq is a special form. The first argument doesn't need to be quoted -- that is what the "q" means.
You want to use set instead.
I am trying to define a recursive function balanced that takes a string and returns true only if the parens in the string are balanced.
The elisp code I wrote is based on some Scala code I wrote for the Coursera class by Odersky, it's a transliteration.
;; check if expr (list of chars of some expression) is balanced
(defun balanced (expr)
(defvar lparen (string-to-char "("))
(defvar rparen (string-to-char ")"))
(defun is-open (c) (eq lparen c))
(defun is-close (c) (eq rparen c))
(defun is-empty (ls) (eq ls nil))
(defun is-matching (l r) (and (is-open l) (is-close r)))
(defun is-balanced (list stack)
(cond ((is-empty list) (is-empty stack))
((is-open (car list))
(is-balanced (cdr list) ;; 'push' open-paren onto stack
(cons (car list) stack)))
((is-close (car list))
(if (is-empty stack) nil
(and
(is-balanced (cdr list) (cdr stack))
(is-matching (car stack) (car list)))))
(is-balanced (cdr list) (cdr stack))))
is-balanced
I am in lisp-interaction-mode, so I used Ctrl-J to evaluate the above defun statement.
Then, when I attempt to evaluate this:
(balanced "(balanced nil nil)")
I get a void-variable error:
Debugger entered--Lisp error: (void-variable is-balanced)
balanced("(balanced nil nil)")
(progn (balanced "(balanced nil nil)"))
eval((progn (balanced "(balanced nil nil)")) t)
eval-last-sexp-1(t)
eval-last-sexp(t)
eval-print-last-sexp()
call-interactively(eval-print-last-sexp nil nil)
recursive-edit()
debug(error (void-variable is-balanced))
balanced("(balanced nil nil)")
(progn (balanced "(balanced nil nil)"))
eval((progn (balanced "(balanced nil nil)")) t)
eval-last-sexp-1(t)
eval-last-sexp(t)
eval-print-last-sexp()
call-interactively(eval-print-last-sexp nil nil)
recursive-edit()
The function doesn't seem to recognize itself, what am I doing wrong?
When you execute your function (balanced ...), what it does is this:
It first defines two global variables
It defines five other functions
It accesses the variable is-balanced.
Step 3. happens right after the end of (defun is-balanced (list stack) ... )))).
(defun balanced (expr)
...
(defun is-balanced (list stack)
...
(is-balanced (cdr list) (cdr stack))))
is-balanced ;; <= here!
But you have not defined such a variable. You have defined a function of the same name, but you cannot access function objects as if they're variables in Emacs Lisp. See also here. Since there is no variable named is-balanced you get an error message.
(That said, there's a lot to be critized about the rest of your code. For starters, be aware that by having defuns inside defuns, you're re-defining your is-* functions every single time you're invoking (balanced ...). That's certainly not what you want. Similarly, you probably want to move the defvar outside the function body, since they define global variables. Or did you mean to use (let ...) instead? If you really want global values, then (defconst...) might be more appropriate.)
The problem is that the final element of the cond expression is not wrapped in (t ... ):
Incorrect:
(is-balanced (cdr list) (cdr stack))
Correct
(t (is-balanced (cdr list) (cdr stack)))
The reason this is needed is that the last expression is supposed to be the else case.
I am trying to write a function (lnn; list-not-nil) similar to list that only appends values that are not nil.
(list nil 3) --> (NIL 3)
(lnn nil 3) --> (3)
Here is the code I have so far. For some reason it causes infinite recursion on any input that I try.
(defun lnn (&rest items)
(lnn-helper nil items))
(defun lnn-helper (so-far items)
(cond ((null items)
so-far)
((null (car items))
(lnn-helper so-far (cdr items)))
(t (lnn-helper (append so-far (list (car items))) (cdr items)))))
Any ideas? Thanks very much.
(defun lnn-helper (so-far &rest items)
...)
With this argument list, items will never be nil if you always call lnn-helper with two arguments. Remove the &rest specifier, and it'll work.
Matthias' answer should have helped. Also note, that this is just a simple reduction:
(defun lnn (&rest elements)
(reduce (lambda (elt acc) (if elt (cons elt acc) acc))
elements
:from-end t
:initial-value nil))
Or even (less efficient):
(defun lnn (&rest elements)
(reduce #'cons (remove nil elements) :from-end t :initial-value nil))
Then:
(defun lnn (&rest elements)
(remove nil elements))
:)
P.S.: I know this was probably just an exercise in recursion, but SCNR.