Come progetteresti un linguaggio di programmazione? [chiuso]


41

Se dovessi progettare un linguaggio di programmazione, come lo faresti? Quali funzionalità vorresti inserire? Cosa vorresti lasciare fuori? Digitato staticamente o dinamicamente? Scritto fortemente o debolmente? Compilato o interpretato? Giustifica le tue risposte.


12
Questa domanda è troppo vaga. Le caratteristiche della lingua non possono essere realmente discusse fino a quando non viene determinato lo scopo della lingua.
Blucz,

1
Se puoi votare e pensare che questa sia una domanda utile o abbia delle risposte utili di seguito, vota per favore. I siti StackExchange hanno bisogno di voti per costruire una buona comunità. Puoi dare 30 voti al giorno, non sprecarli. Specialmente gli utenti con alta reputazione e basso numero di voti assegnati, per favore leggi questo: meta.programmers.stackexchange.com/questions/393/…
Maniero

3
Vorrei creare un linguaggio di altissimo livello con un metodo: public void DoWhatIMeant ();
Dave,

6
il linguaggio di programmazione ideale? ... Vorrei che il compilatore leggesse la mia mente e generasse un programma esattamente come lo voglio .. :) potrebbe volerci un po ', ma ne varrebbe la pena.
WalterJ89,

2
Compilazione e interpretazione sono tratti di ... beh, il compilatore o l'interprete (duh), non la lingua. Tutte le lingue possono essere implementate da un compilatore o un interprete. E in effetti, praticamente tutti lo sono. Ci sono compilatori per Ruby, Python, ECMAScript, PHP, ci sono interpreti per C, C ++, Java, Haskell, ...
Jörg W Mittag

Risposte:


55
  • Penso sicuramente che i linguaggi di programmazione funzionale prenderanno piede, quindi il mio linguaggio sarà funzionale. Vedi Effetti domare con la programmazione funzionale

  • Penso che presto le CPU avranno centinaia di core, e i thread sarà un inferno da gestire. Quindi il modello di attore è un must invece dei thread. Vedi Erlang - software per un mondo concorrente

  • Penso anche che OOP sia fallito, la comunicazione tra oggetti è stata considerata asincrona . Quindi penso che abbiamo bisogno del passaggio di messaggi , con messaggi immutabili. Invia e dimentica. Come nel modello Actor. Vedi programmazione orientata agli oggetti: il percorso sbagliato?

  • Penso che sarebbe bene avere la tipizzazione statica , quindi gli errori vengono colti all'inizio del ciclo di sviluppo. Ma userei l' inferenza del tipo come in Haskell, in modo che lo sviluppatore non abbia bisogno di scrivere il tipo ovunque nel codice come in C, C # e Java. Vedi Learn You A Haskell for Great Good

  • Progetterei anche una grande libreria UI , con layout dichiarativo , come in WPF e Android. Ma vorrei averlo come nella Programmazione reattiva funzionale .

Quindi il mio linguaggio sarebbe come la concorrenza in Erlang ma con la digitazione come in Haskell e un framework GUI come in WPF.NET.


4
suona come Scala, in realtà, tranne forse per la grande libreria dell'interfaccia utente.
Ape-inago,

Pensavo che Scala avesse avuto messaggi e attori. Immagino di non sapere come si rapporta a OOP.
Ape-inago,

@Jonas: sembra fantastico :) Non so molto sul modello di attore, è simile a quello che Go ha fatto con le goroutine?
Matthieu M.

1
L'unica cosa di cui sono scettico è la tipizzazione statica. Preferirei decisamente la digitazione forte anziché quella debole, ma a volte la digitazione statica è troppo restrittiva. Ma non conosco Haskell e ho sentito solo cose positive sul suo sistema di battitura :)
sakisk,

1
Il fallimento di OOP, francamente, è che quasi nessun linguaggio "orientato agli oggetti" lo implementa realmente . Molto semplicemente calzascarpe un modello a oggetti in un linguaggio procedurale e chiamarlo un giorno. Vorrei che Smalltalk avesse preso più su se stesso, piuttosto che spingere ogni weenie del linguaggio procedurale a dire "Eh, possiamo fare qualcosa di simile-forse-simile" e riuscire a perdere completamente il punto di OOP.
cHao,

22

Nota: ho usato la sintassi di tipo C per descrivere le funzionalità di questo post, ma non sono schizzinoso riguardo alla sintassi stessa, purché non sia qualcosa di ridicolo come tutte le parole chiave in maiuscolo.

1. Sistema di battitura

La caratteristica numero uno che vorrei in una lingua è la digitazione statica con la digitazione dinamica opzionale . Il motivo è che la tipizzazione statica consente di a) rilevare gli errori in anticipo piuttosto che in ritardo eb) la maggior parte del codice è implicitamente digitata staticamente, indipendentemente dal fatto che la lingua faccia la distinzione. Tuttavia, ci sono diversi casi d'uso in cui la digitazione dinamica è estremamente utile. Ad esempio, quando si leggono dati da un file, spesso si hanno campi di vari tipi e la digitazione dinamica rende facili i contenitori eterogenei. Quindi, il mio linguaggio ideale avrebbe qualcosa del genere:

