Perché le librerie standard non programmano le primitive del linguaggio? [chiuso]


30

Stavo pensando perché ci sono (in tutti i linguaggi di programmazione che ho imparato, come C ++, Java, Python) librerie standard come stdlib, invece di avere "funzioni" simili essendo una primitiva del linguaggio stesso.


4
Cosa intendi con "perché il compilatore non potrebbe semplicemente tradurre una chiamata di funzione in un set di istruzioni"? Questo è più o meno quello che fa il compilatore, libreria standard o meno (Ok, Python solo parzialmente e codice byte da Java a JVM; concetto simile). Le librerie standard non hanno nulla a che fare con la compilazione del codice -> istruzioni.
Delioth,

25
@Delioth Penso che Simone stia chiedendo perché non ci sia tutto nella libreria standard del linguaggio $ LANG un costrutto / funzione primitiva di quel linguaggio. Direi che è una domanda ragionevole per chiunque sia molto nuovo nei linguaggi di programmazione :)
Andres F.

33
La biblioteca standard in genere colma il divario tra un linguaggio di programmazione funzionante e uno utile che le persone useranno.
Telastyn,

6
Una parte significativa della libreria standard di Python è in realtà scritta in C e già compilata.
ElmoVanKielmo

1
Come mezzo di contrasto, nella maggior parte delle implementazioni di BASIC tutto fa parte del linguaggio e non ci sono affatto librerie né supporto per esse (salvo, in diverse implementazioni, la possibilità di chiamare in routine di linguaggio macchina).
Euro Micelli,

Risposte:


32

Mi permetta di espandere un po ' la buona risposta di @ Vincent (+1) :

Perché il compilatore non può semplicemente tradurre una chiamata di funzione in una serie di istruzioni?

Può e lo fa tramite almeno due meccanismi:

  • incorporare una chiamata di funzione : durante la traduzione, il compilatore può sostituire una chiamata di codice sorgente con la sua implementazione direttamente in linea invece di effettuare una chiamata effettiva alla funzione. Tuttavia la funzione deve avere un'implementazione definita da qualche parte e che può trovarsi nella libreria standard.

  • funzione intrinseca : le intrinseche sono funzioni di cui il compilatore è stato informato senza necessariamente trovare la funzione in una libreria. Di solito sono riservati a funzionalità hardware che non sono praticamente accessibili in nessun altro modo, essendo così semplice che anche il sovraccarico di una chiamata alla funzione di libreria della lingua dell'assembly è considerato elevato. (Il compilatore in genere può incorporare automaticamente solo il codice sorgente nella sua lingua, ma non le funzioni di assemblaggio, che è qui che entra in gioco il meccanismo intrinseco.)

Detto questo, a volte l'opzione migliore è che il compilatore traduca una chiamata di funzione nella lingua di origine in una chiamata di funzione nel codice macchina. Ricorsione, metodi virtuali e dimensioni pure sono alcuni dei motivi per cui non è sempre possibile / pratico integrare. (Un altro motivo è l'intento della build, come compilazione separata (moduli oggetto), unità di carico separate (ad esempio DLL)).

Non c'è alcun vantaggio reale nel rendere intrisiche anche la maggior parte delle funzioni di libreria standard (ciò renderebbe molto più complessa la conoscenza del compilatore senza alcun vantaggio reale), quindi una chiamata di codice macchina spesso è più appropriata.

C è un linguaggio notevole che ha probabilmente omesso altre dichiarazioni esplicite del linguaggio a favore delle funzioni di libreria standard. Sebbene le biblioteche preesistessero, questo linguaggio ha fatto il passaggio a fare più lavoro dalle funzioni di libreria standard e meno come dichiarazioni esplicite nella grammatica del linguaggio. L'IO in altre lingue, ad esempio, è stata spesso data la propria sintassi sotto forma di varie istruzioni, mentre la grammatica C non definisce alcuna istruzione IO, semplicemente rinviando alla sua libreria standard per fornire che, tutte accessibili tramite chiamate di funzione, che il compilatore sa già come fare.


3
Bella risposta. Bisognerebbe aggiungere alcune parole per cui è stata presa questa decisione in C.
Doc Brown,

10
@DocBrown Nel 1975, c'erano abbastanza esempi nell'area dello sviluppo del linguaggio di programmazione (ALGOL-68, chiunque?) Che mostravano che i tentativi di inserire tutto nel linguaggio portavano direttamente a notevoli rallentamenti sia nel definire le specifiche del linguaggio sia nel produrre implementazioni linguistiche.
Joker_vD

