I am trying to use butlast but for some reason, I get this
error: no function definition: BUTLAST. Any ideas why?
butlast does not exist in AutoLisp so that the error says there is such function is on point.
You can define it though
(defun butlast (lst)
(reverse (cdr (reverse lst))))
Related
I'm learning LISP and I am trying to write a function that adds 1 to each element inside my list. I first test for if the first element is a number or not then add 1 to the first element in the list. I then recursively call the function on the rest of the list but I get an error. Any help? Here's the function:
(defun add-1-all (L)
(cond (not (numberp (first L)) nil)
(t (+1 (first L)) (add-1-all (rest L)))))
Here are more approaches:
When dealing with lists (see Joshua's comment), use ENDP, FIRST and REST, which are preferred over NULL, CAR and CDR. They convey the intent more clearly and in the case of ENDP, check that the argument is a proper-list. Imagine you pass a dotted-list built with (cons 'a 'b), what should happen? ENDP detects that the list is not proper and signals an error.
(defun add-1-all (list)
(unless (endp list)
(cons (1+ (first list))
(add-1-all (rest list)))))
I used UNLESS for its NIL value, which some people might not like. You may want to explicitely return NIL when reaching the end of your list. In that case, stick with COND or just use IF.
Loop.
(defun add-1-all (list)
(loop for e in list collect (1+ e)))
Make it work on arrays too, not just lists.
(defun add-1-all (sequence)
(map (type-of sequence) #'1+ sequence))
The easiest way to accomplish your goal would be to use map. Map applies a function to each element of a sequence. That way one does not have to take care of details like iterating through the sequence. In the code below I use mapcar which works only on lists.
(defun add-1 (list)
(mapcar #'1+ list))
To find out about other mapping functions that CL provides run (apropos "map") and use (describe ) to find out more. Or better yet use the clhs search engine or the extended CL documentation search engine
The solution you provided is attempting to solve the problem through recursion. The general idea is to traverse the list using first/rest while building a new one with the elements incremented by one. When the list reaches the end (You can use the functions null or endp to test that the end of the list has been reached) the new list should be returned. One of the problems with your solution is that it lacks an accumulator. Also your base-case (the condition that signals to stop the recursion) is wrong.
A couple of other pointers. Use an editor that formats your code as it is difficult to read. Also CL is not a Lisp-1 so you can use list as a variable name and it won't collide with the function list. They have separate namespaces. It is also helpful to post the error message and the explain what/how your solution is trying to do. You may also find this textbook useful for learning Lisp
You could write (+ 1 (first L)) or (1+ (first L)) but you didn't write that.
Also, you should use cons to tack the result on the first element to the result of the rest of them.
Also, did you really want to drop off all the elements after the first non-number? Or did you want to assume all elements were numbers, in which case you should learn about map or mapcar, which allows you to solve the problem in 15 characters.
First of all your code is wrong if you compile it you get several errors and warnings, is important a good lisp syntax and also knowing what you are writing. If you are learning lisp I reccomend you to get a confortable environment for that like slime and quicklisp
; SLIME 2015-06-01; compiling (DEFUN ADD-1-ALL ...)
; file: /tmp/file451NPJ
; in: DEFUN ADD-1-ALL
; (1 (FIRST L))
;
; caught ERROR:
; illegal function call
; (REST L)
; --> CDR
; ==>
; L
;
; note: deleting unreachable code
; (COND (NOT (NUMBERP (FIRST L)) NIL) (T (1 (FIRST L)) (ADD-1-ALL (REST L))))
; ==>
; (IF NOT
; (PROGN (NUMBERP (FIRST L)) NIL)
; (COND (T (1 (FIRST L)) (ADD-1-ALL (REST L)))))
;
; caught WARNING:
; undefined variable: NOT
;
; compilation unit finished
; Undefined variable:
; NOT
; caught 1 ERROR condition
; caught 1 WARNING condition
; printed 1 note
Then it is a good idea to use recursion for doing this task, for recursions is important to know when to stop and the base case of your algorithm
In you case you can also use if for this two path the function will be this:
(defun add-1-all (list)
(cond
((null list) nil)
(t (cons (1+ (car list))(add-1-all (cdr list))))))
I recommend you to try doing this using a tail recursive function for better perfomance and a great learning.
Also with lisp you can use more functional style, when time comes you will learn this, like using higher order functions in this case your function is as follows:
;; functional programming higher order functions
(defun add-1-all-ho (list)
(mapcar #'1+ list))
This defines the Helm-source for Emacs commands history, for the Emacs package Helm.
(defvar helm-source-emacs-commands-history
(helm-build-sync-source "Emacs commands history"
:candidates (lambda ()
(let ((cmds))
(dolist (elem extended-command-history)
(push (intern elem) cmds))
cmds))
:coerce #'intern-soft
:action #'command-execute)
"Emacs commands history")
From this source you get the latest commands that you called with M-x. I would like to have a function, that calls the latest command that I called with M-x in Emacs earlier. I read the documentation about list elements.
Function: car cons-cell
This function returns the value referred to by the first slot of the cons cell cons-cell. In other words, it returns the CAR of cons-cell.
As a special case, if cons-cell is nil, this function returns nil. Therefore, any list is a valid argument. An error is signaled if the argument is not a cons cell or nil.
(car '(a b c))
⇒ a
(car '())
⇒ nil
So I assume I need to replace the push with car, and return the result.
(dolist (elem extended-command-history)
(car (intern elem)))
But I got the error message
Debugger entered -- Lisp error (wrong-type-argument listp Info-next)
(Info-Next)
The Info-Next was indeed the latest command that I called with M-x. However, I don't understand the error. Another way to get the latest called function.
(defun foobar ()
(interactive)
(call-interactively (intern (car extended-command-history))))
After calling foobar, I get the following error:
funcall-interactively: Lisp nesting exceeds `max-lisp-eval-depth'
Any suggestion to get the latest command?
(defun magit-max-args-internal (function)
"Return the maximum number of arguments accepted by FUNCTION."
(if (symbolp function)
(setq function (symbol-function function)))
(if (subrp function)
(let ((max (cdr (subr-arity function))))
(if (eq 'many max)
most-positive-fixnum
max))
(if (eq 'macro (car-safe function))
(setq function (cdr function)))
(let ((arglist (if (byte-code-function-p function)
(aref function 0) ; <--------- format changed
(cadr function))))
(if (memq '&rest arglist)
most-positive-fixnum
(length (remq '&optional arglist))))))
I had to recompile magit.el and discovered this problem in their code. If I follow the code correctly, then what they were after here is the function's arity, but instead they are getting some "strange" number. Any ideas what happened?
In addition, this post: Elisp get function arity? offers a better solution (which does the job just fine, the answer by Andreas Röhler. So I will probably try to suggest it to magit maintainers.
Indeed this "number in (aref bytecode 0)" was introduced for lexical-binding. The better fix is to throw away magit-max-args-internal and use (condition-case nil (delete-directory <args>) (wrong-number-of-arguments (delete-directory <fewerargs>)) instead.
i'm new to common lisp and therefore my problem could be very easy, but i didn't find anything, maybe i used the wrong search terms.
i've got the following problem:
i have a function that does a special addition on an arbitrary number of parameters. the next step would be to apply that function to an arbitrary number of lists of same size, the result would be an list of that size.
it works if i call
(mapcar #'addition list1 list2 ...)
but if i have to define a function
(defun list-add (list &rest lists)
(mapcar #'addition list lists))
it won't work, because &rest lists now is a list of lists. the function addition needs to be called with all parameters as sequence, so a recursive call is not possible.
does anyone have a solution?
See APPLY.
Also note the value of CALL-ARGUMENTS-LIMIT.
The obvious solution would be:
(defun list-add (&rest lists)
(apply #'mapcar #'addition lists))
I'm not sure I got the question correctly but try
(defun list-add (list &rest lists)
(mapcar (lambda (l) (apply #'addition list l))
lists))
I'm not sure if this is necessarily better or worse than the answers already supplied, but here's what I came up with:
(defun list-add (first-required-list &rest other-lists)
(let ((all-lists (cons first-required-list
other-lists)))
(reduce (lambda (left-list right-list)
(mapcar #'addition left-list right-list))
all-lists)))
...just like packages do.
I use Emacs (maybe, it can offer some kind of solution).
For example (defun the-very-very-long-but-good-name () ...) is not to useful later in code. But the name like Fn-15 or the first letters abbreviation is not useful too.
Is it possible either to have an alias like for packages or to access the documentation string while trying to recall the function's name?
In other words, is it possible for functions to mix somehow self-documenting and short names?
You want defalias. (defalias 'newname 'oldname) will preserve documentation and even show "newname is an alias for `oldname'" when its documentation is requested.
You could use setf to assign the function to the function cell of another, for example:
(defmacro alias (new-name prev-name)
`(setf (symbol-function ,new-name) (symbol-function ,prev-name)))
from 《On Lisp》?Here is the code:
(defmacro alias (new-name prev-name)
`(defmacro ,new-name (&rest args)
`(,',prev-name ,#args)))
; use: (alias df defun)
(defun group (source n)
(if (zerop n) (error "zero length"))
(labels ((rec (source acc)
(let ((rest (nthcdr n source)))
(if (consp rest)
(rec rest (cons (subseq source 0 n) acc))
(nreverse (cons source acc))))))
(if source (rec source nil) nil)))
(defmacro aliasx (&rest names)
`(alias
,#(mapcar #'(lambda (pair)
`(alias ,#pair))
(group names 2))))
; use: (aliasx df1 defun
; df2 defun
; df3 defun)
If it's all the typing which makes continual use of long names undesirable, then yes, emacs can help. Check out abbrev-mode. Also well thought-of in this context is hippie-expand.
If it's a question of readability, that's harder.
If your problem is that you can't remember a very long function name, but you remember PART of the name, that's what "apropos" is for. In my Emacs, I have "C-h a" bound to "hyper-apropos". You enter a substring of the symbol you're looking for, and it lists all the matches.
I dont know Emacs, but wouldn't (define shortname longnamefunctionblahblah) work?
You could simply have a function that just calls another function.
you can use (defmacro ...) to alias a function