Я сбивал «Learn You a Haskell» и нашел в самом низу this page способ найти тройной (a, b, c), представляющий правый треугольник с указанным периметром, который я нашел очень элегантный -Поиск правильных треугольников в Лиспе
ghci> let rightTriangles' = [ (a,b,c) | c <- [1..10], b <- [1..c], a <- [1..b], a^2 + b^2 == c^2, a+b+c == 24]
и мне было интересно, если есть способ сделать это в Лиспе аналогичным образом/без явного использования петель. Вот что я сделал -
(defun sq (x) (expt x 2))
(loop for c from 1 to 10 do
(loop for a from 1 to c do
(let ((b (- 24 a c)))
(if (= (sq c) (+ (sq a) (sq b)))
(format t "~a, ~a, ~a~%" a b c)))))
, но это явно не выглядит так же хорошо, как версия Haskell, и он также выводит решение в два раза ((6, 8, 10) и (8, 6, 10)), потому что a
идет от 1 до c
.
Ну, код Haskell не вычисляет b так, как вы. Он на самом деле петли c от 1 до 10, b от 1 до c и от 1 до b. (ОК, он не работает, он генерирует последовательности.) Это объясняет, почему Haskell печатает только одно решение, в то время как ваш LISP генерирует два. –
Нет встроенной функции для генерации последовательностей в LISP; вы можете сделать это с рекурсией хвоста, но использование цикла легче читать и, вероятно, немного более эффективно. Вы можете подражать Haskell функцией * (defun sequence (ab) (цикл для i от a до b собирать i)) * –
Если вы добавите во внешний цикл 'named outer' и имеете в истинном состоянии' (return-from external) ', что сделало бы это * логически правильным. Но уродливый. –