Первое и чрезвычайно важное: используйте автоматический отступ.
(defun diagonal? (x y array)
(loop for line from 0 to 19 do
(let (col (aref array line)) (
(if (= col -1) (return-from diagonal? t))
(let (diag (= (abs (- x line)) (abs (- y col)))) (
if (= diag T) (return-from diagonal? NIL))
)
)))
return T
)
Тогда ваш код выглядит странно с длинными строками: никогда не ставьте круглые скобки на своей собственной строке и никогда не заканчивайте строку открытыми скобками.
Улучшено:
(defun diagonal? (x y array)
(loop for line from 0 to 19 do
(let (col (aref array line))
((if (= col -1)
(return-from diagonal? t))
(let (diag (= (abs (- x line))
(abs (- y col))))
(if (= diag T)
(return-from diagonal? NIL))))))
return T)
Второе: LET
ожидает список привязок.Одиночная привязка - это переменная или (variable value)
:
(defun diagonal? (x y array)
(loop for line from 0 to 19 do
(let ((col (aref array line)))
((if (= col -1)
(return-from diagonal? t))
(let ((diag (= (abs (- x line))
(abs (- y col)))))
(if (= diag T)
(return-from diagonal? NIL))))))
return T)
Третье: LET ожидает тело форм Lisp.Это ноль или более форм Lisp:
(defun diagonal? (x y array)
(loop for line from 0 to 19 do
(let ((col (aref array line)))
(if (= col -1)
(return-from diagonal? t))
(let ((diag (= (abs (- x line))
(abs (- y col)))))
(if (= diag T)
(return-from diagonal? NIL)))))
return T)
Четвертый: =
ожидает числа в качестве аргументов.T
это не число.=
уже возвращает T
или NIL
, которые мы можем проверить.
(defun diagonal? (x y array)
(loop for line from 0 to 19 do
(let ((col (aref array line)))
(if (= col -1)
(return-from diagonal? t))
(if (= (abs (- x line))
(abs (- y col)))
(return-from diagonal? NIL))))
return T)
Пятый: return T
не является допустимой формой Лисп.Мы можем просто вернуть T
напрямую.
(defun diagonal? (x y array)
(loop for line from 0 to 19 do
(let ((col (aref array line)))
(if (= col -1)
(return-from diagonal? t))
(if (= (abs (- x line))
(abs (- y col)))
(return-from diagonal? NIL))))
T)
Шестое: нам не нужно LET
для col
, мы можем заменить его на FOR
в LOOP
.
(defun diagonal? (x y array)
(loop for line from 0 to 19
for col = (aref array line)
do
(if (= col -1)
(return-from diagonal? t))
(if (= (abs (- x line))
(abs (- y col)))
(return-from diagonal? NIL))))
T)
Седьмое: кратное IF
может быть записано как одно COND
.
(defun diagonal? (x y array)
(loop for line from 0 to 19
for col = (aref array line)
do (cond ((= col -1)
(return-from diagonal? t))
((= (abs (- x line))
(abs (- y col)))
(return-from diagonal? nil))))
t)
Восьмое: for from 0 to n
можно заменить на below (+ n 1)
или upto n
(defun diagonal? (x y array)
(loop for line below 20
for col = (aref array line)
do (cond ((= col -1)
(return-from diagonal? t))
((= (abs (- x line))
(abs (- y col)))
(return-from diagonal? nil))))
t)
Девятое: поскольку (RETURN-FROM ... T)
возвращается из функции, которая по умолчанию возвращает T
, мы можем заменить ее на предложение UNTIL
в цикле:
(defun diagonal? (x y array)
(loop for line below 20
for col = (aref array line)
until (= col -1)
when (= (abs (- x line))
(abs (- y col)))
do (return-from diagonal? nil))
t)
Десятое: поскольку col - это просто итерация значений массива:
(defun diagonal? (x y array)
(loop for line below 20
for col across array
until (= col -1)
when (= (abs (- x line))
(abs (- y col)))
do (return-from diagonal? nil))
t)
Одиннадцатое: предложение @Coredump, используйте NEVER
.По умолчанию возвращаемое значение LOOP
теперь равно T
.Возврат только тогда nil
, когда предложение never
не выполнено.
(defun diagonal? (x y array)
(loop for line below 20
for col across array
until (= col -1)
never (= (abs (- x line))
(abs (- y col)))))