99 Bottles of Beer/Lisp: Difference between revisions

From Rosetta Code
Content added Content deleted
(→‎{{header|newLISP}}: make language name consistent with website...)
m (Fixed syntax highlighting and duplicate headers.)
Line 4: Line 4:
{{collection|99 Bottles of Beer}}
{{collection|99 Bottles of Beer}}
[[99 Bottles of Beer]] done in Lisp-languages
[[99 Bottles of Beer]] done in Lisp-languages

<!--
See [[99 Bottles of Beer/Lisp]]
-->


<!-- still missing:
<!-- still missing:
Line 15: Line 11:
__toc__
__toc__


=={{header|ACL2}}==
===ACL2===
<lang Lisp>(defun bottles-of-beer (n)
<syntaxhighlight lang="lisp">(defun bottles-of-beer (n)
(if (zp n)
(if (zp n)
nil
nil
Line 29: Line 25:
(1- n)
(1- n)
(if (= n 2) 0 1))
(if (= n 2) 0 1))
(bottles-of-beer (- n 1)))))</lang>
(bottles-of-beer (- n 1)))))</syntaxhighlight>


=={{header|Common Lisp}}==
===Common Lisp===
===Sensible solution===
====Sensible solution====
<lang lisp>(defun bottles (x)
<syntaxhighlight lang="lisp">(defun bottles (x)
(loop for bottles from x downto 1
(loop for bottles from x downto 1
do (format t "~a bottle~:p of beer on the wall~@
do (format t "~a bottle~:p of beer on the wall~@
Line 40: Line 36:
~V[No more~:;~:*~a bottle~:p of~] beer on the wall~2%"
~V[No more~:;~:*~a bottle~:p of~] beer on the wall~2%"
bottles (1- bottles))))
bottles (1- bottles))))
</syntaxhighlight>
</lang>
and then just call
and then just call
<lang lisp>(bottles 99)</lang>
<syntaxhighlight lang="lisp">(bottles 99)</syntaxhighlight>


===Ridiculous===
====Ridiculous====
<lang lisp>(format t "~{~[~^~]~:*~D bottle~:P of beer on the wall~%~:*~D bottle~:P of beer~%Take one down, pass it around~%~D bottle~:P~:* of beer on the wall~2%~}"
<syntaxhighlight lang="lisp">(format t "~{~[~^~]~:*~D bottle~:P of beer on the wall~%~:*~D bottle~:P of beer~%Take one down, pass it around~%~D bottle~:P~:* of beer on the wall~2%~}"
(loop :for n :from 99 :downto 0 :collect n))</lang>
(loop :for n :from 99 :downto 0 :collect n))</syntaxhighlight>
The [http://www.lispworks.com/documentation/HyperSpec/Body/22_c.htm FORMAT function] is probably the most baroque (i.e. featureful almost to a fault) function in Common Lisp.
The [http://www.lispworks.com/documentation/HyperSpec/Body/22_c.htm FORMAT function] is probably the most baroque (i.e. featureful almost to a fault) function in Common Lisp.
To really drive this point home, try replacing each instance of <tt>~D</tt>
To really drive this point home, try replacing each instance of <tt>~D</tt>
Line 60: Line 56:
* <tt>~:P</tt> is for English plurals: it prints <tt>s</tt> if the last argument wasn't 1; it prints nothing otherwise. There's also <tt>~@P</tt> for <tt>y</tt>/<tt>ies</tt>, in case you were worried about that.
* <tt>~:P</tt> is for English plurals: it prints <tt>s</tt> if the last argument wasn't 1; it prints nothing otherwise. There's also <tt>~@P</tt> for <tt>y</tt>/<tt>ies</tt>, in case you were worried about that.
Note, by the way, how the emoticons <tt>:*~D</tt> and <tt>:P</tt> have shown up in the format string. FORMAT is so powerful, it's even self-aware about how silly it is.
Note, by the way, how the emoticons <tt>:*~D</tt> and <tt>:P</tt> have shown up in the format string. FORMAT is so powerful, it's even self-aware about how silly it is.
===Alternate solution===
====Alternate solution====
Bit of a beginner in Lisp, but this seems to work:
Bit of a beginner in Lisp, but this seems to work:
<lang lisp>
<syntaxhighlight lang="lisp">
(defun beer-verse (count)
(defun beer-verse (count)
"Recurses the verses"
"Recurses the verses"
Line 78: Line 74:
(beer-verse (- count 1))))
(beer-verse (- count 1))))
(beer-verse 99)
(beer-verse 99)
</syntaxhighlight>
</lang>