5
Un esempio simile è quello che ha fatto Python print: in 2.x, era un'istruzione , con la sua grammatica speciale, ma in 3.x è diventata solo un'altra chiamata di funzione. Vedi PEP 3105 per la spiegazione ufficiale.
dan04

1
@DocBrown, la portabilità non era quasi certamente una ragione. Quando Unix e C furono creati, furono progettati e costruiti esattamente per una macchina, un PDP-7 di riserva, mentre Ken Thompson si chiedeva quali concetti potessero essere recuperati dal fallito progetto Multics. C è stato anche creato per un motivo: avere un linguaggio di alto livello in cui (re) implementare Unix. Fondamentalmente siamo un esperimento di progettazione software, non un serio tentativo di un sistema operativo e linguaggio multipiattaforma commerciale. Vedi bell-labs.com/usr/dmr/www/chist.html per esempio.
Euro Micelli,

@EuroMicelli: non vedo una contraddizione. E il tuo riferimento contiene molti dettagli su quando la portabilità è diventata importante, in realtà era nei primi anni dello sviluppo di C e Unix. Posso solo indovinare qui, ma se gli inventori C non avessero mantenuto il linguaggio intenzionalmente piccolo, penso che sarebbe stato abbastanza improbabile che avrebbero potuto portarlo così rapidamente e con successo su molte architetture diverse.
Doc Brown,

70

Questo è semplicemente per mantenere la lingua stessa il più semplice possibile. È necessario distinguere tra una funzionalità del linguaggio, ad esempio un tipo di loop o modi per passare i parametri alle funzioni e così via, e le funzionalità comuni necessarie alla maggior parte delle applicazioni.

Le librerie sono funzioni che possono essere utili a molti programmatori, quindi vengono create come codice riutilizzabile che può essere condiviso. Le librerie standard sono progettate per essere funzioni molto comuni di cui i programmatori hanno generalmente bisogno. In questo modo il linguaggio di programmazione è immediatamente utile per una più ampia gamma di programmatori. Le librerie possono essere aggiornate ed estese senza modificare le funzionalità di base della lingua stessa.


3
Non sempre. PHPad esempio difficilmente fa alcuna differenza tra le sue vaste funzioni linguistiche e la lingua stessa.
Vahid Amiri

15
Non prenderei PHP come esempio di un linguaggio semplice
DrBreakalot il

3
@DrBreakalot PHP è un linguaggio estremamente semplice. Questo non vuol dire che ha un design coerente, ma questo è un altro problema.
Lightness Races con Monica

19
@LightnessRacesinOrbit Non definirei PHP "semplice": ha un sistema a oggetti di classe, un insieme separato di "valori primitivi", funzioni autonome, chiusure di prima classe costruite sul sistema a oggetti, un meccanismo dello spazio dei nomi, vari nozioni cosiddetti "statica", istruzioni nonché espressioni include, requiree require_once, se / per / while (programmazione strutturata), eccezioni, un sistema separato di 'valori di errore' complicato regole battitura deboli, complicate regole operatore precedenza, e così via . Confronta questo con la semplicità di, diciamo, Smalltalk, Scheme, Prolog, Forth, ecc .;)
Warbo

3
Il motivo principale, che è accennato ma non esplicitamente indicato in questa risposta, è che mantenendo il linguaggio il più semplice possibile, è molto più facile implementarlo su altre piattaforme. Poiché le librerie standard sono generalmente scritte nella lingua stessa , possono essere banalmente portate.
BlueRaja - Danny Pflughoeft il

34

Oltre a ciò che hanno già detto le altre risposte, inserire le funzioni standard in una libreria è la separazione delle preoccupazioni :

  • È compito del compilatore analizzare la lingua e generare il codice per essa. Non è compito del compilatore contenere tutto ciò che può già essere scritto in quella lingua e fornito come libreria.

  • È il lavoro della libreria standard (quello che è sempre implicitamente disponibile) per fornire le funzionalità di base necessarie praticamente per tutti i programmi. Non è compito della libreria standard contenere tutte le funzioni che potrebbero essere utili.

  • È compito delle librerie standard opzionali fornire funzionalità ausiliarie di cui molti programmi possono fare a meno, ma che sono ancora abbastanza basilari e anche essenziali per molte applicazioni per garantire la spedizione con ambienti standard. Non è compito di quelle librerie opzionali contenere tutto il codice riutilizzabile che sia mai stato scritto.

  • È compito delle librerie utente fornire raccolte di utili funzioni riutilizzabili. Non è compito delle librerie utente contenere tutto il codice che sia mai stato scritto.

  • È compito del codice sorgente di un'applicazione fornire i rimanenti bit di codice che sono realmente rilevanti solo per quella applicazione.