//variable declarations
int anInt = 42 //anInt is now irrevocably an integer and assigning another type to it is an error
vartype aVariable = 42 //aVariable is currently an integer, but any type can be assigned to it in the future

//function definitions
int countElements(Collection c)
{
  return c.count();
} 

//c HAS to be a collection, since countElements doesn't make sense otherwise

void addToCollection(Collection& c, vartype v) 
{
  c.append(v)
}

//c is passed by reference here

2. Compilato vs. interpretato

Vorrei che il linguaggio venisse compilato in anticipo, o compilato da JIT, ma non puramente interpretato, essendo la velocità la ragione. Ciò si lega al punto 1 , poiché un compilatore / jitter ottimizzato avrà un tempo molto più semplice nell'ottimizzazione del codice tipizzato staticamente e il codice tipizzato dinamicamente potrebbe semplicemente essere lasciato così com'è.

3. Chiusure

Il linguaggio deve supportare costrutti di programmazione funzionale e le funzioni dovrebbero essere oggetti di prima classe.

4. Orientato agli oggetti

Il linguaggio dovrebbe consentire di scrivere codice orientato agli oggetti, ma dovrebbe essere consentito anche un semplice codice imperativo. cioè, dovrebbe essere possibile scrivere un programma ciao mondo in questo modo:

int main(string<> args=null)
{
  printf("hello, world"); 
  return 0;
}

// this code also demonstrates two other features,
// default arguments for functions (not explained further)
// and immutable lists like string<> (see 6. Built-in datatypes)

5. Spazi dei nomi

Gli spazi dei nomi sono una buona cosa. Roba molto piccola dovrebbe andare nello spazio dei nomi globale. Ma se devi mettere cose nello spazio dei nomi globale, puoi (ala C ++).

6. Tipi di dati integrati

Il linguaggio deve avere, come tipi di dati integrati, i seguenti costrutti:

  • Un inttipo di dati o tipi. Se esiste un solo inttipo, dovrebbe avere un intervallo illimitato. Se ce ne sono altri, dovrebbe esserci un upcast implicito nel tipo più piccolo in grado di contenere il risultato di un calcolo, con il tipo di intervallo illimitato che è il più grande.
  • Un singolo floattipo binario incorporato , equivalente a un IEEE 754double
  • Un listtipo mutabile che viene implementato come un elenco doppiamente collegato o un blocco di memoria contigua che contiene puntatori a ciascun elemento
  • Un listtipo immutabile che si comporta come un array ma le cui dimensioni non possono essere modificate dopo la creazione
  • stringTipi mutabili e immutabili , con l'impostazione predefinita immutabile.
  • Un tipo mapo dictche è mutabile e contiene chiavi immutabili e valori mutabili e / o immutabili.
  • I tipi di raccolta incorporati devono essere tipizzati in modo omogeneo per impostazione predefinita, ma possono essere vartyped se necessario
  • Un booleantipo
  • A nullo nonetipo che può essere assegnato a una variabile di qualsiasi tipo.
  • setTipi mutabili e immutabili
  • Un decimaltipo che implementa variabili decimali in virgola mobile
  • Un fixedtipo, che implementa un numero a virgola fissa

I decimal, floate le fixedtipologie dovrebbero condividere l' esatto stessa interfaccia pubblica (tramite eredità o digitando anatra), consentendo loro di essere trasparente passati a e restituiti dalle funzioni. È possibile chiamare il tipo parent real.

7. Chiamata per valore e per riferimento

Dovresti essere in grado di chiamare le funzioni sia per valore che per riferimento, con il valore predefinito come valore (cioè, una copia dell'argomento viene creata e gestita nella funzione).

8. Puntatori

La lingua dovrebbe avere puntatori e consentire l'aritmetica dei puntatori. I puntatori possono essere digitati staticamente (per evitare l'incubo che è a void*). vartypei puntatori sono esplicitamente vietati. Avere puntatori e aritmetica dei puntatori consente al linguaggio di essere seriamente utilizzato come linguaggio di programmazione dei sistemi.

9. Assemblaggio in linea

In connessione con 8. , La lingua dovrebbe consentire il codice della lingua di assembly inline per quelle situazioni in cui è necessario.

10. Sicurezza

Il linguaggio dovrebbe essere per lo più sicuro da usare, supportando la gestione delle eccezioni ecc. L'aritmetica del puntatore e l'assemblaggio in linea possono essere relegati in parti del codice esplicitamente contrassegnate come non sicure. Il codice non sicuro è consentito, ma fortemente scoraggiato.

11. Comportamento indefinito

Lo standard linguistico dovrebbe specificare come deve comportarsi il programma in tutte le circostanze tranne che nel codice esplicitamente contrassegnato come non sicuro, ovvero non dovrebbe esserci un comportamento indefinito al di fuori dei blocchi non sicuri. Ciò consente al linguaggio di essere utilizzato come linguaggio di sviluppo di applicazioni praticabile, pur consentendo di dire, scrivere un sistema operativo al suo interno.

