Perché i vecchi BASIC (e forse altre lingue) utilizzavano i numeri di riga come parte del codice sorgente?
Voglio dire, quali problemi ha (tentato di) risolvere?
Perché i vecchi BASIC (e forse altre lingue) utilizzavano i numeri di riga come parte del codice sorgente?
Voglio dire, quali problemi ha (tentato di) risolvere?
Risposte:
BASIC deve essere inserito nel contesto dei suoi linguaggi contemporanei: fortran primitivo, cobol e assembly.
Quando stavo dilettando sull'assemblaggio 6502 senza etichette, ciò significava che quando hai scoperto che dovevi aggiungere un'istruzione da qualche parte nel mezzo di un codice compresso (in seguito ho aggiunto NOP ), dovevi passare e ripetere tutto il salto indirizzi. Ciò ha richiesto molto tempo.
Fortran era un sistema basato sul numero di riga che precedeva BASIC. In Fortran, le colonne 1-5 erano un numero di riga da utilizzare per gli obiettivi per la ramificazione. La cosa chiave con Fortran era che i compilatori tendevano a essere un po 'più intelligenti dell'interprete BASIC e aggiungere alcune istruzioni era solo una questione di prendere alcune carte e metterle nel mazzo nel posto giusto.
BASIC, d'altra parte, doveva mantenere tutte le sue istruzioni ordinate. Non c'era molto del concetto di "continuazione della linea precedente". Invece, in Applesoft BASIC (uno dei dialetti ampiamente usati con cui ho familiarità e su cui posso trovare informazioni) ogni riga in memoria era rappresentata come:
NN NN TT TT AA BB CC DD .. .. 00
Aveva due byte per l'indirizzo della riga successiva ( NN NN
). Due byte per il numero di riga di questa riga ( TT TT
), quindi un elenco di token ( AA BB CC DD .. ..
) seguito dall'indicatore di fine riga ( 00
). (Questo è da pagina 84-88 di Inside the Apple // e )
Un punto importante da capire quando si guarda quella rappresentazione di memoria è che le linee possono essere archiviate in memoria fuori servizio. La struttura della memoria era quella di un elenco collegato con un puntatore "linea successiva" nella struttura. Ciò ha reso semplice l'aggiunta di nuove righe tra due righe, ma è necessario numerare ciascuna riga affinché funzioni correttamente.
Molte volte quando lavoravi con BASIC, stavi effettivamente lavorando in BASIC stesso. In particolare, una determinata stringa era un numero di riga e istruzioni BASIC o un comando per l'interprete di base a RUN
o LIST
. Ciò ha reso facile distinguere il codice dai comandi: tutto il codice inizia con i numeri.
Queste due informazioni identificano il motivo per cui sono stati utilizzati i numeri: è possibile ottenere molte informazioni in 16 bit. Le etichette basate su stringhe occuperebbero molto più spazio e sono più difficili da ordinare. I numeri sono facili da lavorare, comprensibili e più facili da rappresentare.
Più tardi dialetti Basic in cui non erano a nel l'interprete per tutto il tempo sono stati in grado di farla finita con la linea di ogni numerato e invece solo bisogno di numerare le linee che erano gli obiettivi di filiale. In effetti, le etichette.
] PRINT "FOO"
stato gestito immediatamente dall'interprete BASIC. È una dichiarazione. Se volessi eseguirlo in un secondo momento, lo faresti ] 10 PRINT "FOO"
e poi ] RUN
. Nell'ambiente BASIC di AppleSoft, ogni istruzione BASIC poteva essere eseguita immediatamente o ritardata; c'erano solo pochissimi comandi forniti da DOS che non erano istruzioni BASIC valide. La differenziazione tra un'istruzione ora e un'istruzione successiva era il numero di riga. È inoltre possibile modificare un'istruzione ritardata inserendo nuovamente il numero di riga corrispondente. Puoi anche mettere più dichiarazioni su una riga::
Sui primi microcomputer il montaggio era basato su linee. Non puoi semplicemente muoverti liberamente nel codice sorgente e modificarlo. Avevi una sola riga nella parte inferiore dello schermo in cui puoi digitare i comandi e inserire il codice. Il resto dello schermo era costituito da elenchi di codice di sola lettura e output dei comandi. Se si desidera modificare, dire la riga 90 nel programma in cui è stato scritto " EDIT 90
" e il contenuto della riga è 90
entrato nel buffer di modifica a riga singola. Dopo aver modificato la riga che hai premuto invio, l'elenco del programma è stato aggiornato. Quindi avevi bisogno di numeri di riga per poter modificare il programma.
Quando gli editor di codice sono diventati più avanzati e ti hanno permesso di spostare il cursore nell'elenco dei codici non hai più bisogno dei numeri di riga.
Se stai pensando ai dialetti BASIC dei microcomputer domestici a 8 bit degli anni '80, quei computer non avevano editor di testo (a meno che tu non abbia acquistato un'applicazione per l'elaborazione di testi). Non c'era modo di avere l'intero codice sorgente del programma BASIC "aperto in un editor", come si farebbe oggi con la programmazione. Il programmatore non penserebbe nemmeno al programma come un file di codice sorgente o testo, davvero.
Quindi, supponiamo che tu abbia un semplice programma senza numeri di riga in testa:
FOR I=1 TO 42
PRINT I
NEXT I
Avvii il tuo computer. Hai un prompt "pronto" o qualcosa del genere e il cursore si trova nella riga successiva. Questo è molto simile agli ambienti REPL odierni con diversi linguaggi di scripting, anche se non proprio come strettamente basati su linee, più come su schermo. Quindi non abbastanza come i REPL di oggi, ma vicino.
Ora, se inizi a entrare nel programma, potresti ricevere un errore dopo la prima riga, perché l'interprete BASIC tenta di eseguirlo (e dimenticarlo) immediatamente, e non ha senso senza NEXT terminare il ciclo. Questo non è un editor di testo in cui si modifica il testo, è qui che si danno i comandi al computer!
Quindi hai bisogno di un modo per dire, questa è la linea di programma, salvala! Potresti avere un comando speciale o solo un simbolo che dice che ehi, questa è la riga di programma, salvalo. Immaginiamo questo:
#FOR I=1 TO 42
#PRINT I
#NEXT I
Ok, ora il nostro immaginario interprete BASIC ha memorizzato il programma e puoi eseguirlo. Ma ora vuoi modificare la riga STAMPA. Come si fa? Non sei in un editor di testo, non puoi semplicemente spostare il cursore sulla riga e modificarlo. Oppure vuoi aggiungere un'altra linea come LET COUNT=COUNT+1
nel ciclo. Come si indica dove inserire la nuova riga?
I numeri di riga lo risolvono in un modo molto semplice, anche se piuttosto volgare. Se si immette una riga di programma con un numero già esistente, la vecchia riga viene sostituita. Ora l'ambiente REPL telematico diventa utile, perché si può semplicemente spostare il cursore al programma di lista sullo schermo, modificare la riga sullo schermo e premere ENTER per memorizzarlo. Sembra che tu stia modificando la linea, mentre in realtà stai modificando il testo sullo schermo e quindi sostituendo l'intera linea con una nuova dallo schermo. Inoltre, l'inserimento di nuove righe diventa facile se si lasciano numeri inutilizzati in mezzo. Dimostrare:
10 FOR I=1 TO 42
20 PRINT I
30 NEXT I
Dopo aver reinserito la riga 20 con le modifiche e aver aggiunto nuove righe, potrebbe essere
5 LET COUNT=0
10 FOR I=1 TO 42
20 PRINT "Index", I
25 LET COUNT=COUNT+1
30 NEXT I
C'è il vantaggio (o la maledizione, in quanto consente il famoso codice spaghetti BASIC) di poter usare i numeri di linea come costrutto linguistico, almeno come bersaglio di comandi GOTO
AND GOSUB
. Questo potrebbe essere sostituito da etichette, ma l'uso dei numeri di riga è molto più semplice da implementare nell'interprete BASIC, che era ancora un vantaggio decisivo in un tipico computer a 8 bit degli anni '80.
Ancora più importante, dal punto di vista dell'esperienza dell'utente, i numeri di riga sono in realtà un'interfaccia sorprendentemente semplice ma completa per la modifica del codice. Basta digitare una riga che inizia con un numero per inserire un nuovo codice. Utilizzare LIST 100-200
per mostrare le linee 100-200. Per modificare una linea, elencala sullo schermo, modifica il testo sullo schermo e inserisci nuovamente la linea. Per rimuovere una riga, modificala in modo che sia vuota, ovvero fornisci semplicemente il numero di riga con nulla dopo. Un paragrafo per descriverlo. Confronta cercando di descrivere l'uso di vecchi editor di testo come edlin di DOS, o ed o ex di Unix: hai bisogno di un paragrafo (solo una leggera iperbole) solo per spiegare come l'utente può uscirne, se avviato accidentalmente!
Altre risposte spiegano come sono nati i numeri di riga. Sto cercando di spiegare qui, perché i numeri di riga sono sopravvissuti finché hanno continuato, come hanno continuato a risolvere un problema del mondo reale: hanno offerto un modo per eseguire la programmazione effettiva senza un vero editor, in un modo molto semplice. Una volta che gli editor di testo a schermo intero appropriati e facili da usare sono diventati il modo principale per modificare il codice, sia con la scomparsa delle limitazioni hardware sia quando si è superata l'inerzia delle persone che adattano cose nuove, i dialetti BASIC basati sul numero di riga sono scomparsi abbastanza rapidamente dall'uso, perché il principale problema di usabilità che hanno risolto non era più un problema.
Nel luogo e nell'era in cui fu sviluppato Basic, il miglior dispositivo I / O disponibile era un teletipo. La modifica di un programma è stata eseguita stampando (su carta) un elenco di tutto il programma, o la parte interessante di esso, e quindi digitando le righe di sostituzione con i numeri di riga.
Questo è anche il motivo per cui la numerazione delle linee predefinita era di 10, quindi tra le linee esistenti sarebbero presenti numeri inutilizzati.
ren
comando ' ', per rinumerare. Un'invocazione tipica era ren 10, 10
(rinumerare a partire da dieci, incrementando di dieci - il comportamento predefinito se uno appena digitato ren
. I comandi goto
e gosub
e then (linenumber)
sarebbero stati aggiornati automaticamente. Ma questo non era sicuramente disponibile nei primi BASIC. Ma IIRC, era disponibile in Apple Integer Basic, Applesoft FP basic, TI Basic / Extended Basic, MS Basic / GW Basic, ecc.
"Numeri di riga" significa alcune cose diverse.
Prima di tutto, tieni presente che il concetto di "linee" non esiste da sempre. Molti linguaggi di programmazione in questo periodo utilizzavano schede perforate e avere numeri di sequenza (di solito nelle ultime colonne della carta) ti ha aiutato a recuperare il tuo mazzo nell'ordine corretto se lo hai lasciato cadere o è successo qualcosa di terribile nel lettore di carte. C'erano macchine per farlo automaticamente.
I numeri di riga da utilizzare come target di GOTO
istruzioni sono un concetto completamente diverso. In FORTRAN IV, erano facoltativi e precedevano l'affermazione (nelle colonne 1-5). Oltre ad essere più facile da implementare rispetto alle etichette in formato libero, esisteva anche il concetto di GOTO calcolato e assegnato , che consentiva di passare a un numero di riga arbitrario. Questo era qualcosa che la maggior parte dei linguaggi di programmazione moderni non ha (sebbene le switch
istruzioni si avvicinino), ma era un trucco familiare per i programmatori di assemblatori.
BASIC è stato derivato da FORTRAN e intendeva essere più semplice da implementare e da comprendere, quindi forzare ogni "linea" ad avere un numero di linea (sia per il sequenziamento sia come obiettivo di GOTO
/ GOSUB
dichiarazioni) era probabilmente una decisione di progettazione presa per quel motivo.
goto array_of_labels[some_computation()];
GOTO
(o ASSIGN
) e l'aritmetica originale aka aka a tre vie IF
, e (usati raramente) rendimenti alternativi CALL
e tipi di obiettivi (probabilmente delimitatori) di DO
, e FORMAT
dichiarazioni. In altre affermazioni erano facoltative.
GOTO 1000+N*100
per emulare switch
un'istruzione.
Ho iniziato a programmare in COBOL che utilizzava i numeri di riga nelle colonne 1-6 di ogni riga. Poiché negli anni '70 non esistevano IDE, tutto veniva fatto tramite schede perforate e il numero di riga veniva utilizzato per identificare quali righe nella fonte originale dovevano essere sostituite e quali nuove linee aggiunte. Abbiamo usato per aumentare i numeri di riga di 100 per darci spazio per aggiungere più righe.
BASIC è nato più tardi di FORTRAN, nell'era dei terminali di linea. Presenta un ambiente read-exe-print-loop che era più interattivo di un mazzo di carte.
Ho imparato a programmare, in BASIC, su un display a una riga che conteneva 24 caratteri. I numeri di riga erano un modo naturale per specificare dove si voleva andare una linea, modificandola o inserendola tra le altre.
Non riesco davvero a immaginare come lo faresti altrimenti.
Un punto che nessuno ha ancora menzionato è che è più facile per i principianti ragionare sul flusso del programma in cui gli obiettivi del ramo sono espliciti. Quindi, piuttosto che dover abbinare le istruzioni (possibilmente annidate) BEGIN / END (o qualunque delimitatore di blocco usato), era abbastanza ovvio dove andasse il flusso di controllo. Ciò è stato probabilmente utile dato il pubblico di destinazione di BASIC (dopo tutto è il Codice di istruzioni simbolico per tutti gli usi del Principiante ).
Il sistema di condivisione del tempo di Dartmouth utilizzava un'interfaccia di teletipo. Quindi ha usato un'interfaccia basata su comandi. Inizialmente, i numeri di riga venivano usati solo come mezzo per modificare il programma. È possibile inserire, sostituire o eliminare utilizzando un numero di riga. Non sembra che la versione precedente usasse i numeri di riga per le dichiarazioni goto, ma questa è stata un'aggiunta successiva alla lingua.