<!-- missing here:
<!-- missing here:
=={{header|Emacs Lisp}}==
===Emacs Lisp===
-->
-->


=={{header|newLISP}}==
===newLISP===
<lang newlisp>(for (n 99 1)
<syntaxhighlight lang="newlisp">(for (n 99 1)
(println n " bottles of beer on the wall," n " bottles of beer. Take one down, pass it around. ")
(println n " bottles of beer on the wall," n " bottles of beer. Take one down, pass it around. ")
(println (- n 1) "bottles of beer on the wall!"))
(println (- n 1) "bottles of beer on the wall!"))
Line 95: Line 92:
" bottles of beer on the wall" (rec ( - bottles 1))))(list bottles))
" bottles of beer on the wall" (rec ( - bottles 1))))(list bottles))


(rec 99)</lang>
(rec 99)</syntaxhighlight>


=={{header|Ol}}==
===Ol===
<lang scheme>
<syntaxhighlight lang="scheme">
(define nn 99)
(define nn 99)


Line 116: Line 113:
"Go to the store and buy some more, "
"Go to the store and buy some more, "
nn " bottles of beer on the wall.")
nn " bottles of beer on the wall.")
</syntaxhighlight>
</lang>


=={{header|PicoLisp}}==
===PicoLisp===
<lang PicoLisp>(de bottles (N)
<syntaxhighlight lang="picolisp">(de bottles (N)
(case N
(case N
(0 "No more beer")
(0 "No more beer")
Line 130: Line 127:
(prinl "Take one down, pass it around,")
(prinl "Take one down, pass it around,")
(prinl (bottles (dec 'N)) " on the wall.")
(prinl (bottles (dec 'N)) " on the wall.")
(prinl) )</lang>
(prinl) )</syntaxhighlight>


=={{header|Shen}}==
===Shen===
<lang Shen>(define bottles-h
<syntaxhighlight lang="shen">(define bottles-h
{ number --> string }
{ number --> string }
0 -> "No more beer"
0 -> "No more beer"
Line 144: Line 141:
X -> (let Msg (bottles-h X)
X -> (let Msg (bottles-h X)
(do (output "~A on the wall~%~A~%Take one down, pass it around~%~A on the wall~%~%" Msg Msg (bottles-h (- X 1)))
(do (output "~A on the wall~%~A~%Take one down, pass it around~%~A on the wall~%~%" Msg Msg (bottles-h (- X 1)))
(bottles (- X 1)))))</lang>
(bottles (- X 1)))))</syntaxhighlight>


=={{header|Wart}}==
===Wart===
<lang python>def (beer n)
<syntaxhighlight lang="python">def (beer n)
when (n > 0)
when (n > 0)
prn n " bottles of beer on the wall"
prn n " bottles of beer on the wall"
Line 154: Line 151:
prn n-1 " bottles of beer on the wall"
prn n-1 " bottles of beer on the wall"
prn ""
prn ""
beer n-1</lang>
beer n-1</syntaxhighlight>

Revision as of 19:34, 1 September 2022

99 Bottles of Beer/Lisp is part of 99 Bottles of Beer. You may find other members of 99 Bottles of Beer at Category:99 Bottles of Beer.

99 Bottles of Beer done in Lisp-languages


ACL2

(defun bottles-of-beer (n)
   (if (zp n)
       nil
       (prog2$ (cw (concatenate 'string
                   "~%"
                   "~N0 bottle~#1~[~/s~] of beer on the wall,~%"
                   "~n0 bottle~#1~[~/s~] of beer.~%"
                   "Take one down, pass it around,~%"
                   "~n2 bottle~#3~[~/s~] of beer on the wall.~%")
                   n
                   (if (= n 1) 0 1)
                   (1- n)
                   (if (= n 2) 0 1))
               (bottles-of-beer (- n 1)))))

Common Lisp

Sensible solution

(defun bottles (x)
  (loop for bottles from x downto 1
        do (format t "~a bottle~:p of beer on the wall~@
                      ~:*~a bottle~:p of beer~@
                      Take one down, pass it around~@
                      ~V[No more~:;~:*~a bottle~:p of~] beer on the wall~2%"
                   bottles (1- bottles))))

and then just call

(bottles 99)

Ridiculous

(format t "~{~[~^~]~:*~D bottle~:P of beer on the wall~%~:*~D bottle~:P of beer~%Take one down, pass it around~%~D bottle~:P~:* of beer on the wall~2%~}"
          (loop :for n :from 99 :downto 0 :collect n))

The FORMAT function is probably the most baroque (i.e. featureful almost to a fault) function in Common Lisp. To really drive this point home, try replacing each instance of ~D with ~R, and then with ~@R. Yes, this is all standard and dependable (dys?)functionality.

Explanation of the format string for the uninitiated:

  • ~{fmt~} expects the next argument to be a list (which is of the integers from 99 down to 0), and executes the format string fmt on each element. It is essentially a map or foreach.
  • ~[...~] is a case/switch. It executes the nth clause, where n is taken from the next argument. Since there is only one clause here, it will be executed only when the argument is 0.
  • ~^ will terminate formatting.
  • ~:* will back-up to the most-recently used argument.
  • ~D prints the next argument as a decimal number.
  • ~:P is for English plurals: it prints s if the last argument wasn't 1; it prints nothing otherwise. There's also ~@P for y/ies, in case you were worried about that.

Note, by the way, how the emoticons :*~D and :P have shown up in the format string. FORMAT is so powerful, it's even self-aware about how silly it is.

Alternate solution

Bit of a beginner in Lisp, but this seems to work:

(defun beer-verse (count)
  "Recurses the verses"
  (format t "~A bottle~:P of beer on the wall~%" count)
  (format t "~A bottle~:P of beer~%" count)
  (format t "Take one down, pass it round~%")
  (format t "~A bottle~A of beer on the wall~%~%"
	  (if (= count 1)
	      "No"
	      (- count 1))
	  (if (/= count 2)
	      "s"
	      ""))
  (if (> count 1)
      (beer-verse (- count 1))))
(beer-verse 99)


newLISP

(for (n 99 1) 
(println n " bottles of beer on the wall," n " bottles of beer. Take one down, pass it around. ")
(println (- n 1) "bottles of beer on the wall!"))

;;recursive
;;also shows list afterword
(define (rec bottles)
	(if (!= 0 bottles) (print "/n" bottles " bottles of beer on the wall" bottles " bottles of beer. 
\nTake one down, pass it around, " (- bottles 1) 
" bottles of beer on the wall" (rec ( - bottles 1))))(list bottles))

(rec 99)

Ol

(define nn 99)

(for-each (lambda (n)
   (let ((bottle (lambda (n) (if (eq? n 1) " bottle" " bottles")))
         (m (- n 1)))
      (print
         n (bottle n) " of beer on the wall, "
         n (bottle n) " of beer." "\n"
         "Take one down and pass it around, "
         (if (eq? m 0) "no more" m)
         (bottle m) " of beer on the wall.\n")))
   (reverse (iota nn 1)))
(print
   "No more bottles of beer on the wall, "
   "no more bottles of beer." "\n"
   "Go to the store and buy some more, "
   nn " bottles of beer on the wall.")

PicoLisp

(de bottles (N)
   (case N
      (0 "No more beer")
      (1 "One bottle of beer")
      (T (cons N " bottles of beer")) ) )

(for (N 99 (gt0 N))
   (prinl (bottles N) " on the wall,")
   (prinl (bottles N) ".")
   (prinl "Take one down, pass it around,")
   (prinl (bottles (dec 'N)) " on the wall.")
   (prinl) )

Shen

(define bottles-h
  { number --> string }
  0 -> "No more beer"
  1 -> "One bottle of beer"
  N -> (make-string "~A bottles of beer" N))

(define bottles
  { number --> number }
  0 -> 0
  X -> (let Msg (bottles-h X)
         (do (output "~A on the wall~%~A~%Take one down, pass it around~%~A on the wall~%~%" Msg Msg (bottles-h (- X 1)))
             (bottles (- X 1)))))

Wart

def (beer n)
  when (n > 0)
    prn n " bottles of beer on the wall"
    prn n " bottles of beer"
    prn "take one down, pass it around"
    prn n-1 " bottles of beer on the wall"
    prn ""
    beer n-1