I am a novice in the field of lisp... i am writing a code to solve the 8 puzzle in bfs...
I want to store the visited lists in a global list and change its value regularly from within a function...
(defparameter *vlist* nil)
(defun bfs-core(node-list)
(let (cur-node tmp-node-list)
(if (null node-list)
NIL
(progn
; (if (= 1 (length node-list))
(setq cur-node (car node-list))
(setq tmp-node-list (cdr node-list))
(if (goalp cur-node)
cur-node
((setq *vlist* (append cur-node *vlist*))
(bfs-core (append tmp-node-list (expand cur-node))))))
)
)
)
The defparameter one is my global variable... and witjin the function i want to change its value with setq... i have also used defvar, setf,set and all possible combinations.....
Can anyone help me out????
Here is your code (reformatted for standard Lisp style):
(defparameter *vlist* nil)
(defun bfs-core (node-list)
(let (cur-node tmp-node-list)
(if (null node-list)
NIL
(progn
; (if (= 1 (length node-list))
(setq cur-node (car node-list))
(setq tmp-node-list (cdr node-list))
(if (goalp cur-node)
cur-node
((setq *vlist* (append cur-node *vlist*))
(bfs-core (append tmp-node-list (expand cur-node)))))))))
Your code as one clear problem.
The form ((setq *vlist* ...) (bfs-core ...)) ends up being a function call. When you have a form like (exp1 exp2 exp3) then exp1 is a function applied to parameter values of exp2 and exp3. Your exp1 is (setq *vlist* ...) which doesn't evaluate to a function and, of course, you never wanted it to.
A rewritten version of your code, that at least would remove the misplaced function call, is:
(defparameter *vlist* nil)
(defun bfs-core (node-list)
(let (cur-node tmp-node-list)
(if (null node-list)
NIL
(progn
; (if (= 1 (length node-list))
(setq cur-node (car node-list))
(setq tmp-node-list (cdr node-list))
(if (goalp cur-node)
cur-node
(progn
(setq *vlist* (append cur-node *vlist*))
(bfs-core (append tmp-node-list (expand cur-node)))))))))
You certainly can change global variables from inside functions:
[1]> (defparameter *visited-lists* nil)
*VISITED-LISTS*
[2]> *visited-lists*
NIL
[3]> (defun change-global-value ()
(setf *visited-lists* (append (list 'new-value)
*visited-lists* )))
CHANGE-GLOBAL-VALUE
[4]> *visited-lists*
NIL
[5]> (change-global-value)
(NEW-VALUE)
[6]> *visited-lists*
(NEW-VALUE)
[7]> (change-global-value)
(NEW-VALUE NEW-VALUE)
[8]> *visited-lists*
(NEW-VALUE NEW-VALUE)
But let's look at your code some more:
(defun bfs-core(node-list)
(let (cur-node tmp-node-list)
(if (null node-list)
NIL
(progn
; (if (= 1 (length node-list))
(setq cur-node (car node-list))
(setq tmp-node-list (cdr node-list))
(if (goalp cur-node)
cur-node
((setq *vlist* (append cur-node *vlist*))
(bfs-core (append tmp-node-list (expand cur-node))))))
)
)
)
First, let's get closing parentheses on the correct lines, and remove the commented-out code. Most Lisp coders don't close their parens like braces in an ALGOL-style language:
(defun bfs-core(node-list)
(let (cur-node tmp-node-list)
(if (null node-list)
NIL
(progn
(setq cur-node (car node-list))
(setq tmp-node-list (cdr node-list))
(if (goalp cur-node)
cur-node
((setq *vlist* (append cur-node *vlist*))
(bfs-core (append tmp-node-list (expand cur-node)))))))))
Now, we have a nil for the first branch of an if. We can change it to unless, which has a built-in progn, so we don't need that either:
(defun bfs-core(node-list)
(let (cur-node tmp-node-list)
(unless (null node-list) ;;changed this line to an unless, dropped nil, progn
(setq cur-node (car node-list))
(setq tmp-node-list (cdr node-list))
(if (goalp cur-node)
cur-node
((setq *vlist* (append cur-node *vlist*))
(bfs-core (append tmp-node-list (expand cur-node))))))))
We're also using a let to set some variables to nil, and when we get inside the unless, we immediately set the variables to the values we actually want to work with. Let's switch it so that we only create the variables if we're going to use them:
(defun bfs-core(node-list)
(unless (null node-list) ;;switched this line and the let below
(let ((cur-node (car node-list)) ;;also set the variables inside the let
(tmp-node-list) (cdr node-list))
(if (goalp cur-node)
cur-node
((setq *vlist* (append cur-node *vlist*))
(bfs-core (append tmp-node-list (expand cur-node))))))))
Ok, we're already at much cleaner code. Yay!
Let's look at one of the calls here:
((setq *vlist* (append cur-node *vlist*))
(bfs-core (append tmp-node-list (expand cur-node))))
Did you mean to put this as a single call, and not two? There's a difference between that and this:
((setq *vlist* (append cur-node *vlist*)))
(bfs-core (append tmp-node-list (expand cur-node)))
Do you see the difference? The first is a single statement; the second is two. You probably want the second, as you want to change *vlist*, then call bfs-core. And, to do that, you'll need progn:
(defun bfs-core(node-list)
(unless (null node-list)
(let ((cur-node (car node-list))
(tmp-node-list) (cdr node-list))
(if (goalp cur-node)
cur-node
(progn (setq *vlist* (append cur-node *vlist*))
(bfs-core (append tmp-node-list (expand cur-node))))))))
The other answers are specific to the problem at hand. As a general answer on how to change the value of a variable that is passed to a subroutine, it is possible if the variable is passed as a symbol:
(defun modify (x)
(set x 100))
(setq d 1) => value of d is 1
(modify 'd) => value of d is 100
So, to use the terminology of pass by value and pass by reference and apply that to lisp:
(userfunction 'x) is pass by reference,
(Userfunction x) is pass by value.
Related
How can I cycle through only those buffers which are in a given major mode (such as Python-mode ) ?
Currently I am using C-X-Left/Right arrows, but these also show all sorts of irrelevant (i.e. non source code) buffers, any idea how can I restrict the buffer switching only to a specific type of buffer (with a given major mode) ?
I could not find something ready-made. However, it is not very hard to make the suitable commands.
(defun buffer-mode-alist ()
"Returns a list of (<buffer-name> . <major-mode>) pairs."
(let ((all-buffers (buffer-list))
(rv nil))
(while all-buffers
(let* ((this (car all-buffers))
(name (buffer-name this)))
(setq all-buffers (cdr all-buffers))
(when name
(setq rv (cons (cons name (with-current-buffer this major-mode)) rv)))))
rv))
(defun buffers-with-major-mode (the-major-mode)
(let ((buffer-alist (buffer-mode-alist))
(rv nil))
(while buffer-alist
(let ((this (car buffer-alist)))
(setq buffer-alist (cdr buffer-alist))
(if (eql (cdr this) the-major-mode)
(setq rv (cons (car this) rv)))))
(sort rv #'string<)))
(defun spin-buffers (buffer-list current)
(cond ((not (member current buffer-list)) buffer-list)
((string= current (car buffer-list)) buffer-list)
(t (spin-buffers (append (cdr buffer-list)
(list (car buffer-list)))
current))))
(defvar next-buffer-mode nil)
(defun choose-next-buffer-mode (mode)
"Ask for what major mode should be used as a selector for next-buffer-with-mode."
(interactive "aMajor Mode: ")
(setq next-buffer-mode mode))
(defun next-buffer-with-mode (set)
"Switches to the 'next' buffer with a given mode. If the mode is not set,
require it to be set, by calling choose-next-buffer-mode. If any prefix
argument is passed, also call choose-next-buffer-mode."
(interactive "P")
(when (or (not next-buffer-mode)
set)
(call-interactively 'choose-next-buffer-mode))
(let ((buffers (spin-buffers (buffers-with-major-mode next-buffer-mode)
(buffer-name))))
(when (cdr buffers)
(switch-to-buffer (cadr buffers)))))
(defun prev-buffer-with-mode (set)
"Switches to the 'previous' buffer with a given mode. If the mode is not set,
require it to be set, by calling choose-next-buffer-mode. If any prefix
argument is passed, also call choose-next-buffer-mode."
(interactive "P")
(when (or (not next-buffer-mode)
set)
(call-interactively 'choose-next-buffer-mode))
(let ((buffers (spin-buffers (buffers-with-major-mode next-buffer-mode)
(buffer-name))))
(when buffers
(switch-to-buffer (car (last buffers))))))
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 looking for some assistance, please, to extract all elements of a list of files and/or directories that have been marked in dired-mode. Essentially, if there were some way to just remove the parentheses from around the result of (mapcar (lambda (filename) (file-name-nondirectory filename)) (dired-get-marked-files)), then that would do the trick.
(start-process
"name-of-process"
"*output-buffer*"
"/usr/bin/zip"
"zip-file-name.zip"
(mapcar
(lambda (filename) (file-name-nondirectory filename))
(dired-get-marked-files)) )
The result I am seeking will look like this:
(start-process
"name-of-process"
"*output-buffer*"
"/usr/bin/zip"
"zip-file-name.zip"
"filename-number-one"
"filename-number-two"
"filename-number-three" )
EDIT:
The start-process function does not generally accept a single concatenated string of arguments. Instead, each argument must be separately spelled out (with quotation marks around each argument), or the argument can be a variable.
Here is the debugger message from the first example above -- the error occurs because there is a parentheses around the file names -- i.e., it cannot be a list.
Debugger entered--Lisp error: (wrong-type-argument stringp ("file-name-number-one" "file-name-number-two" "file-name-number-three"))
start-process("name-of-process" "*output-buffer*" "/usr/bin/zip" "zip-file-name.zip" ("file-name-number-one" "file-name-number-two" "file-name-number-three"))
eval((start-process "name-of-process" "*output-buffer*" "/usr/bin/zip" "zip-file-name.zip" (mapcar (lambda (filename) (file-name-nondirectory filename)) (dired-get-marked-files))) nil)
(cons (eval exp lexical-binding) values)
(setq values (cons (eval exp lexical-binding) values))
(let ((debug-on-error old-value)) (setq values (cons (eval exp lexical-binding) values)) (setq new-value debug-on-error))
(let ((old-value (make-symbol "t")) new-value) (let ((debug-on-error old-value)) (setq values (cons (eval exp lexical-binding) values)) (setq new-value debug-on-error)) (if (eq old-value new-value) nil (setq debug-on-error new-value)))
(if (null eval-expression-debug-on-error) (setq values (cons (eval exp lexical-binding) values)) (let ((old-value (make-symbol "t")) new-value) (let ((debug-on-error old-value)) (setq values (cons (eval exp lexical-binding) values)) (setq new-value debug-on-error)) (if (eq old-value new-value) nil (setq debug-on-error new-value))))
(let ((exp (if exp exp (read--expression "Eval: ")))) (if (null eval-expression-debug-on-error) (setq values (cons (eval exp lexical-binding) values)) (let ((old-value (make-symbol "t")) new-value) (let ((debug-on-error old-value)) (setq values (cons (eval exp lexical-binding) values)) (setq new-value debug-on-error)) (if (eq old-value new-value) nil (setq debug-on-error new-value)))) (let ((print-length (and (not (= 0 (prefix-numeric-value insert-value))) eval-expression-print-length)) (print-level (and (not (= 0 (prefix-numeric-value insert-value))) eval-expression-print-level)) (deactivate-mark)) (if insert-value (with-no-warnings (let ((standard-output (current-buffer))) (prog1 (prin1 (car values)) (if (= 0 ...) (progn ...))))) (prog1 (prin1 (car values) t) (let ((str (eval-expression-print-format ...))) (if str (princ str t)))))))
(if (active-minibuffer-window) nil (let ((exp (if exp exp (read--expression "Eval: ")))) (if (null eval-expression-debug-on-error) (setq values (cons (eval exp lexical-binding) values)) (let ((old-value (make-symbol "t")) new-value) (let ((debug-on-error old-value)) (setq values (cons (eval exp lexical-binding) values)) (setq new-value debug-on-error)) (if (eq old-value new-value) nil (setq debug-on-error new-value)))) (let ((print-length (and (not (= 0 ...)) eval-expression-print-length)) (print-level (and (not (= 0 ...)) eval-expression-print-level)) (deactivate-mark)) (if insert-value (with-no-warnings (let ((standard-output ...)) (prog1 (prin1 ...) (if ... ...)))) (prog1 (prin1 (car values) t) (let ((str ...)) (if str (princ str t))))))))
lawlist-eval-expression()
funcall-interactively(lawlist-eval-expression)
call-interactively(lawlist-eval-expression nil nil)
command-execute(lawlist-eval-expression)
What you want is to use apply with (mapcar ...) as its last argument:
(apply 'start-process
"name-of-process"
"*output-buffer*"
"/usr/bin/zip"
"zip-file-name.zip"
(mapcar #'file-name-nondirectory (dired-get-marked-files)))
Note that (mapcar #'function list) is a shorter spelling of (mapcar (lambda (arg) (function arg)) list).
combine-and-quote-strings is what you want:
(combine-and-quote-strings (mapcar (lambda (x)
(file-name-nondirectory x))
(dired-get-marked-files)))
EDIT: the following will give you a single, quoted string with internal quotes. Not sure if it'll play nicely with start-process:
(mapconcat
(lambda (x)
(concat "\"" (file-name-nondirectory x) "\""))
(dired-get-marked-files) " ")
EDIT: Righty-o, let's try this. Splice the backquoted list with ,#, then eval the whole thing:
(eval `(start-process
"name-of-process"
"*output-buffer*"
"/usr/bin/zip"
"zip-file-name.zip"
,#(mapcar
(lambda (x)
(file-name-nondirectory x))
(dired-get-marked-files))))
How do I generate an enumerated list of all tags (e.g., :tag:) in an org-mode file? Say I have a list of the form:
* Head1 :foo:bar:
** Subhead1 :foo:
* Head2
** Subhead2 :foo:bar:
I want to generate a list of all tags in this file as well as how many times each tag was used. Say something like,
:foo: 3
:bar: 2
Here is a shorter version.
(defun get-tag-counts ()
(let ((all-tags '()))
(org-map-entries
(lambda ()
(let ((tag-string (car (last (org-heading-components)))))
(when tag-string
(setq all-tags
(append all-tags (split-string tag-string ":" t)))))))
;; now get counts
(loop for tag in (-uniq all-tags)
collect (cons tag (cl-count tag all-tags :test 'string=)))))
I could not make use of the code posted by John Kitchin, as it requires an interactive function. bpalmer from IRC freenode/#emacs was so kind to help me out. Please find a working example that spits out all tags below the respective tree.
; use this in order to be able to use loop on its own
(require 'cl)
;; count tags (see John's answer)
(defun get-tag-counts ()
(let ((all-tags '()))
(org-map-entries
(lambda ()
(let ((tag-string (car (last (org-heading-components)))))
(when tag-string
(setq all-tags
(append all-tags (split-string tag-string ":" t)))))))
;; now get counts
(loop for tag in (seq-uniq all-tags)
collect (cons tag (cl-count tag all-tags :test 'string=)))))
;; wrap get-tag-counts in an interactive function
(defun create-tag-counts-buffer ()
(interactive)
(let ((tags (get-tag-counts)) (b (get-buffer-create "*Org Tag Count*")))
(dolist (tag tags) (insert (car tag)) (insert "\n")) (display-buffer b)))
Here is an approach.
(setq my-hash (make-hash-table :test 'equal))
(org-map-entries
(lambda ()
(let ((tag-string (car (last (org-heading-components))))
(current-count))
(when tag-string
(dolist (tag (split-string tag-string ":" t))
(setq current-count (gethash tag my-hash))
(if current-count;
(puthash tag (+ 1 current-count) my-hash)
(puthash tag 1 my-hash))
)
)
)
)
)
;; https://github.com/Wilfred/ht.el
(require 'ht)
(ht-map
(lambda (key value)
(list key value))
my-hash)
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)))