Lisp jako alternativa k Javě


Original: http://www.norvig.com/java-lisp.html

V říjnu 1999 Sdělení ACM Lutz Prechelt měl zajímavý článek s názvem Porovnání Java vs C / C + + ekonomické aspekty mezilidských otázky , které žádaly, 38 programátorům implementovat verze programu v C, C + + , nebo Java . Závěry ukázaly, že Java je 3 nebo 4 krát pomalejší než C nebo C + + , ale že rozptyl mezi programátory byl větší než rozptyl mezi jazyky , což naznačuje, že jeden by mohl chtít trávit více času na školení programátorů než dohadovat se výběr jazyka . ( Nebo , což naznačuje, že byste měli najmout dobré programátory a vyhnout se ty špatné . )Rozptyl pro Javu byla nižší než C nebo C + + . ( Cynics by se říci, že Java vás nutí psát jednotně pomalé programy. ) Oceňuji tuhle práci , a doufám, že další studie tohoto druhu bude hotovo.

Ukazuje se, že mé naděje byly zodpovězeny . Za prvé, Prechelt publikoval další článek , který pokrývá Tcl , Python, Perl nebo REXX . Také Ron Garret (rozená Erann Gat ) dělal návaznou studii, ve které žádal programátorům psát Prechelt je testovací program v Lisp . Jeho výsledky ukazují, že výsledné programy v Lispu běžel rychleji než je průměr než je C, C + + nebo Java programy (i když nejrychlejší Lisp nebyl tak rychle, jak nejrychleji programu C ) a že programy v Lispu trvalo kratší dobu vývoje než jiné jazyky.

Nechtěl jsem účastí ve studii , ale poté, co jsem to viděl, jsem napsal verzi v Lisp . Trvalo mi asi 2 hodiny ( ve srovnání s řadou 2-8,5hodina pro ostatní programátory Lisp ve studii , 3-25 pro C / C + + a 4-63 pro Javu ) a já jsem skončil s 45 non- comment non- prázdné řádky (ve srovnání s rozsahem 51 až 182 pro Lisp a 107-614 pro jiné jazyky ) . (To znamená, že některé Java programátor trávil 13 řádky a 84 minut , aby funkčnost každého řádku mého programu Lisp ).

Tady je můj program:

; Peter Norvig – Programování Challange z Erann Gat :
; Http://www.flownet.com/ron/papers/lisp-java/
; Vzhledemseznam slov aseznam telefonních čísel , najít všechny způsoby, kterými
; Každé telefonní číslo lze vyjádřit jako seznam slov.
; Run: (hlavní ” word -list -file -name” ” telefonní číslo -file -name” )

( defvar * dict * nil
“Hash tabulky mapování telefonního čísla ( integer ) a seznam slov z
Vstup slovník, který produkují toto číslo . ” )