Se vuoi un software adatto a tutti, ottieni qualcosa di follemente complesso. È necessario modularizzare per portare la complessità a livelli gestibili. Ed è necessario modularizzare per consentire implementazioni parziali :

  • La libreria di threading è inutile sul controller incorporato single-core. Consentire all'implementazione della lingua per questo controller incorporato di non includere la pthreadlibreria è la cosa giusta da fare.

  • La libreria matematica non ha valore sul microcontrollore che non ha nemmeno una FPU. Ancora una volta, non essere costretti a fornire funzioni come quelle sin()rende la vita molto più semplice per gli implementatori della tua lingua per quel microcontrollore.

  • Anche la libreria standard di base è inutile quando si sta programmando un kernel. Non è possibile implementare write()senza un syscall nel kernel e non è possibile implementare printf()senza write(). Come programmatore del kernel, è tuo compito fornire il write()syscall, non puoi aspettarti che sia lì.

Un linguaggio che non consente tali omissioni dalle librerie standard non è semplicemente adatto a molte attività . Se vuoi che la tua lingua sia utilizzabile in modo flessibile in ambienti non comuni, deve essere flessibile in quali librerie standard sono incluse. Più il tuo linguaggio si basa su librerie standard, più ipotesi fa sul suo ambiente di esecuzione, e quindi limita il suo uso agli ambienti che forniscono questi prerequisiti.

Naturalmente, linguaggi di alto livello come Python e Java possono fare molte ipotesi sul loro ambiente. E tendono ad includere molte, molte cose nelle loro librerie standard. Linguaggi di livello inferiore come C forniscono molto meno nelle loro librerie standard e mantengono la libreria standard di base molto più piccola. Ecco perché trovi un compilatore C funzionante praticamente per qualsiasi architettura, ma potresti non essere in grado di eseguire alcun script Python su di esso.


16

Un grande motivo per cui i compilatori e le librerie standard sono separati è perché servono a due scopi diversi (anche se entrambi sono definiti dalla stessa lingua specifica): il compilatore traduce il codice di livello superiore in istruzioni macchina e la libreria standard fornisce pre-test implementazioni di funzionalità comunemente necessarie. Gli autori di compilatori apprezzano la modularità proprio come fanno gli altri sviluppatori di software. In effetti, alcuni dei primi compilatori C suddividono ulteriormente il compilatore in programmi separati per la pre-elaborazione, la compilazione e il collegamento.

Questa modularità offre numerosi vantaggi:

  • Riduce al minimo la quantità di lavoro necessario quando si supporta una nuova piattaforma hardware, poiché la maggior parte del codice libreria standard è indipendente dall'hardware può essere riutilizzato.
  • Un'implementazione della libreria standard può essere ottimizzata in diversi modi (per velocità, spazio, utilizzo delle risorse, ecc.). Molti dei primi sistemi di elaborazione disponevano di un solo compilatore e la presenza di una libreria standard separata consentiva agli sviluppatori di scambiare le implementazioni in base alle proprie esigenze.
  • La funzionalità di libreria standard non deve nemmeno esistere. Quando si scrive codice C bare-metal, ad esempio, si dispone di un compilatore completo, ma la maggior parte delle funzionalità di libreria standard non è presente e alcune cose come l'I / O dei file non sono nemmeno possibili. Se il compilatore fosse necessario per implementare questa funzionalità, allora non potresti avere un compilatore C conforme agli standard su alcune delle piattaforme in cui ne hai maggiormente bisogno.
  • Sui primi sistemi, i compilatori venivano spesso sviluppati dall'azienda che progettava l'hardware. Le librerie standard erano spesso fornite dal fornitore del sistema operativo, poiché spesso richiedevano l'accesso a funzionalità (come le chiamate di sistema) specifiche per quella piattaforma software. Era poco pratico per uno scrittore di compilatori dover supportare tutte le diverse combinazioni di hardware e software (c'era una varietà molto più ampia sia nell'architettura hardware che nella piattaforma software).
  • In linguaggi di alto livello, una libreria standard può essere implementata come libreria caricata dinamicamente. Un'implementazione di libreria standard può quindi essere utilizzata da più compilatori e / o linguaggi di programmazione.