Questo è tutto ciò che riesco a pensare al momento, ma modificherò / aggiornerò il post mentre penso a più cose.


5
Date un'occhiata di "D Programming Language": digitalmars.com/d
Wizard79

Per quanto posso ricordare, D non ha una digitazione dinamica opzionale o un tipo intero con intervallo illimitato incorporato. Il tipo intero non è un gran problema, ma la mancanza di una tipizzazione dinamica opzionale lo rende piuttosto poco attraente.
Chinmay Kanchi,

1
Vorrei davvero aggiungere un decimaltipo qui.
configuratore

3
"Un tipo nullo o nessuno che può essere assegnato a una variabile di qualsiasi tipo." - Incluso il valore booleano? :-p
Timwi,

1
Non vedo "flessibile" nel post originale. Inline Assembler non mi viene in mente come requisito fondamentale per un linguaggio di programmazione. Forse questo secondo Felix von Leitner al giorno d'oggi la scrittura di Assembler ti dà per lo più risultati lenti e errati.
LennyProgrammers,

7

Ecco come sarebbe il mio linguaggio di programmazione dei sogni:

  • Un potente sistema di tipo statico con supporto per la digitazione dipendente.
  • Digitazione dinamica opzionale.
  • Torre numerica alla Lisp, ma digitata staticamente.
  • Macro alla Lisp.
  • Principalmente un linguaggio di programmazione funzionale con supporto di base per la programmazione imperativa (come la famiglia ML).
  • Raccolta dei rifiuti.
  • Tipo di inferenza.
  • Continuazioni.
  • Semantica pigra opzionale.
  • Tutti i costrutti di controllo sarebbero forniti sotto forma di funzioni di libreria. (Ciò può essere reso possibile utilizzando le ultime due funzioni.)
  • Sintassi minima (non tanto quanto Lisps, ma qualcosa del tipo di Ioke / Seph.)

Suona bene. Non ho davvero visto un buon modo per fare macro staticamente sicure.
Jörg W Mittag,

@ Jörg: Nemerle?
missingfaktor il

In Smalltalk tutte le strutture di controllo sono in realtà metodi e non usa continuazioni nella loro implementazione. Uno non è necessario per l'altro.
Oak

@Oak, puoi implementare Python yieldin Smalltalk? Dovrebbe essere pulito da usare.
missingfaktor il

Un meccanismo simile al rendimento è già implementato in smalltalk come metodo di libreria, senza continuazioni.
Oak

6

Lo avrei progettato più o meno come C #, ma Microsoft mi ha battuto. :)

(Tranne ovviamente che il mio sarebbe stato meno ben pensato e più dilettante.)

Non mi importa molto se è compilato o interpretato, quindi non ho bisogno di giustificare quel bit.

Per quanto riguarda la tipizzazione statica forte, trovo difficile capire perché ciò richieda persino una giustificazione. La digitazione statica è una funzione che rileva i bug durante la compilazione. La digitazione dinamica è la mancanza di tale funzionalità e difende i bug fino al runtime. Nella mia esperienza personale ho avuto pochi casi d'uso in cui il dispacciamento dinamico aveva senso ed era utile, quindi le convoluzioni che dovevo attraversare in C # prima della 4.0 per ottenerlo erano facilmente giustificabili. Con C # 4.0 non ho nemmeno più bisogno di giustificarlo perché ora abbiamo un dispaccio dinamico.

Tuttavia, probabilmente avrei creato una nuova sintassi invece di attenermi religiosamente alla vecchia sintassi C come ha fatto C #. L'istruzione switch è particolarmente orribile e non mi piace nemmeno la sintassi del cast (è il modo sbagliato di aggirare). Non mi preoccupo molto dei dettagli della sintassi, quindi non ho bisogno di giustificarlo in dettaglio, tranne per il fatto che non lo vorrei verboso come Visual Basic.

Cos'altro vorresti che giustificassi?


+1 Buona risposta! Ne pubblicherò uno anche io in seguito.
Chinmay Kanchi,

4
C # è un linguaggio potente, ma la sintassi è spesso disordinata. Penso che sia perché molte di queste funzionalità non erano nel design originale.
Casebash,

Quindi "4.0", immagino.
Segna C

5

Bene, ecco un elenco di funzionalità che avrei inserito:


Lisp come sintassi

Stile Lisp

Professionisti :

  • Sintassi facilmente estensibile. Hai mai provato a implementare un ciclo foreach in C? Non è esattamente facile. (Intendiamoci, ho fatto ).
  • Homoiconicity. Puoi semplicemente(eval "your data files")

Contro :

  • La notazione polacca nidificata è spesso difficile da leggere

Programmazione Funzionale

Stile Haskell

Pro :

  • Facile concorrenza, tutto il codice è thread-safe.

Contro :

  • Difficile implementare effetti collaterali in puro codice funzionale, anche se le monadi sembrano fare un buon lavoro.

Digitazione dinamica forte

Stile pitone

Pro :

  • La digitazione dinamica rende il codice leggibile pulito, la digitazione forte può eliminare gli errori di tipo

Implementazione :

