I have a quick question. I understand recursion. I also understand why there is a need to implement a depth limit for recursion. My question deals with the randomness of when the maximum depth error is displayed.
Consider the following method, which simply adds all numbers from 1 to the value being passed in:
(defun sum (x)
(cond
((= x 0) 0)
(t (+ x (sum (- x 1))))))
If I call:
(sum 50)
I get:
1275
If I call:
(sum 100)
I get:
Debugger entered--Lisp error: (error "Lisp nesting exceeds `max-lisp-eval-depth'")
That's fine, but now when I dismiss the debugger and call:
(sum 50)
I get the same error message as above for (sum 100).
Why does the error message seem to be coming up inconsistently? I would assume that after I back the value back down to 50, it would calculate normally as it did prior. Is there some flag I need to reset somewhere? Maybe I'm simply misunderstanding the error message. Any help would be greatly appreciated.
EDIT: I forgot to add that if I exit out of Emacs and open it back up, I'm able to calculate the value with 50 as the argument again, but as soon as I try the value of 100 and get the error, I can no longer use 50.
The *Debugger* buffer is a buffer like any other. So when you use window-movement operations to switch to another buffer, it has no effect on the fact that you're within a debugging session.
You can see that in the modeline where the part showing the major mode name is surrounded by square brackets (potentially several such brackets if you're within several such recursive-edits).
You can exit the debugging session by hitting c (for "Continue") or q in the *Debugger* buffer. You can also exit it like any other recursive-edit, by hitting for example ESC ESC ESC (keyboard-escape-quit) or you can also use C-] (abort-recursive-edit).
Related
I'm new to Common Lisp and ran into a performance thing that just struck me as weird. I'm checking if a number is divisible by 10 using rem in a loop. If I move the check into a function, it runs 5x slower. What would cause that?
I'm running sbcl 1.4.5 on 64 bit Ubuntu 18.04.
(defun fn (x)
(= 0 (rem x 10))
)
(defun walk-loop-local (n)
(loop for i from 1 to n do
(= 0 (rem i 10))
))
(defun walk-loop-func (n)
(loop for i from 1 to n do
(fn i)
))
(time (walk-loop-local 232792560))
(time (walk-loop-func 232792560))
I'd expect the time to be the same (and a lot faster, but that's a separate question). Instead, here's the output,
CL-USER> (load "loops.lisp")
Evaluation took:
0.931 seconds of real time
0.931389 seconds of total run time (0.931389 user, 0.000000 system)
100.00% CPU
2,414,050,454 processor cycles
0 bytes consed
Evaluation took:
4.949 seconds of real time
4.948967 seconds of total run time (4.948967 user, 0.000000 system)
100.00% CPU
12,826,853,706 processor cycles
0 bytes consed
Common Lisp allows dynamic redefinition of functions: if you redefined fn during the approx. 5 seconds of your second test, the running loop would switch to calling the new definition of fn while running. This features comes with some constraints on how to compile function calls and how to optimize them when needed.
As pointed out by RainerJoswing in comments, the above is an over-simplification, there are cases where the compiler may assume functions are not redefined (recursive functions, functions in the same file), see 3.2.2.3 Semantic Constraints, for example:
A call within a file to a named function that is defined in the same
file refers to that function, unless that function has been declared
notinline. The consequences are unspecified if functions are redefined
individually at run time or multiply defined in the same file.
A function mixes error checking and the computations you want it to perform. At function call boundaries you typically have a prologue where your inputs are checked, and an epilogue where results might be "boxed": if the compiler knows that locally a variable is always a single-float, it can use a raw representation of floats during the extent of the function, but when returning the result, it should be a valid Lisp type, which means coercing it back to a tagged value, for example.
The SBCL compiler tries to ensure the code is safe, where safe means never invoking code that has undefined behaviour in the Lisp specification. Note however that if you call fn with a string input, the code is expected to detect the type error. Unlike C, a type-error at runtime in Lisp is well-defined (as long as the declared type, which defaults to T, encompasses all possible values at runtime). And so, compiling Lisp code for safety tends to add a lot of error checking at multiple points of the program.
Optimizing code consists in removing checks that are guaranteed to be always true, eliminating dead branches in the generated code.
For example, if you consider fn alone, you can see that it has to check its input every time it is called, because it might very well be called with a string input. But when you directly inline the operation, then the index i can be statically determined to be an integer, which allows calls to = and rem to be applied without (much) error checking.
Optimization in SBCL happens because there is a static analysis which maps variables to elements of the type lattice of Lisp (and and or are basically the greatest lower bound and lowest upper bound for types, with types T and type nil at both ends). SBCL reports only errors that are sure to happen: you have an error if you call a function that accepts integers from 0 to 5 if you call it with an input that is known to always be above 5 or below zero (both sets have no intersection), but you have no warning if you call it with an integer between 2 and 10. This is safe because the compiler can defer error checking at runtime, contrary to other languages where the runtime has no sense of types (trying to warn everytime the code might have errors would result in a lot of warnings given the open-worldness of Lisp).
You can (declaim (inline fn)) in your file and then the performance will be identical to the first version. A rule of thumb is that inside a function, things are a bit more static than in the global environment: local functions cannot be redefined, local variables can have their types precisely defined, etc. You have more control about what is always true.
Note that the overhead of error checking is a problem if it is executed a lot of time (relatively to the rest of the code). If you fill a big array with single-floats and apply numerical code on it, it makes sense to use a specialized array type, like (simple-array single-float), or to declare local variables to be floats with (declare (type single-float x)), so that you don't check that each value is effectively a float. In other cases, the overhead is not high enough to spend too much time reducing it.
You are using the SBCL compiler:
(defun walk-loop-local (n)
(loop for i from 1 to n do
(= 0 (rem i 10))))
I think your code does nothing in the loop iteration. It gets optimized away, since the value of = form is not used anywhere and there are no side-effects.
Thus there is no overhead, since there is no code.
Use (disassemble #'walk-local-form) to check the compile code.
If I move the check into a function, it runs 5x slower. What would cause that?
Instead of doing nothing, in each iteration the function gets called and executes your code.
Actually measuring calling overhead
(defparameter *i* nil)
(defun walk-loop-local (n)
(loop for i from 1 to n do
(setf *i* (= 0 (rem i 10)))))
(defun fn (x)
(setf *i* (= 0 (rem x 10))))
(defun walk-loop-func (n)
(loop for i from 1 to n do
(fn i)))
In above case the code doesn't get removed.
CL-USER> (time (walk-loop-local 232792560))
Evaluation took:
5.420 seconds of real time
5.412637 seconds of total run time (5.399134 user, 0.013503 system)
99.87% CPU
6,505,078,020 processor cycles
0 bytes consed
NIL
CL-USER> (time (walk-loop-func 232792560))
Evaluation took:
6.235 seconds of real time
6.228447 seconds of total run time (6.215409 user, 0.013038 system)
99.89% CPU
7,481,974,847 processor cycles
0 bytes consed
You can see that the function call overhead isn't that large.
Every function call adds an overhead. This is what you are measuring.
You could declaim the function fn to be inline and also try modifying the compiler flags to optimize for runtime execution (opposed to debug information or safety). I'm on the phone now, but could add the hyperspecs link if needed.
BR, Eric
I am starting to learn Scheme and well, I am trying to implement my own max function that gives the max of just two parameters.
I've written the function like this:
(define (myMax x y) (cond ((> x y) (x)) ((< x y) (y))))
But every time I try calling it (myMax 100 40)(example) I get an error that says:
The object 100 is not applicable.
Searching the documentation of GNU's MIT-Scheme, they say:
This type indicates an error in which a program attempted to apply an object that is not a procedure. The object being applied is saved in the datum field, and the arguments being passed to the object are saved as a list in the operands field.
But what is that supposed to mean?
Weird thing is, I implemented a very simple function that adds two numbers and it works just fine, also an absolute value function that works fine; could it be the conditional is messed up?
Thanks
In Scheme (function-name arguments) is the syntax for applying a function to the given arguments. So (x) means "apply the function x to no arguments". However x is not a function, which the compiler is trying to tell you by saying that it's not "applicable".
Since you don't actually want to apply x, simply remove the parentheses around it. Same for (y) in the other case of the cond.
I am brand spanking new to scheme. To the extent that tonight is the first time I've ever played around with it aside from what a powerpoint slide explained to me in class. I have to write a scheme program that takes a user input operator and then performs that operation on the numbers that follow it. (in other words implement my own version of schemes built-in '+', '*', etc operators). The catch is that I have to use recursion. Trying to maneuver my way around this scheme syntax is making it very difficult for me to even figure out where to start.
So, I decided to start with some code that at least recursively sums up values entered by the user (without worrying about recognizing the user inputting an operator and parentheses). I just plain can't figure out how to make it work. Here's what I'm trying:
(define run (lambda (x)
(cond
((eqv? x "a") (display x) )
(else (+ x (run(read))))
)))
(run (read))
The condition to check if x equals "a" was intended to be a way for me to break the recursion right now. In the final version, the input will be in between a set of parenthesis, but I thought I'd cross that bridge when I come to it. Anyways, the code just keeps accepting input, and never stops. So, the condition to display x is never getting called I guess. I know I'm probably doing everything wrong, and I would really appreciate some pointers.
EDIT: OK, I'm at least starting to realize that something isn't making sense. Such as my displaying x won't actually give the sum since I'm not storing the sum in x in any way. However, I still don't understand why the code isn't at least stopping when I enter the letter a.
EDIT 2: I've got it to work but only when the condition is equal to 1. How can I get it to recognize an input of a char or better yet a right parenthesis to get it to end the recursion just like it is with the 1? :
(define run (lambda (x)
(cond
((eq? x 1) 0)
(else (+ x (run(read))))
)))
(run (read))
End-Of-File (EOF) marks the end of input. Scheme has a procedure eof-object? for this. Your code is basically correct:
(define (run x)
(if (eof-object? x)
0
(+ x (run (read)))))
You end the run using Control-D. If for some reason you don't have access to eof-object? just use a special character like X. In that case your test would be (eq? x #\X)
(define (addition-loop)
(let ((answer (read)))
(if (number? answer)
(+ answer (addition-loop))
0)))
This will break as soon as you enter something that isn't a number.
In addition as you can see, you can have a function of zero arguments.
Anyways the problem with your code is when you enter a into read, it's value it actually the same a 'a or (quote a), rather than "a".
(eqv? 'a "a")
;Value: #f
I know how to calculate the sum of the digits of a number:
(define (sum-of-digits x)
(if (= x 0) 0
(+ (modulo x 10)
(sum-of-digits (/ (- x (modulo x 10))
10)))))`
But I just don't have a clue to make a count of the digits. And also don't know how to do that by a linear iterative progress.
Thanks!!
You are very close to the answer.
In order to figure out how to change sum-of-digits into count-of-digits, try writing some test cases. A test case must include an example of calling the function, and also the expected result.
As a side note, this is an example of generative recursion, and you shouldn't be tackling it until you've done a bunch of problems like "add the numbers in a list", "count the elements in a list", etc.
Some hints regarding each of your questions:
For counting digits, you don't need to add the current digit (as is the case in your code). Just add 1
There are several strategies for transforming a recursive solution (like yours) to a tail recursion (one that generates a linear iterative progress). Here's a short list:
Add an extra parameter to the function to hold the result accumulated so far
Pass the initial value for the accumulator the first time you call the procedure, typically this is the same value that you'd have returned at the base case in a "normal" (non-tail-recursive) recursion.
Return the accumulator at the base case of the recursion
At the recursive step, update the accumulated result with a new value and pass it to the recursive call
And the most important: when the time comes to call the recursion, make sure to call it as the last expression with no "additional work" to be performed.
Sorry for the vague title, I guess I just don't understand my problem well enough to ask it yet but here goes. I want to write a recursive function which takes a sequence of functions to evaluate and then calls itself with their results & so on. The recursion stops at some function which returns a number.
However, I would like the function being evaluated at any point in the recursion, f, to be wrapped in a function, s, which returns an initial value (say 0, or the result of another function i) the first time it is evaluated, followed by the result of evaluating f (so that the next time it is evaluated it returns the previously evaluated result, and computes the next value). The aim is to decouple the recursion so that it can proceed without causing this.
I think I'm asking for a lazy-seq. It's a pipe that's filling-up with evaluations of a function at one end, and historical results are coming out of the other.
Your description reminds me some of reductions? Reductions will perform a reduce and return all the intermediate results.
user> (reductions + (range 10))
(0 1 3 6 10 15 21 28 36 45)
Here (range 10) creates a seq of 0 to 9. Reductions applies + repeatedly, passing the previous result of + and the next item in the sequence. All of the intermediate results are returned. You might find it instructive to look at the source of reductions.
If you need to build a test (check for value) into this, that's easy to do with an if in your function (although it won't stop traversing the seq). If you want early exit on a condition being true, then you'll need to write your own loop/recur which amalloy has already done well.
I hate to say it, but I suspect this might also be a case for the State Monad but IANAMG (I Am Not A Monad Guy).
I don't understand your entire goal: a lot of the terms you use are vague. Like, what do you mean you want to evaluate a sequence of functions and then recur on their results? These functions must be no-arg functions (thunks), then, I suppose? But having a thunk which first returns x, and then returns y the next time you call it, is pretty vile and stateful. Perhaps trampoline will solve part of your problem?
You also linked to something you want to avoid, but seem to have pasted the wrong link - it's just a link back to this page. If what you want to avoid is stack overflow, then trampoline is likely to be an okay way to go about it, although it should be possible with just loop/recur. This notion of thunks returning x unless they return y is madness, if avoiding stack overflow is your primary goal. Do not do that.
I've gone ahead and taken a guess at the most plausible end goal you might have, and here's my implementation:
(defn call-until-number [& fs]
(let [numeric (fn [x] (when (number? x) x))]
(loop [fs fs]
(let [result (map #(%) fs)]
(or (some numeric result)
(recur result))))))
(call-until-number (fn [] (fn [] 1))) ; yields 1
(call-until-number (fn [] (fn [] 1)) ; yields 2
(fn [] 2))
(call-until-number (fn f [] f)) ; never returns, no overflow