Storicamente parlando (almeno dal punto di vista di C), le versioni originali e pre-standardizzate del linguaggio non avevano affatto una libreria standard. I fornitori di sistemi operativi e le terze parti fornivano spesso librerie piene di funzionalità di uso comune, ma implementazioni diverse includevano elementi diversi ed erano in gran parte incompatibili tra loro. Quando C è stato standardizzato, hanno definito una "libreria standard" nel tentativo di armonizzare queste diverse implementazioni e migliorare la portabilità. La libreria standard C si è sviluppata separatamente dal linguaggio, come le librerie Boost hanno per C ++, ma sono state successivamente integrate nelle specifiche del linguaggio.


6

Risposta complementare: gestione della proprietà intellettuale

Un esempio notevole è l' implementazione di Math.Pow (doppio, doppio) in .NET Framework che è stato acquistato da Microsoft da Intel e non viene divulgato anche se il framework è diventato open-source. (Per essere precisi, nel caso precedente si tratta di una chiamata interna anziché di una libreria ma l'idea è valida.) Una libreria separata dalla lingua stessa (teoricamente anche un sottoinsieme di librerie standard) può offrire ai sostenitori della lingua una maggiore flessibilità nel disegnare il linea tra cosa mantenere trasparente e ciò che deve rimanere nascosto (a causa dei loro contratti con terze parti o altri motivi relativi alla proprietà intellettuale).


Questo è confusionario. La pagina a cui ti colleghi Math.Pownon menziona alcun acquisto o qualcosa su Intel e parla di persone che leggono il codice sorgente dell'implementazione della funzione.
Lightness Races con Monica

@LightnessRacesinOrbit - hm, posso ancora vederlo lì (quando cerco "intel"). Puoi anche trovare il riferimento al recente codice sorgente (nei commenti più recenti) e anche un'implementazione alternativa (nella seconda risposta) che è disponibile pubblicamente ma la complessità e l'inefficacia commentata danno un suggerimento sul perché l'implementazione originale non è ancora divulgata. Un'attuazione veramente efficiente potrebbe richiedere una conoscenza approfondita di molti dettagli a livello di CPU che non sono necessariamente disponibili nel pubblico dominio.
miroxlav,

5

Bug e debug.

Bug: tutto il software ha dei bug, la tua libreria standard ha dei bug e il tuo compilatore ha dei bug. Come utente della lingua è molto più facile trovare e aggirare tali bug quando si trovano nella libreria standard anziché nel compilatore.

Debug: è molto più facile per me vedere una traccia dello stack di una libreria standard e darmi un'idea di cosa potrebbe andare storto. Perché quella traccia dello stack ha un codice che capisco. Naturalmente puoi scavare più a fondo e puoi anche rintracciare le tue funzioni intrinseche, ma è molto più facile se è in una lingua che usi tutto il giorno di giorno in giorno.


5

Questa è un'ottima domanda!

All'avanguardia

Lo standard C ++, ad esempio, non specifica mai cosa dovrebbe essere implementato nel compilatore o nella libreria standard: si riferisce solo all'implementazione . Ad esempio, i simboli riservati sono definiti sia dal compilatore (come intrinseci) che dalla libreria standard, in modo intercambiabile.

Tuttavia, tutte le implementazioni di C ++ che conosco avranno il numero minimo possibile di elementi intrinseci forniti dal compilatore e il più possibile forniti dalla libreria standard.

Pertanto, mentre è tecnicamente possibile definire la libreria standard come funzionalità intrinseca nel compilatore, sembra raramente utilizzata nella pratica.

Perché?

Consideriamo l'idea di spostare alcune funzionalità dalla libreria standard al compilatore.

vantaggi:

  • Migliore diagnostica: i valori intrinseci possono essere sottoposti a casi speciali.
  • Migliori prestazioni: i valori intrinseci possono essere di tipo speciale.

svantaggi:

  • Aumento della massa del compilatore: ogni caso speciale aggiunge complessità al compilatore; la complessità aumenta i costi di manutenzione e la probabilità di bug.
  • Iterazione più lenta: modificare l'implementazione della funzionalità richiede la modifica del compilatore stesso, rendendo più difficile la creazione di una piccola libreria (al di fuori di std) per sperimentare.
  • Barra più alta all'ingresso: più è costoso / più difficile cambiare qualcosa, meno è probabile che le persone saltino dentro.