Consenti il ​​sovraccarico delle funzioni in base a tipi, simili ai CL defgeneric:

(define (+ (a <int>) (b <int>))
  (ints-add a b))

(define (+ (a <string>) (b <string>))
  (string-concat a b))

(define (+ a b)
  (add-generic a b))

Compilabile e interpretabile

Pro :

  • Aumento delle prestazioni se compilato (di solito vero, non sempre)

Contro :

  • Può limitare le funzionalità nella lingua, tuttavia llvm sarebbe un buon appoggio.

Programmazione di sistemi

Stile C.

Pro :

  • Fa appello a una gamma di utenti leggermente più ampia.
  • Più facile per applicazioni, kernel e driver di dispositivo interagire se sono tutti scritti nella stessa lingua

Contro :

  • Limita le astrazioni nella lingua, la digitazione dinamica spesso non è adatta.

Macro igieniche (stile CL e stile schema)

Pro :

  • Facile estendere la lingua, specialmente con la sintassi Lispy ™
  • L'ho già detto prima, vero?

Contro :

  • Non molti se fatto con la sintassi Lispy ™

Pensaci, questo schema più o meno definisce, ad eccezione del bit di compilazione e programmazione dei sistemi. Ciò può essere risolto usando libguile e scrivendo quei bit in C.


1
Dai un'occhiata a Ioke e Seph. È incredibile quanto più facilmente leggibile una lingua possa aggiungere aggiungendo solo una piccola quantità di sintassi rispetto alle S-Expressions e avere ancora le funzionalità macro complete. (Fondamentalmente, invece di "ogni chiamata di funzione è un elenco e gli elenchi sono di prima classe" è "tutto è un messaggio inviato e le catene di messaggi sono di prima classe". Invece di un elenco di cui carè la funzione e cdrsono gli argomenti, hai un oggetto il cui namecampo è il metodo e il cui argumentscampo sono gli argomenti. E invece di annidare, hai preve nextcampi puntatore.)
Jörg W Mittag

Sembra quasi esattamente Clojure (supponendo che tu usi Mjolnir per la generalizzazione del codice nativo su LLVM per la parte di programmazione dei sistemi - github.com/halgari/mjolnir )
mikera,

3