( defun main ( a volitelně ( dict ” dict ” ) ( nums ” nums ” ) ( dict -size 100) )
” Přečtěte si vstupní soubor ¨ dict a vložte ji do * dict * . Pak pro každý řádek v
Nums , vytisknout všechny překlady čísla do posloupnosti slov,
podle pravidel překladu . ”
( setf * dict * ( zatížení slovníku dict dict -size ) )
( s -open -file ( v nums )
( smyčka pro num = ( čtení -line v Kč) , zatímco num dělat
( print -translations num ( remove- if- ne # ” číslice – char -p num) ))))

( defun tisk – překlady ( num číslic a volitelné (start 0) ( slovy nula ) )
“Tisk každé možné překlad NUM do řetězce slov. ČÍSLICE
musí být WORD s odstraněnými ne- číslic. Na rekurzivní volání , START je
pozice v číslech , ve kterém se hledají další slova , a slova je seznam
slov nalezených pro výraz ( poté vždy ČÍSLICE 0 START ) . Takže pokud START dostane na konec
Čísel, tak máme řešení ve slovech . V opačném případě , pro každý prefix
ČÍSLICE , podívejte se do slovníku na slovo (a) , že namapovat na hodnotě
prefix ( počítány postupně jako N ) , a pro každý takový slova se snaží rozšířit
řešení s rekurzivní volání . K dispozici jsou dvě komplikace : ( 1 )
Pravidla říkají, že kromě slovníku slov , můžete použít jeden
číslice na výstupu , ale ne dvě číslice v řadě . Také ( a to se zdá
hloupé ), které nemůžete mítčíslice v místě, kde by se mohly objevit nějaké slovo .
Starám se to pomocí proměnné FOUND – WORD , pokud je false po smyčce ,
a poslední slovo, není číslice , zkuste rekurzivní volání, které tlačí
číslice. ( 2 )další komplikací je, žezřejmý způsob mapování
řetězce na celá čísla by mapoval R na 2 a ER na 02 , což je samozřejmě
stejně jako celé číslo 2 . Proto přidat před 1 ke každému číslu , a R
se 12 a ER se 102 . ”
( if ( > = počáteční délka ( číslice) )
( formát t “~: ~ ~ { a } ~ ~ ” % num ( reverzní slov) )
( let ( (nalezeno slovo – Kč)
(n 1) ); úvodní nuly problém
( smyčka pro i od začátku pod (délka číslic) do
( setf n ( + (* 10 n ) ( n-tého číslice číslice i )))
(loop slova v ( gethash n * dict *) do
( setf nalezeno slovo – t )
( print -translations num číslic ( 1 + i) ( zápory slovo slova ))))
(je-li ( a ( nebyl nalezen – slovo ) (není součástí ( numberp ( první slova ) ) ) )
( print -translations num číslice ( + začátek 1)
( cons ( n-tého číslice začnou číslice ) slova ) ) ))))

( defun zatížení slovníku (velikost souboru )
“Vytvořit Hashtable ze spisu slov ( jedno na řádek ) . Bere tip
pro první Hashtable velikosti . Každý klíč je telefonní číslo na slova ;
každá hodnota je seznam slov s tímto telefonní číslo. ”
( let ( ( tabulky ( make- hash – tabulky : test # ‘ EQL : Velikost S )))
( s -open -file ( v souboru)
(loop slova = (read -line v Kč) , zatímco slovo do
( stiskněte slovo ( gethash (slovo > číslo word) tabulka ))))
tabulka ) )

( defun slovo > číslo ( slovo)
” Přeložit slovo (řetězec ) na telefonní číslo , podle pravidel . ”
( let ( (n 1) ); úvodní nuly problém
( smyčka pro i od 0 níže ( délka slov )
CH = ( char slovem i) učinit
(je-li ( alfa- char -p ch) ( setf n ( + ( * 10 n) (char – > číslice ch) ))))
n ) )

( defun nth -místné (číslice i)
“I-tý prvek znakového řetězce číslic , jako celočíselný 0-9 . ”
( – . (Char – kód ( char číslic i ) ) # (znak kód # \ 0 )))

( defun char – > číslice ( ch)
” Převod znakčíslice v souladu s pravidly telefonní číslo. ”
( ecase (char – downcase ch )
( ( # \ e ) 0 )
( ( # \ j # \ n # \ q) 1)
( ( # \ r # \ w # \ x ) 2 )
( ( # \ d # \ s # \ r ) 3)
( ( # \ f # \ t ) 4)
( ( # \# \ m ) 5)
( ( # \ c # \ # i \ v ) 6 )
( ( # \ b # \ k # \ u) 7)
( ( # \ l # \ # o \ p ) 8)
( ( # \ # g \ h # \ z ) 9) ) )

Dvě poznámky : (1) Zpočátku jsem si myslel, že jsem porazil ostatní Lisp programátory (a všichni ostatní ), kterou skončil na 1,5 hodiny , ale pak jsem si uvědomil, že jsem podváděl : směry řekl kódu , jak jste zvyklí profesionálně a že znamená, že by se měl vyjádřit svou práci . Trvalo 30 minut více , aby v komentářích a trochu uklidit . (2) Měl jsem štěstí v tom, že když jsem byl skoro hotov , jsem si uvědomil, že jsem měl chybu : Nemohl jsem se rozlišovat mezi číslem 123 a 0123 . Chystal jsem se pro změnu čísel na řetězce ( to znamená, že 123 až 123 “a ” 0123 ” na 0123 ” ) , který by měl brát 15 minut nebo tak, když jsem si uvědomil , že bych mohl opravit chybu s jedním charakteru změny: změnit inicializaci n od 0 do 1 , tak, že se 123 reprezentován jako 1123 a 0123 jako 10123 . S tímto oprava , všechno se zdálo , že funguje .