Ciò significa che spostare qualcosa nel compilatore è costoso , ora e in futuro, e quindi richiede un caso solido. Per alcune funzionalità, è necessario (non possono essere scritte come codice normale), ma anche allora paga estrarre parti minime e generiche per passare al compilatore e costruirle sopra nella libreria standard.


5

Come progettista della lingua, vorrei echeggiare alcune delle altre risposte qui, ma fornirle attraverso gli occhi di qualcuno che sta costruendo una lingua.

Un'API non è terminata quando hai finito di aggiungere tutto ciò che puoi. Un'API è terminata quando hai finito di estrarre tutto ciò che puoi.

È necessario specificare un linguaggio di programmazione usando un linguaggio. Devi essere in grado di trasmettere il significato dietro qualsiasi programma scritto nella tua lingua. Questa lingua è molto difficile da scrivere, e ancora più difficile da scrivere bene. In generale, tende ad essere una forma inglese molto precisa e ben strutturata utilizzata per trasmettere significato non al computer, ma ad altri sviluppatori, in particolare quegli sviluppatori che scrivono compilatori o interpreti per la tua lingua. Ecco un esempio dalla specifica C ++ 11, [intro.multithread / 14]:

La sequenza visibile di effetti collaterali su un oggetto atomico M, rispetto ad un calcolo del valore B di M, è una sub-sequenza contigua massima di effetti collaterali nell'ordine di modifica di M, in cui il primo effetto collaterale è visibile rispetto a B e per ogni effetto collaterale, non è il caso che B accada prima di esso. Il valore di un oggetto atomico M, determinato dalla valutazione B, deve essere il valore memorizzato da qualche operazione nella sequenza visibile di M rispetto a B. [Nota: si può dimostrare che la sequenza visibile di effetti collaterali di un valore il calcolo è unico dati i requisiti di coerenza indicati di seguito. —Endola nota]

Blek! Chiunque si sia immerso nella comprensione di come C ++ 11 gestisce il multithreading può capire perché la formulazione deve essere così pericolosa opaca, ma ciò non perdona il fatto che sia ... beh ... così opaca!

In contrasto con la definizione di std::shared_ptr<T>::reset, nella sezione libreria dello standard:

template <class Y> void reset(Y* p);

Effetti: equivalente ashared_ptr(p).swap(*this)

Quindi qual è la differenza? Nella parte della definizione della lingua, gli scrittori non possono presumere che il lettore capisca le primitive della lingua. Tutto deve essere specificato con cura in prosa inglese. Una volta arrivati ​​alla parte della definizione della libreria, possiamo usare la lingua per specificare il comportamento. Questo è spesso molto più semplice!

In linea di principio, si potrebbe avere un buon andamento dai primitivi all'inizio del documento sulle specifiche, fino alla definizione di ciò che potremmo pensare come "caratteristiche standard della libreria", senza dover tracciare una linea tra "primitivi linguistici" e funzionalità "libreria standard". In pratica, quella linea si rivela estremamente preziosa da disegnare perché ti permette di scrivere alcune delle parti più complesse del linguaggio (come quelle che devono implementare algoritmi) usando un linguaggio progettato per esprimerle.

E vediamo davvero alcune linee sfocate:

  • In Java, java.lang.ref.Reference<T>possono essere suddivisi in sottoclassi solo dalle classi di libreria standard java.lang.ref.WeakReference<T> java.lang.ref.SoftReference<T>e java.lang.ref.PhantomReference<T>poiché i comportamenti di Referencesono così profondamente intrecciati con le specifiche del linguaggio Java che avevano bisogno di mettere alcune restrizioni nella parte di quel processo implementato come classi di "libreria standard".
  • In C # esiste una classe System.Delegate che incapsula il concetto di delegati. Nonostante il suo nome, non è un delegato. È anche una classe astratta (non può essere istanziata) da cui non è possibile creare classi derivate. Solo il sistema può farlo attraverso le funzionalità scritte nelle specifiche del linguaggio.

2

Questo si intende come aggiunta alle risposte esistenti (ed è troppo lungo per un commento).

Esistono almeno altri due motivi per una libreria standard:

Barriera all'ingresso