Ci sono diverse lingue là fuori che considero dannatamente buone (C # è il mio preferito attuale). Dal momento che questo è il mio linguaggio fantasy, ecco cosa voglio davvero avere:

  • Documentazione API ufficiale ufficiale. L'API Java è buona in questo modo e C # /. NET è piuttosto buona. Ruby / Rails è piuttosto terribile qui.
  • Documentazione generale ufficiale Kick-ass (istruzioni, usi comuni, molti esempi di codice). C # /. Net è buono per questo.
  • Un'enorme comunità di documentatori basati su blog e risolutori di problemi StackOverflow per aiutarmi a superare i punti difficili
  • Una vasta gamma di plugin / librerie / estensioni ben supportate, ben documentate e potenti (Ruby / Rails ha "potenti" ma nessuna delle altre due).
  • È ragionevolmente stabile: non è necessario cambiare tutto per interrompere la maggior parte del codice esistente su base annuale (ti guarda, Ruby / Rails).
  • Non è troppo stabile, è in grado di adattarsi ai progressi nella progettazione del linguaggio (ti guarda, c ++)

2
I punti della "documentazione di Kick-ass" dovrebbero includere PHP: D
Corey il

3

Suggerimenti per il compilatore

Sto parlando fuori di me, dal momento che non so molto del design del linguaggio, ma penso che la caratteristica di cui sto parlando si chiami suggerimenti in altre lingue. Suggerimenti per il compilatore , forse?

Non so se l'ho letto in una bozza di Perl6 o al momento ero solo in alto, ma immagino un linguaggio in cui tutto per impostazione predefinita è vagamente volgare e automagico. Ma se volessi davvero migliorare le prestazioni e dire, ehi, questo valore è sempre un numero intero o non è mai nullo, o questo può essere parallelo, o questo è apolide, cose del genere ... Che il compilatore potrebbe andare automaticamente in città su queste aree specificamente contrassegnate.

E: Gradirei commenti che chiariscano cosa sto chiedendo o citando esempi in cui questo esiste già.


1
Puoi farlo in Common Lisp. Ad esempio, puoi dire al compilatore che i è un numero intero di dimensioni ragionevoli. Una cosa utile è che, variando i valori safetye speed, è spesso possibile fare in modo che il compilatore controlli e imponga (per trovare i problemi) o supponga che ciò che dici sia vero (e compili codice più veloce).
David Thornley,

2

Per provare nuove idee:

Vorrei creare un linguaggio di programmazione funzionale di tipo dinamico, che ti permetta di fare tutti i trucchi di espressione delle espressioni e la sintassi lambda più semplice con pattern matching. Regola off-side abilitata.

// a view pattern (or Active Pattern in F#)
default = \def val: !!val.Type val def

// usage of the pattern
greet = \name<(default "world") `and` hasType Str>:
  p "Hello, \{name}!"

(p "Enter your name", .input).greet // (, ) is a sequence expression, returning the last value

Ecco una spiegazione:

default =imposta la memoria, \def valinizia una funzione curry con due argomenti, val.Typeè uguale a Type[val], !!converte in booleano e booleano può essere applicato, quindi valedef are after it.

f x= f[x]= x.f .f=f[]

e in greet, ha usato name<(default "world")e hasType Str>, significa che il modello default "world"sarà usato e legato name. Il modello predefinito specifica un valore predefinito. andè un altro modello che incatena due modelli insieme. lo defaultschema non può fallire mentrehasType può fallire. In tal caso, genera un'eccezione.

Le variabili sono in realtà archivi, che possono essere passati in modo funzionale e le tabelle di archiviazione possono essere riferimenti, creati e distrutti al variare degli ambiti.

Hash e simili saranno come in Lua e JavaScript.

Se ho intenzione di creare un linguaggio compilato, creerò un F # per Java, con funzionalità simili a Haskell. È un linguaggio funzionale puro, tranne per il fatto che esiste una funzione che mescola citazioni e Comp Exprs per ottenere una programmazione imperativa scrivendo blocchi simili a pseudocodici.


1
Sembra un po 'come Erlang, un linguaggio di programmazione funzionale tipizzato dinamico e aggiunto a ciò che un linguaggio concorrente abbastanza unico costruisce.
Jonas,

2

Tenendo presente che le uniche lingue che conosco sono PHP e javascript e che dovrei davvero imparare un po 'di più prima di progettare una lingua:

Sintassi: pensa attentamente ai nomi delle funzioni e all'ordine degli argomenti (ovvero, sii meno disordinato di PHP).

Caratteristiche: hanno un set di stringfunzioni, che operano su variabili come una serie di byte, ma non comprendono il testo, e un set di textfunzioni, che comprendono molte codifiche e possono operare su UTF-8 e altre stringhe multibyte. (E hanno codifica dei controlli di integrità integrati nel linguaggio, con una funzione come quella text.isValidEncoding(text, encoding)che ti dirà se una sequenza di byte è malformata e non sicura da trattare come testo.

Penso che mi piaccia l'idea di una forte tipizzazione statica, ma non l'ho mai usata, quindi non posso davvero dirlo.


2

Prima di progettare un linguaggio di programmazione, troverei una buona risposta alla domanda: perché abbiamo bisogno di un altro linguaggio di programmazione? Codice Rosetta al momento della stesura di questo elenco elenca 344 lingue. Se nessuno di questi rispondesse alle mie esigenze, i dettagli del perché non determinerebbero il punto di partenza (le lingue che si avvicinano di più) e ciò che sarebbe aggiunto ad esso.

Se vincessi alla lotteria e per qualche ragione non avessi nulla di meglio da fare, inizierei con Liskell e lo trasformerei in un vero e proprio linguaggio al contrario di un front-end GHC, quindi renderebbe FFI più semplice (e automatizzato) in modo da poter usare qualsiasi Libreria C / C ++.


2

Una buona lingua è una lingua che è:

  • facile ragionare su (nessuna sintassi oscura)
  • ti consente di esprimere le tue idee con la minima distorsione
  • ti nascondi i dettagli grintosi (ottimizzazione / gestione delle risorse)
  • facilmente parallelizzabile (più core, calcolo distribuito)

È piuttosto difficile trasformarlo in un elenco di funzionalità, ma penso che la Programmazione funzionale, sebbene non sembri naturale , sia più vicina a questa rispetto alla programmazione imperativa (specialmente nel nascondere i dettagli grintosi)

  • Interfaccia C: C è la lingua franca dei linguaggi di programmazione e il numero di librerie sviluppate in C è sorprendente. Avendo un'interfaccia semplice (come Python) con C, il linguaggio beneficia automaticamente di tutte quelle librerie e consente anche di inviare compiti pesanti che non potrebbero essere abbastanza ottimizzati per un linguaggio simile al metal.
  • Distribuito : mi piace prendere Go nel multi-threading, con routine leggere che il runtime invia sui thread in base alla loro attività. Tale linguaggio incoraggia il programmatore a ragionare sui compiti e a isolarli gli uni dagli altri.
  • Garbage Collection : va da sé al giorno d'oggi;)
  • Immutabile : molto più facile ragionare su qualcosa che non può mai mutare, molto più facile implementare anche il multithreading / calcolo distribuito (è necessaria solo la sincronizzazione per gestire la durata, che è l'attività del compilatore)
  • Lambdas : suppongo che funzioni con funzioni di prima classe
  • Message Passing : immutabilità non significa mutex, quindi seguiamo il suggerimento di Tony Hoares
  • Moduli : in qualche modo simili agli spazi dei nomi, ma con una migliore incapsulamento
  • Riflessione : il calcolo distribuito richiede la serializzazione, che dovrebbe essere lasciata al compilatore, e la deserializzazione si ottiene più facilmente con una qualche forma di riflessione.
  • Digitazione statica forte : prima viene rilevato un errore, meno costa

Al momento, la lingua più vicina a questo elenco è probabilmente Haskell, sebbene:

  • manca routine: non ho ancora visto un modo naturale per esprimere il parallelismo in Haskell (anche se potrebbe essere la mia ignoranza ...)
  • ha una sintassi oscura: in qualche modo sembra che i programmatori Haskell prosperino usando operatori strani piuttosto che parole. Può sembrare lucido, ma non aiuta molto a capire cosa sta succedendo.

2

Alla tua prima domanda, "come lo faresti" - risposta breve, non lo farei. Non ho abbastanza teoria del parser / compilatore per riuscirci. Ma ho programmato per 25 anni, quindi ho alcune idee e opinioni da condividere.

Prima di tutto, proverei a trovare un approccio OOP che ti consenta di creare modelli veramente connessi. Ciò che intendo con ciò è che i modelli sono una delle cose più importanti in quasi tutti i tipi di progetti di programmazione - è sempre un sacco di lavoro grintoso e refactoring continuo per farlo bene, e lo biasimo per la mancanza di una vera connettività in Lingue OO.

Mi permetta di dimostrare. Diciamo che una casa di classe ha una proprietà Porta.

var door = house.Door;

Ora hai una variabile locale con un riferimento all'istanza Door.

Ma considera quello che è appena successo: hai appena strappato la porta dalla casa e ora sei abbastanza felice di passare la porta in giro, e il resto del tuo codice ignora il fatto che questa porta è effettivamente attaccata a una casa.

Per me, questo è fondamentalmente sbagliato.

E sì, lo so, questo è "facilmente" risolto caso per caso - in questo caso mantenendo un riferimento inverso da ogni porta alla casa a cui è attualmente collegato. Questo ovviamente apre il tuo modello agli errori, poiché ora è tuo dovere mantenere accuratamente due riferimenti inversi, in modo da rendere private le proprietà House.Doors e Door.House e aggiungere metodi come House.AddDoor (), House.RemoveDoor ( ), Door.SetHouse () ecc. E cablare il tutto e testarlo per accertarsi che funzioni effettivamente.

Non sta iniziando a sembrare un sacco di lavoro per modellare una relazione così diretta? Un sacco di codice da mantenere? Un sacco di codice per refactoring mentre il modello si evolve?

Il problema sono i puntatori. Ogni linguaggio OO che ho visto soffre intrinsecamente del fatto che un riferimento ad oggetto è davvero un puntatore, perché è quello che usano i computer.

I puntatori non sono un buon modo per modellare il mondo reale. Indipendentemente dal mondo che stai cercando di modellare, è quasi garantito che qualsiasi relazione in quel mondo sarà a doppio senso. I puntatori puntano solo in una direzione.

Vorrei vedere un linguaggio in cui il modello di dati fondamentale è un grafico - in cui tutte le relazioni, per impostazione predefinita, hanno due fini. Ciò fornirebbe quasi sicuramente una misura molto più naturale per modellare il mondo reale, che è davvero l'unica cosa di cui abbiamo bisogno dei computer in primo luogo. (quello e i videogiochi.)

Non ho idea di come sarebbe la sintassi di una tale lingua, o se possa anche essere plausibilmente espresso usando il testo. (Mi chiedevo se un tale linguaggio dovesse essere grafico, in qualche modo ...)

Vorrei anche vedere tutte le forme di stato accidentale eliminate.

Ad esempio, nello sviluppo web, dedichiamo molto tempo a modellare i dati da database, a modelli di business, a modelli di visualizzazione per la presentazione ... quindi alcuni di questi dati vengono presentati su moduli, il che è in realtà solo un'altra trasformazione. .. e lo stato ritorna dai post dei form, e quindi rimodelliamo quei dati e li proiettiamo di nuovo sul modello di vista, ad es. leganti del modello di vista e simili ... poi proiettiamo dal modello di vista sul business- modello ... utilizziamo quindi mappatori relazionali a oggetti (o grunt work) per trasformare i dati dal modello di visualizzazione e proiettarli su un database relazionale ...

Sta iniziando a sembrare ridondante? A che punto durante tutta questa follia abbiamo davvero realizzato qualcosa di utile? E per utile intendo qualcosa di tangibile, qualcosa che l'utente finale può capire e preoccuparsi. Alla fine della giornata, le ore che hai trascorso a costruire qualcosa che gli utenti possono persino capire, sono davvero le uniche ore ben spese. Tutto il resto è effetti collaterali.

Vorrei un linguaggio altamente dinamico. Il ciclo di scrittura / compilazione / esecuzione è una noiosa perdita di tempo. Idealmente, la lingua dovrebbe solo capire cosa è cambiato e compilare / caricare in modo trasparente, in background, se necessario.

Idealmente, non dovresti nemmeno premere "corri": le cose dovrebbero accadere sullo schermo mentre apporti le modifiche, riflettendo immediatamente le modifiche che apporti. Il problema con il ciclo di scrittura / compilazione / esecuzione, o anche per il ciclo di scrittura / esecuzione più diretto, è che sei troppo disconnesso da ciò che stai facendo - per sentirci connessi al nostro lavoro, noi bisogno di feedback immediato, risultati immediati. Ogni attesa è troppo lunga!

Ancora una volta, non so nemmeno se questo potrebbe essere realizzato con un IDE tradizionale o se ciò richiederebbe un tipo di interfaccia completamente nuovo.

Dovresti essere in grado di utilizzare un mix di digitazione debole e forte, qualunque sia la più adatta al problema su cui stai lavorando.

Lo stato in generale dovrebbe essere qualcosa che la lingua gestisce completamente per te. Perché dovresti fare affidamento su un database per la persistenza? Idealmente, vorrei essere in grado di specificare semplicemente il periodo di vita di qualsiasi variabile nel modello: una richiesta Web, una sessione, 24 ore, in modo permanente.

Perché dobbiamo scegliere tra una vasta gamma di soluzioni di archiviazione per diversi supporti e termini di vita? - per non parlare di trasformare e modellare i dati per adattarli a ciascun supporto; cache del browser, database, memoria, disco, a chi importa! I dati sono dati. Dove conservi i tuoi dati (e per quanto tempo) dovrebbe essere una scelta semplice, non una battaglia contro gli dei!

Bene, buona fortuna con quello.


1

Probabilmente sarebbe un linguaggio multi paradigma, che supporta quanto segue:

  • Programmazione strutturata / procedurale
  • Programmazione orientata agli oggetti
  • Programmazione funzionale

Perché questi? Orientato agli oggetti perché è un ottimo modo per organizzare programmi di grandi dimensioni, in particolare per l'organizzazione dei dati. Strutturato perché non sempre lo desideri / ne hai bisogno (OOP), le persone dovrebbero scegliere. Funzionale perché semplifica il debug dei programmatori e rende i programmi più chiari.

Vorrei usare il modello di Python con blocchi rientrati per contrassegnare i blocchi di codice. È molto simpatico e piacevole da leggere.

Vorrei rubare molte idee da Python in realtà perché Python è un linguaggio molto carino. Lo prenderei per affermazione e copierò le sue mappe, elenco e tuple.

Ora, probabilmente non prenderei i concetti dinamici da Python: per prima cosa, sarebbe probabilmente esplicitamente e tipicamente statico. Penso che i programmi diventino più chiari con questo. Le variabili sarebbero probabilmente tutti oggetti con metodi, quindi potresti fare qualcosa di simile str.length()per ottenere la lunghezza di una stringa. Nelle definizioni delle funzioni, è necessario specificare il tipo restituito e i tipi degli argomenti (supportando anche alcuni tipi di tipi generici).

Torniamo alla copia da Python ;-). Adoro il modo di avere argomenti di procedura opzionali, quindi probabilmente avrei questo. Python tuttavia non supporta il sovraccarico delle procedure, lo vorrei.

Diamo un'occhiata alle classi, abbandonerei l'eredità multipla; facile da abusare. Implementerei ambiti privati ​​e simili e probabilmente lo implementerei nel modo in cui è fatto in C ++. Avrei anche classi e interfacce astratte; Non credo che Python lo abbia.

Supporterebbe le classi interiori, infatti, vorrei un linguaggio orientato agli oggetti molto potente.

Probabilmente sarebbe interpretato. È possibile ottenerlo molto velocemente usando una buona compilazione JIT (vorrei un linguaggio veloce, anche se la produttività del programmatore verrebbe prima) e la compilazione è semplicemente dannosa per la produttività in molte volte. Le lingue interpretate promuovono anche l'indipendenza della piattaforma, qualcosa che conta sempre di più per ogni giorno.

Avrebbe integrato il supporto Unicode; oggigiorno l'internazionalizzazione conta molto.

Sarebbe sicuramente la spazzatura raccolta. Accidenti, odio fare da solo la gestione della memoria; non va bene neanche per la produttività.

Infine, avrebbe una buona libreria standard.

Wow, ho appena realizzato quanto adoro Python.


Perché Interpreted languages also promote platform independance? Immagino che ci siano più interpreti multipiattaforma piuttosto che compilatori (percentuale), ma non riesci a capire perché questa frase dovrebbe essere vera? Penso che non ci sia alcuna differenza tra loro, per quanto riguarda le abilità multipiattaforma.
Mahdi,

1

Prima di tutto, vorrei comprare alcuni libri sui compilatori, alcuni standard e seguire un corso o due in lingue e compilatori. Contribuirò ai PEP e visiterei le riunioni del comitato sugli standard C ++. Darei delle patch ai compilatori che uso, speriamo sia per le funzionalità che per i bug.

Poi torno indietro e guardo con orrore questo elenco che ho trovato ora, che è di quali direzioni seguirei una lingua se iniziassi proprio ora:

  • Funzionale , perché attualmente non sono esperto di alcun linguaggio funzionale e crearne uno sarebbe un ottimo modo per impararne uno. Nel caso in cui non segua direttamente: tutto è costante .
  • Lo riempirei con tutta l' Inferenza di Tipo che potrei inserirvi, ma con l'opzione di specificare esplicitamente le interfacce. Non sono sicuro di altri tipi. Questo raddoppia perché tutte le funzioni sono generiche per impostazione predefinita.
  • Come avrai intuito, con le interfacce ; vale a dire, con tipi che forniscono solo promesse sulle operazioni disponibili.
  • Dire se la lingua è tipizzata in modo forte o debole non è molto significativo in questo caso, per quanto ne so. Lo definirei fortemente tipizzato, poiché le cose non cambiano mai quali interfacce implementano .
  • Avrebbe molto supporto Design by Contract . Ancora una volta, per quanto posso adattarmi: precondizioni e postcondizioni sono un must; Non so quanto siano importanti gli invarianti quando si tratta di programmazione funzionale.
  • Mentre ci sono, darei un'occhiata alle lingue in cui puoi formalmente dimostrare la correttezza e vedere se riesco a raccogliere qualcosa da lì.
  • Vorrei uscire e scrivere una fantastica libreria di test . Anche nel caso in cui non riuscissi a renderlo fantastico, almeno passerò una notevole quantità di tempo a lavorarci perché penso che sia qualcosa che ogni lingua dovrebbe avere.
  • Per quanto riguarda la sintassi, il linguaggio avrebbe uno spazio significativo e assomiglierebbe molto a Python , oppure sarebbe basato su Lojban e condivideva molto la grammatica e il vocabolario. Nel primo caso, farei del mio meglio per rendere la grammatica il più vicino possibile a un CFG.
  • Non mi importa se le persone che hanno implementato il linguaggio lo compilaranno in anticipo, JIT, lo interpreterebbero, cantano ai falò o pagano i ragazzi del college per eseguirla per loro. La mia implementazione probabilmente dovrebbe iniziare come un interprete o un compilatore C, e alla fine si sposterà verso un JITter.

Visto che anche questi punti abbastanza ampi probabilmente cambieranno rapidamente se avessi iniziato a implementare il linguaggio, quindi penso che non sia necessario approfondire i dettagli.


0

Se avessi il tempo, progetterei un localizzabile linguaggio di programmazione basato su Scala, quindi avrebbe la maggior parte delle sue caratteristiche, tranne probabilmente per XML. Il mio obiettivo è quello di creare una lingua che legga quasi naturalmente in lingue con una struttura diversa dall'inglese, come l'arabo (la mia lingua madre). Sto pensando alle seguenti caratteristiche:

  • Una #langdirettiva pre-processore , utilizzata per informare il pre-processore del linguaggio umano utilizzato per la programmazione. Ad esempio: #lang arconsentirebbe l'uso della parola فئةanziché class,عرف anziché defe così via. Le parole chiave specifiche della lingua umana verrebbero definite in file di preprocessore standard.
  • Il pre-processore rimuoverà alcune parole chiave opzionali il cui unico scopo è quello di aggiungere chiarezza al codice. Ad esempio, rimuove "è composto da" in class MyClass is composed of {per diventare class MyClass {e rimuove "come" indef MyMethod(x: Int) as { per diventare def MyMethod(x: Int) {. In alcune lingue (umane), questo renderebbe il codice molto più facile da capire, specialmente per gli studenti.
  • Il compilatore consentirebbe l'uso della notazione del prefisso per l'accesso alle proprietà. Questo potrebbe non avere senso per la maggior parte dei parlanti di lingua latina, ma per alcune altre lingue ha perfettamente senso. Ad esempio, l'accesso alla proprietà in arabo è normalmente prefisso, come in اعرض طول اسم محمد, che equivale aprint(length(name(Mohammad))) nella programmazione-inglese. (Le parentesi sono per chiarezza.)

Credo che queste minime modifiche al pre-processore e al compilatore renderebbero la programmazione molto più semplice per chi non parla inglese.


5
Microsoft (e alcuni altri prima) creavano versioni localizzate di VBA (applicazioni Visual Basic for Office). E 'stato un casino. Sebbene sia utile per i neofiti, i giovani e le persone non inglesi leggere il codice nella loro lingua madre, è molto difficile condividere il codice con persone al di fuori del proprio paese. Ai nostri giorni su Internet, lavorare in isolamento non è molto produttivo. Se dovessi fare affidamento solo su fonti francesi (articoli di blog, libri, ecc.) Per imparare Scala (come faccio attualmente), mi mancheranno molte informazioni utili. Per non parlare della difficoltà / quantità di lavoro per localizzare le biblioteche ...
PhiLho,

1
@PhiLho: Hai certamente ragione. Ma il mio scopo principale di creare una lingua del genere è quello di essere in grado di presentare la programmazione a un pubblico molto più ampio, compresi studenti K-12 e persone anziane che potrebbero non essere competenti in inglese. A livello introduttivo, probabilmente non hanno bisogno di usare librerie esterne e creare involucri localizzati per alcuni piccoli (ad es. print) Non farebbe male.
Hosam Aly,

1
L'altro punto è che molte persone usano già le loro lingue native per nomi di classi e metodi. Non li aiuta che le parole chiave siano in inglese, né fa differenza per le altre persone, poiché le parole chiave non sono sufficienti per comprendere il codice non inglese. Tuttavia, il pre-processore può sempre sostituire le parole chiave in inglese e, se necessario, in qualsiasi altra lingua.
Hosam Aly,
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.