Dlaczego stare języki BASIC (a może inne języki) używały numerów wierszy jako części kodu źródłowego?
Mam na myśli, jakie problemy to (próbował) rozwiązać?
Dlaczego stare języki BASIC (a może inne języki) używały numerów wierszy jako części kodu źródłowego?
Mam na myśli, jakie problemy to (próbował) rozwiązać?
Odpowiedzi:
BASIC należy rozpatrywać w kontekście współczesnych języków: wczesnego fortranu, kobolu i asemblera.
Wcześniej, kiedy zajmowałem się montażem 6502 bez etykiet, oznaczało to, że kiedy odkryłeś, że musisz dodać instrukcję gdzieś pośrodku ciasno upakowanego kodu (później dodałem NOP ), musisz przejść i powtórzyć cały skok adresy. To było czasochłonne.
Fortran był systemem opartym na numerach linii, który był wcześniejszy niż BASIC. W Fortranie kolumny 1-5 były numerami linii, które miały być użyte dla celów do rozgałęzienia. Kluczową sprawą w Fortranie było to, że kompilatory były nieco bardziej inteligentne niż interpreter BASIC, a dodanie kilku instrukcji było po prostu kwestią wybicia niektórych kart i umieszczenia ich w talii we właściwym miejscu.
Z drugiej strony BASIC musiał zachować wszystkie instrukcje w porządku. Nie było zbyt wiele koncepcji „kontynuacji poprzedniej linii”. Zamiast tego w Applesoft BASIC (jeden z powszechnie używanych dialektów, które znam i mogę znaleźć informacje) każda linia w pamięci była reprezentowana jako:
NN NN TT TT AA BB CC DD .. .. 00
Miał dwa bajty na adres następnej linii ( NN NN
). Dwa bajty dla numeru linii tej linii ( TT TT
), a następnie lista tokenów ( AA BB CC DD .. ..
), a następnie znacznik końca linii ( 00
). (Jest to strona 84-88 Inside the Apple // e )
Ważnym aspektem, na który należy zwrócić uwagę, patrząc na tę reprezentację pamięci, jest to, że linie mogą być przechowywane w pamięci poza kolejnością. Struktura pamięci była połączoną listą ze wskaźnikiem „następnej linii” w strukturze. Ułatwiło to dodawanie nowych linii między dwiema liniami - ale trzeba było ponumerować każdą linię, aby działała poprawnie.
Wiele razy pracując z BASIC, tak naprawdę pracowałeś w BASIC. W szczególności danym ciągiem był albo numer linii i instrukcje BASIC, albo polecenie podstawowego interpretera do RUN
lub LIST
. Ułatwiło to odróżnienie kodu od poleceń - cały kod zaczyna się od cyfr.
Te dwie informacje wskazują, dlaczego użyto liczb - możesz uzyskać wiele informacji w 16 bitach. Etykiety oparte na łańcuchach zajmowałyby znacznie więcej miejsca i są trudniejsze do zamówienia. Liczby są łatwe w obsłudze, zrozumiałe i łatwiejsze do przedstawienia.
Późniejsze dialekty BASIC, gdzie nie byli w interpreter cały czas byli w stanie pozbyć się każda linia ponumerowane i zamiast tylko potrzebne do numeru linii, które były Branża cele. W efekcie etykiety.
] PRINT "FOO"
został natychmiast uruchomiony przez tłumacza BASIC. To jest oświadczenie. Jeśli chcesz go uruchomić później, zrobisz to ] 10 PRINT "FOO"
i wtedy ] RUN
. W środowisku AppleSoft BASIC każdą instrukcję BASIC można uruchomić natychmiast lub z opóźnieniem - w systemie DOS było tylko kilka poleceń, które nie były prawidłowymi instrukcjami BASIC. Różnica między instrukcją teraz a instrukcją później była numerem linii. Możesz także zmodyfikować opóźnione polecenie, wprowadzając ponownie odpowiedni numer wiersza. Można również umieścić wiele instrukcji w jednym wierszu::
Na wczesnych mikrokomputerach edycja odbywała się liniowo. Nie można po prostu swobodnie poruszać się w kodzie źródłowym i edytować. Na dole ekranu był jeden wiersz, w którym można było wpisywać polecenia i wprowadzać kod. Reszta ekranu zawierała tylko kody do odczytu i dane wyjściowe poleceń. Jeśli chcesz edytować powiedz linię 90 w programie, który napisałeś „ EDIT 90
”, a zawartość linii 90
weszła do bufora edycji jednowierszowej. Po zredagowaniu linii naciśnij Enter, a lista programów została zaktualizowana. Potrzebne były więc numery linii, aby móc edytować program.
Kiedy edytory kodu stały się bardziej zaawansowane i pozwoliły Ci przesuwać kursor na liście kodów, nie potrzebujesz już numerów linii.
Jeśli myślisz o dialektach BASIC 8-bitowych domowych mikrokomputerów z lat 80-tych, to komputery te nie miały edytorów tekstu (chyba że kupiłeś jakieś edytory tekstu). Nie było możliwości, aby cały kod źródłowy programu BASIC był „otwarty w edytorze”, tak jak zrobiłbyś to podczas programowania. Programista nawet nie pomyślałby o programie jako pliku kodu źródłowego lub tekście.
Powiedzmy, że masz prosty program bez numerów linii w głowie:
FOR I=1 TO 42
PRINT I
NEXT I
Uruchamiasz komputer. Masz monit „gotowy” lub coś w tym rodzaju, a kursor siedzi w następnym wierszu. Jest to bardzo podobne do dzisiejszych środowisk REPL różnych języków skryptowych, choć nie tak ściśle oparte na liniach, a bardziej na ekranie. Więc nie całkiem jak dzisiejsze REPL, ale blisko.
Teraz, jeśli zaczniesz wchodzić do programu, możesz dostać błąd po pierwszym wierszu, ponieważ interpreter języka BASIC próbuje natychmiast go wykonać (i zapomnieć), a bez NEXT zakończenie pętli nie ma sensu. To nie jest edytor tekstu, w którym edytujesz tekst, tutaj podajesz polecenia do komputera!
Więc musisz powiedzieć, to jest linia programu, zapisz ją! Możesz mieć specjalne polecenie lub tylko symbol informujący, że hej, to jest linia programu, zapisz ją. Wyobraźmy sobie to:
#FOR I=1 TO 42
#PRINT I
#NEXT I
Ok, teraz nasz wymyślony interpreter języka BASIC przechował program i możesz go uruchomić. Ale teraz chcesz edytować wiersz PRINT. Jak ty to robisz? Nie jesteś w edytorze tekstu, nie możesz po prostu przesunąć kursora do linii i edytować go. Lub chcesz dodać kolejną linię jak LET COUNT=COUNT+1
w pętli. Jak wskazać, gdzie należy wstawić nową linię?
Numery linii rozwiązują to w bardzo łatwy, choć raczej niezdarny sposób. Jeśli wprowadzisz wiersz programu z już istniejącym numerem, stary wiersz zostanie zastąpiony. Teraz środowisko REPL oparte na ekranie staje się przydatne, ponieważ możesz po prostu przesunąć kursor do listy programów na ekranie, edytować wiersz na ekranie i nacisnąć ENTER, aby go zapisać. Wygląda na to, że edytujesz linię, podczas gdy w rzeczywistości edytujesz tekst na ekranie, a następnie zastępujesz całą linię nową na ekranie. Ponadto wstawianie nowych wierszy staje się łatwe, jeśli między nimi pozostawisz nieużywane liczby. Aby zademonstrować:
10 FOR I=1 TO 42
20 PRINT I
30 NEXT I
Po ponownym wejściu do linii 20 ze zmianami i dodaniu nowych linii może być
5 LET COUNT=0
10 FOR I=1 TO 42
20 PRINT "Index", I
25 LET COUNT=COUNT+1
30 NEXT I
Zaletą (lub przekleństwem, ponieważ umożliwia słynny kod BASIC spaghetti) jest możliwość używania numerów linii jako konstrukcji języka, przynajmniej jako celu poleceń GOTO
AND GOSUB
. Można to zastąpić etykietami, ale użycie numerów linii jest znacznie prostsze do zaimplementowania w interpretera BASIC, co wciąż było wyraźną zaletą w typowym 8-bitowym komputerze domowym lat 80.
Co ważniejsze, z punktu widzenia doświadczenia użytkownika numery linii są naprawdę zaskakująco łatwym, ale kompletnym interfejsem do edycji kodu. Wystarczy wpisać linię zaczynającą się od cyfry, aby wstawić nowy kod. Służy LIST 100-200
do wyświetlania linii 100-200. Aby edytować linię, wyświetl ją na ekranie, edytuj tekst na ekranie i ponownie wprowadź linię. Aby usunąć linię, edytuj ją, aby była pusta, to znaczy po prostu podaj numer linii bez niczego po nim. Jeden akapit, aby to opisać. Porównaj próbę opisania użycia starych edytorów tekstu, takich jak edlin z DOS, ed lub ex z Uniksa: potrzebujesz jednego akapitu (tylko niewielka hiperbola), aby wyjaśnić, w jaki sposób użytkownik może z nich wyjść, gdy został uruchomiony przypadkowo!
Inne odpowiedzi wyjaśniają, jak powstały numery linii. Próbuję tutaj wyjaśnić, dlaczego numery linii przetrwały tak długo, jak przetrwały, w jaki sposób rozwiązują rzeczywisty problem: oferowali sposób na faktyczne programowanie bez prawdziwego edytora, w bardzo prosty sposób. Kiedyś właściwe, łatwe w użyciu pełnoekranowe edytory tekstu stały się głównym sposobem edytowania kodu, zarówno ze znikającymi ograniczeniami sprzętowymi, jak i po przezwyciężeniu bezwładności ludzi dostosowujących nowe rzeczy, wtedy dialekty BASIC oparte na numerach linii dość szybko zniknęły z użycia, ponieważ podstawowy problem użyteczności, który rozwiązali, nie był już problemem.
W czasach, w których opracowywano Basic, najlepszym dostępnym urządzeniem we / wy był teletyp. Edycja programu polegała na wydrukowaniu (na papierze) listy całego programu lub jego interesującej części, a następnie wpisaniu linii zastępczych numerami linii.
Dlatego też domyślna numeracja linii wynosiła 10, więc między istniejącymi liniami nie byłyby używane liczby.
ren
polecenie, aby zmienić numerację. Typowe wywołanie to ren 10, 10
(zmiana numeracji od dziesiątej, zwiększanie o dziesięć - zachowanie domyślne, jeśli tylko się wpisze ren
. Komendy goto
i gosub
i then (linenumber)
zostaną automatycznie zaktualizowane. Ale to zdecydowanie nie było dostępne w najwcześniejszych BASICACH. Ale IIRC było dostępne w Apple Integer Basic, Applesoft FP basic, TI Basic / Extended Basic, MS Basic / GW Basic itp.
„Numery linii” oznaczają kilka różnych rzeczy.
Przede wszystkim pamiętaj, że koncepcja „linii” nie istniała od zawsze. Wiele języków programowania w tej erze używało kart dziurkowanych , a posiadanie numerów sekwencyjnych (zwykle w kilku ostatnich kolumnach karty) pomogło ci odzyskać talię w odpowiedniej kolejności, jeśli ją upuściłeś, lub coś strasznego wydarzyło się w czytniku kart. Były maszyny, aby to zrobić automatycznie.
Numery wierszy stosowane jako cele GOTO
instrukcji to zupełnie inna koncepcja. W FORTRAN IV były one opcjonalne i poprzedzały stwierdzenie (w kolumnach 1-5). Oprócz tego, że jest łatwiejsze do wdrożenia niż etykiety swobodne, pojawiła się także koncepcja obliczonego i przypisanego GOTO , która pozwoliła ci przejść do dowolnego numeru linii. Było to coś, czego większość współczesnych języków programowania nie ma (chociaż switch
instrukcje się zbliżają), ale była to znana sztuczka dla asemblerów.
BASIC wywodzi się z FORTRAN i miał być prostszy w implementacji i zrozumieniu, dlatego zmuszanie każdej „linii” do posiadania numeru linii (zarówno w celu sekwencjonowania, jak i celu GOTO
/ GOSUB
instrukcji) było prawdopodobnie decyzją projektową z tego powodu.
goto array_of_labels[some_computation()];
GOTO
(lub ASSIGN
) i oryginalnej aka arytmetyki aka trójdrożnej IF
oraz (rzadko używanych) alternatywnych zwrotów CALL
i sortowania celów (prawdopodobnie ograniczników) DO
i FORMAT
instrukcji. W innych stwierdzeniach były one opcjonalne.
GOTO 1000+N*100
aby emulować switch
instrukcję.
Zacząłem programować w języku COBOL, który używał numerów linii w kolumnach 1-6 każdej linii. Ponieważ w latach 70. nie było IDE, wszystko zrobiono za pomocą kart perforowanych, a numer linii wykorzystano do zidentyfikowania, które linie w oryginalnym źródle miały zostać zastąpione, a które nowe linie dodane. Zwiększaliśmy numery linii o 100, aby dać nam miejsce na dodanie kolejnych linii.
BASIC powstał później niż FORTRAN, w erze terminalu. Zawierało środowisko odczytu-exe-print-loop, które było bardziej interaktywne niż talia kart.
Nauczyłem się programować w języku BASIC na wyświetlaczu jednowierszowym , który zawiera 24 znaki. Numery linii były naturalnym sposobem na określenie, gdzie ma się znaleźć linia, niezależnie od tego, czy edytujesz jedną, czy wstawiasz między innymi.
Naprawdę nie wyobrażam sobie, jak inaczej byś to zrobił.
Nikt jeszcze nie wspomniał, że początkującym łatwiej jest zrozumieć przebieg programu, w którym cele rozgałęzienia są wyraźne. Zamiast więc dopasowywać (ewentualnie zagnieżdżone) instrukcje BEGIN / END (lub dowolne użyte ograniczniki bloków), było całkiem oczywiste, dokąd poszedł przepływ sterowania. Był to prawdopodobnie użyteczne podane grupy docelowej Zasadniczej (to jest dla początkujących All-purpose Symbolic Instruction Code, mimo wszystko).
Dartmouth Time Sharing System wykorzystał interfejs telegraficzny. Dlatego używał interfejsu opartego na poleceniach. Początkowo numery linii były po prostu używane do edycji programu. Możesz wstawiać, zamieniać lub usuwać za pomocą numeru linii. Nie wydaje się, aby wczesna wersja używała numerów wierszy dla instrukcji goto, ale było to późniejsze uzupełnienie języka.