(1- 3) Notation in Elisp - lisp

I'm not sure what (1- 3) means in Elisp, as I'm only used to seeing operators, or more appropriately "functions," as the first argument in the list, such as (- 1 3), not following a value, as in (1- 3). Thanks.

1+ and 1- are function names (so you can use C-h f to read about them).
(1+ n) returns n + 1.
(1- n) returns n - 1.
The latter can be confusing to read if you don't know what's going on, granted.

Related

to apply #' or not to apply #'

I've just started to play around with Lisp (Common-Lisp), here's a function that calculates the average of a list of numbers
CL-USER> (defun average (list) (/ (apply #'+ list) (length list)))
AVERAGE
CL-USER> (average '(1 2 3 4))
5/2
however if I rewrite the function like so
CL-USER> (defun average (list) (/ (+ list) (length list)))
it doesn't work since (+ '(list-of-numbers)) can't be evaluated, hence the arguement of length and the expression in the + are incompatible.
is there a way of cajoling (list) to be evaluated naturally as an expression by + and passed as data to length ? rather than using apply #'
I've tried this:
(defun average (list) (/ (+ list) (length '(list))))
but this doesn't seem to do it either !
See Common lisp: How many argument can a function take?
It would be preferable to use (reduce #'+ list) instead (apply #'+ list) because apply is subject to the limit of number of argument a that function can take.
So your average function should looks like:
(defun average (list)
(/ (reduce #'+ list)
(length list)))
BTW, the code (length '(list)) returns 1 because it returns the lenght of a list containing the symbol "list".
There is no reason not to use APPLY or, better, REDUCE. Here REDUCE is the correct function.
If you program in Lisp, most of the time you have to use a symbol, naming your operation, followed by arguments. This is the general basic expression style in Lisp. You might expect that there are shorter ways to write something like reducing a list with a function. But there isn't, in basic Lisp.
(+ (list 1 2 3 4)) is an error because + expects numbers, not a list.
If you want to sum all numbers in a list, you have to use REDUCE. This operation is also known as folding.
Summing the numbers in a list:
(reduce #'+ (list 1 2 3 4))
Another simple way is to use LOOP:
(loop for n in (list 1 2 3 4) sum n)
Writing something like (length '(list)) makes no sense, since you are quoting a list. A quoted list is treated as data and not code. Since it is constant data, the result is always 1.
One of the Lisp ways to get to short programs is to build up a vocabulary of reusable functions. One doesn't use the shortest notation, but instead one is creating reusable functions with obvious names. Thus, if we sum a lot, we write a sum function:
(defun sum (list)
(reduce #'+ list))
Then average is:
(defun average (list)
(/ (sum list) (length list)))

Racket Lisp : comparison between new-if and if

(define (sqrt-iter guess x)
(if (good-enough? guess x)
guess
(sqrt-iter(improve guess x)
x)))
(define (improve guess x)
(average guess(/ x guess)))
(define (average x y)
(/ (+ x y) 2))
(define (good-enough? guess x)
(< (abs (- (square guess) x)) 0.0001))
(define (square x)
(* x x))
(define (sqrt-g x)
(sqrt-iter 1.0 x))
This is a program for sqrt. And the question is what happens when you attempts to use new-if to replace if with new-if.
(define (sqrt-iter guess x)
(if (good-enough? guess x)
guess
(sqrt-iter(improve guess x)
x)))
This is new if
(define (new-if predicate then-clause else-clause)
(cond (predicate then-clause)
(else else-clause)))
My opinion is the result of two program gonna be the same. because new-if and if can produce the same results.
However, new-if proved wrong, because it is a dead circle when I tried.
So, why?
new-if is a function. All the arguments to a function are evaluated before calling the function. But sqrt-iter is a recursive function, and you need to avoid making the recursive call when the argument is already good enough.
The built-in if is syntax, and only evaluates the then-branch or else-branch, depending on the value of the condition.
You can use a macro to write new-if.
This is the perfect example for demonstration the algebraic stepper!
In the the algebraic stepper you can see how the course of the computation differs from your expectation. Here you must pay notice to the differences in evaluation of, say, (new-if 1 2 3) and (if 1 2 3).
If you haven't tried the algebraic stepper before, see this answer to see what it looks like.
Since racket is an applicative procedure the 3rd argument to the new-if is (sqrt-iter(improve guess x) x)). Since sqrt-iter is recursive the 3rd argument never has a value assigned to it. Therefore you never move into the procedure of new-if to evaluate the function.

Common Lisp: making rules about input values

While coding a predicate that tests whether or not a number is divisible by all integers across a certain range, I was wondering if it is possible to make rules about input, maybe through the "declare" symbol?
Code:
(defun integer-divisiblep (n m i)
(declare (integer n m i))
(do ((x m (- x 1)))
((< x n) (return t))
(when (not (integerp (/ i x)))
(return nil))))
In this case I may like to specify that the input value "n" must be smaller than "m". Is there anyway to do this with an inbuilt function? I can't seem to find what I want with the declaration-identifiers on the Hyperspec.
Also, I'm using SBCL, if that makes a difference.
Common Lisp does not provide static type checks for argument types. Some Common Lisp compilers do it as an extension, most notably CMUCL and SBCL. These static type checks use the typical declarations of variable types provided by DECLARE. You need to see the syntax of the various types to see what can be declared.
Dynamic checks at runtime are best done with CHECK-TYPE and ASSERT.
In this case I may like to specify that the input value "n" must be smaller than "m"
This is something like:
(assert (and (numberp m) (numberp n) (< n m)) (m n))
The list (m n) at the end is a list of variables which can be interactively set by the user, if the assert is violated. After entering a different value, the assertion will be checked again, until the assertion is satisfied.

Conditional anaphoric collection best practices?

I trying to iterate through a sequence, conditionally perform an operation on each element and then collect it (but only if it matched the criteria). Here is a simplified example that works, I just want to know if this is proper or best practice in lisp:
(loop for n in '(1 2 3 4 5)
when (when (equal (mod n 2) 0) n )
collect it)
yields
(2 4)
This works, it just looks funny to me and not so much of the when-when but because I feel like I am having to rig the condition to return what I want. I get that the anaphoric it works on the evaluation of the when but this just seems a little artificial to me. Am I missing something? I have only been a lisper for a few weeks.
Edit: Actually, I am somewhat confused when I tried to apply this. What I really want to do is this:
(loop for n in '(1 2 3 4 5)
when (when (equal (mod n 2) 0) n)
collect it
do (format t "~A" it))
but the second it seems to become unbound... how do I do this?
I don't see why you need anaphor here.
(loop for n in '(1 2 3 4 5)
when (evenp n)
collect n and
do (format t "~A" n))
Delete the keyword AND if you want the FORMAT unconditionally.

Odd question relating to project euler 72 (lisp)

I recognize that there's an obvious pattern in the output to this, I just want to know why lispbox's REPL aborts when I try to run anything > 52. Also, any suggestions on improving the code are more than welcome. ^-^
(defun count-reduced-fractions (n d sum)
(setf g (gcd n d))
(if (equal 1 d)
(return-from count-reduced-fractions sum)
(if (zerop n)
(if (= 1 g)
(count-reduced-fractions (1- d) (1- d) (1+ sum))
(count-reduced-fractions (1- d) (1- d) sum))
(if (= 1 g)
(count-reduced-fractions (1- n) d (1+ sum))
(count-reduced-fractions (1- n) d sum)))))
All I get when I call
(count-reduced-fractions 53 53 0)
is
;Evaluation aborted
It doesn't make much sense to me, considering it'll run (and return the accurate result) on all numbers below that, and that I could (if i wanted to) do 53 in my head, on paper, or one line at a time in lisp. I even tested on many different numbers greater than 53 to make sure it wasnt specific to 53. Nothing works.
This behaviour hints at a missing tail call optimization, so that your recursion blows the stack. A possible reason is that you have declaimed debugging optimization.
By the way, you don't need to make an explicit call to return-from. Since sum is a self-evaluating symbol, you can change this line
(return-from count-reduced-fractions sum)
to
sum
edit: Explanation of the proposed change: "sum" evaluates to its own value, which becomes the return value of the "if" statement, which (since this is the last statement in the defun) becomes the return value of the function.
edit: Explanation of declaimed optimization: You could add the following to your top level:
(declaim (optimize (speed 3)
(debug 0)))
or use the same, but with declare instead of declaim as the first statement in your function. You could also try (space 3) and (safety 0) if it doesn't work.
Tail call optimization means that a function call whose return value is directly returned is translated into a frame replacement on the stack (instead of stacking up), effectively "flattening" a recursive function call to a loop, and eliminating the recursive function calls. This makes debugging a bit harder, because there are no function calls where you expect them, resp. you do not know how "deep" into a recursion an error occurs (just as if you had written a loop to begin with). Your environment might make some default declamations that you have to override to enable TCO.
edit: Just revisiting this question, what is g? I think that you actually want to
(let ((g (gcd n d)))
;; ...
)
My guess is that there's a built-in stack depth limit with lispbox. Since Common Lisp does not guarantee tail-recursive functions use constant stack space, it's possible that every invocation of count-reduced-fractions adds another layer on the stack.
By the way, SBCL runs this algorithm without problem.
* (count-reduced-fractions 53 53 0)
881
* (count-reduced-fractions 100 100 0)
3043
As a matter of style, you could make d and sum optional.
(defun test (n &optional (d n) (sum 0)) .. )
Probably a Stack Overflow (heh).