Is increasing max-lisp-eval-depth recommended?

Discussion of Emacs Lisp
Post Reply
zck
Posts: 2
Joined: Thu Feb 18, 2010 9:31 pm

Is increasing max-lisp-eval-depth recommended?

Post by zck » Thu Aug 05, 2010 9:16 pm

I'm writing an implementation of Minesweeper for Emacs, and I have two functions that are mutually recursive and hit max-lisp-eval-depth on not-so-large game sizes (i.e., even 10x10 games cause this to happen). The basic algorithm is: the user picks a square. If that square is a zero, pick all the squares around that square that haven't previously been picked.

As far as I can tell, this solution is correct, but is simply too deep. I think there are two possible solutions to this problem:
  1. Simply increase max-lisp-eval-depth for the section of code that will run here. This would work, but I'd have to calculate it dynamically based on the minefield size. Googling has indicated that increasing it is not a problem, but I don't know whether there is a higher limit I should be worried about, or whether this is a bad idea for another reason. I would prefer to do this, as I believe my code is concise and straightforward as it is.
  2. Rewrite the code to simulate recursion -- creating a stack, marking the current cell as revealed, and if it wasn't previously revealed and it is zero, pushing the neighboring cells onto it, and looping. The downside here is that the code would be more complex and less elegant.
Thanks for any suggestions or further reading.

The offending code is as follows:

Code: Select all

(defun minesweeper-pick (x y &optional suppress-field) ;; Bug is here -- recursion is too deep: blows past max-list-eval-depth if you hit a sparse section of the field.
  "Select the square at position (x, y) to reveal. A user-facing function."
  (unless (minesweeper-is-revealed x y) ;; If (x, y) has already been picked, do nothing
    (let ((val (minesweeper-view-mine x y 't)))
      (if (eq val ?X) ;; the user has picked a mine.
	  (minesweeper-lose-game x y)
	(progn
	  (minesweeper-set-revealed x y 't)
	  (when (eq val ?0)
	    (minesweeper-pick-around x y)) ;; Here's the mutual recursion that is the problem.
	  (if (eq minesweeper-mines-left 0)
	      (mineweeper-win-game)
	    (unless suppress-field
	      (minesweeper-print-field))))))))

(defun minesweeper-pick-around (x y)
  "Pick all the squares around (x, y). As a precondition, (x, y) should be zero."
  (mapcar '(lambda (position)
	     (minesweeper-pick (car position) (cadr position) 't))
	  (minesweeper-neighbors x y))) ;; minesweeper-neighbors returns a list of all the valid neighbors of (x, y)

stackman
Posts: 28
Joined: Sat Oct 06, 2012 5:44 am

Re: Is increasing max-lisp-eval-depth recommended?

Post by stackman » Mon Oct 29, 2012 12:44 pm

I have used the following values for years without problem.

Code: Select all

(setq max-specpdl-size         100000
      max-lisp-eval-depth      100000)
The default values are really too low, I used to run into big problems with keyboard macros before changing them.

Post Reply