Se una funzione linguistica particolare si trova in una funzione di libreria e voglio sapere come funziona, posso semplicemente leggere la fonte per quella funzione. Se desidero inviare una segnalazione bug / richiesta patch / pull, non è generalmente troppo difficile codificare una correzione e testare i casi. Se è nel compilatore, devo essere in grado di scavare negli interni. Anche se è nella stessa lingua (e dovrebbe essere, qualsiasi compilatore che si rispetti dovrebbe essere ospitato da solo) il codice del compilatore non assomiglia al codice dell'applicazione. Potrebbe essere necessaria un'eternità anche per trovare i file corretti.

Ti stai escludendo da molti potenziali collaboratori se segui questa strada.

Caricamento codice caldo

Molte lingue offrono questa funzionalità in un modo o nell'altro, ma sarebbe enormemente complicato ricaricare a caldo il codice che sta eseguendo la ricarica a caldo. Se la SL è separata dal runtime, può essere ricaricata.


3
"qualsiasi compilatore che si rispetti dovrebbe essere ospitato da solo" - per niente. Sarebbe inutile avere versioni di dire LLVM scritte in C, C ++, Objective-C, Swift, Fortran e così via per compilare tutti questi linguaggi.
gnasher729,

@ gnasher729 non è un po 'un caso speciale (insieme ad altri target multilingua come il CLR)?
Jared Smith il

@JaredSmith Direi che ora è il caso generale, per niente speciale. Nessuno scrive più "un compilatore" come un'applicazione monolitica. Producono invece sistemi di compilazione . La maggior parte delle funzionalità del compilatore completo è completamente indipendente dalla particolare lingua che viene compilata, e gran parte della parte dipendente dalla lingua può essere eseguita fornendo dati diversi che definiscono la grammatica della lingua, non scrivendo codice diverso per ogni lingua vuoi compilare.
alephzero,

2

Questa è una domanda interessante ma ci sono già molte buone risposte, quindi non tenterò una risposta completa.

Tuttavia, due cose che non credo abbiano ottenuto abbastanza attenzione:

Il primo è che il tutto non è molto chiaro. È un po 'uno spettro esattamente perché ci sono ragioni per fare le cose in modo diverso. Ad esempio, i compilatori spesso conoscono le librerie standard e le loro funzioni. Esempio dell'esempio: la funzione "Hello World" di C - printf - è la migliore a cui riesco a pensare. È una funzione di libreria, in un certo senso deve essere, poiché dipende molto dalla piattaforma. Ma il comportamento (definito dall'implementazione) deve essere conosciuto dal compilatore per avvertire il programmatore di invocazioni errate. Questo non è particolarmente pulito, ma è stato visto come un buon compromesso. Per inciso, questa è la vera risposta alla maggior parte delle domande sul "perché questo design": un sacco di compromessi e "sembrava una buona idea al momento". Non sempre il "questo era il modo chiaro per farlo" o "

Il secondo è che consente alla libreria standard di non essere quella standard. Ci sono molte situazioni in cui una lingua è desiderabile, ma le librerie standard che di solito le accompagnano non sono sia pratiche che desiderabili. Questo è più comunemente il caso di sistemi che programmano linguaggi come C, su piattaforme non standard. Ad esempio, se si dispone di un sistema senza un sistema operativo o uno scheduler: non si avrà il threading.

Con un modello di libreria standard (e il threading in esso supportato), questo può essere gestito in modo pulito: il compilatore è praticamente lo stesso, puoi riutilizzare i bit delle librerie applicabili e tutto ciò che non puoi rimuovere. Se questo viene inserito nel compilatore, le cose iniziano a diventare confuse.

Per esempio:

  • Non puoi essere un compilatore conforme.

  • Come indicheresti la tua deviazione dallo standard. Nota che di solito esiste una qualche forma di sintassi import / include che potresti avere esito negativo, ad esempio l'importazione di Pythons o l'inclusione di C che indica facilmente il problema se manca qualcosa nel modello di libreria standard.

Anche problemi simili si applicano se si desidera modificare o estendere la funzionalità 'libreria'. Questo è molto più comune di quanto si possa pensare. Solo per restare fedeli al threading: windows, linux e alcune unità di elaborazione di rete esotiche eseguono il threading in modo diverso. Mentre i bit linux / windows potrebbero essere abbastanza statici ed essere in grado di usare un'API identica, le cose NPU cambieranno con il giorno della settimana e l'API con esso. I compilatori si discosterebbero rapidamente man mano che le persone decidessero quali parti devono supportare / che potrebbero fare abbastanza rapidamente se non ci fosse modo di dividere questo genere di cose.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.