LISP Recursive Triangle
Minha chamada recursiva parece não estar funcionando, estou tentando fazer um triângulo dado um inteiro, e com a ajuda de vocês finalmente consegui fazer a string imprimir na mesma linha, a quantidade correta de vezes para 1 linha. No final da impressão da linha, tenho uma chamada recursiva que chama o triângulo para fazer outra linha, um caractere mais curto. Esta chamada parece nunca ser alcançada por algum motivo. Por favor, encontre o código abaixo, agradeço a todos antecipadamente por toda e qualquer ajuda, tudo é muito apreciado!
Nota: Em uma observação lateral, existe alguma maneira de interromper uma função em Lisp semelhante a uma instrução de retorno? Gostaria que a recursão parasse em k = 1 e não continuasse para k = 0.
(defun newTriangle (k)
(cond ((<= k 0) (princ '(Nope)))
((or (= k 1) (= k -1)) (princ 'a))
((> k 0) (make-string k :initial-element #\a))
(newTriangle (- k 1))))
(print (newTriangle 3))
amostra de triângulo de saída (3)
aaa
aa
a
amostra de triângulo de saída (-3)
aaa
aa
a
Respostas
Primeiro, você precisa decidir exatamente o que newTriangleestá fazendo. A chamada (print (newTriangle 3))sugere que newTriangledeve retornar uma string , que é então impressa pela chamada para print. Mas, a definição de OP de newTriangleé imprimir saída e retornar uma única linha do triângulo como uma string.
A chamada recursiva para newTrianglenunca é alcançada porque todos os casos possíveis para o valor de ksão esgotados antes que esta linha seja alcançada. Como ksó pode ser menor que zero, igual a zero ou maior que zero, e como todos esses casos são testados antes de atingir a chamada recursiva, ele nunca é alcançado. Observe também que o código OP tem a sintaxe errada para a parte final da condinstrução. A primeira expressão em uma condramificação é um teste, e a convenção é para usar taqui para uma ramificação que sempre será avaliada se alcançada. Mas, muitos casos não são necessários aqui.
Supondo que a newTrianglefunção não deva retornar uma string, mas deva imprimir um triângulo como efeito colateral , o que ela deve fazer? Se o número de entrada for maior que 0, ele deve imprimir uma linha com um número de caracteres igual ao número de entrada e então chamar a si mesmo com a entrada reduzida em um; caso contrário, não deve fazer nada:
(defun print-triangle (k)
(when (> k 0)
(princ (make-string k :initial-element #\a))
(terpri)
(print-triangle (- k 1))))
Essa definição é nomeada print-trianglepara enfatizar que ela imprime um triângulo como um efeito colateral, e porque kebab-case é idiomático em Lisps, e camelCase não é. Observe que cada vez que print-triangleé chamado com entrada maior que zero, uma string de comprimento correto é impressa e, em seguida, uma nova linha é impressa (com o nome obscuramente terpri, que apenas grava uma nova linha no fluxo de saída atual), antes de chamar print-trianglenovamente com kreduzido em 1.
Amostra de interação REPL:
CL-USER> (print-triangle 3)
aaa
aa
a
NIL
Se o objetivo é retornar uma string, uma abordagem seria chamar uma função auxiliar que mantém o resultado em um parâmetro:
(defun new-triangle (k)
(build-triangle k ""))
(defun build-triangle (k result)
(if (> k 0)
(build-triangle (- k 1)
(concatenate 'string
result
(make-string k :initial-element #\a)
(string #\newline)))
result))
Aqui, new-trianglepega um argumento inteiro e chama build-triangle, passando o argumento inteiro e uma string vazia na resultposição. A build-trianglefunção opera da mesma forma que print-triangleantes, mas em vez de imprimir as linhas, elas são concatenadas com result, junto com uma string contendo uma nova linha. Quando build-triangleterminar, a resultstring é retornada new-triangle. Observe que simplesmente chamar a new-trianglepartir do REPL imprimirá a string resultante como dados (ou seja, com aspas); chamar printo resultado de new-triangleimprimirá a string como dados e retornará a string. Para ver a string impressa sem aspas, formatpode ser usado; ou você pode usar o princqual imprimirá a string sem aspas e retornará a própria string:
CL-USER> (new-triangle 3)
"aaa
aa
a
"
CL-USER> (print (new-triangle 3))
"aaa
aa
a
"
"aaa
aa
a
"
CL-USER> (format t "~A" (new-triangle 3))
aaa
aa
a
NIL
CL-USER> (princ (new-triangle 3))
aaa
aa
a
"aaa
aa
a
"