Newsgroup: it.comp.lang.c++
Titolo: Vi piace il seguente codice?

#include "type_inference.h"
#include <iostream>
sum(x,y) { return x+y; }
int main()
{
	UseTypeInference();
	i = 4;
	j = 5.0;
	z = i*j;
	p = "pensavo!";
	std::cout << sum(i,j) + sum(z,2) << std::endl;
	std::cout << sum("non ", p) << std::endl;
}
Funziona con qualsiasi compilatore. Come? Mi vergogno un po' a dirvelo :)
Kiuhnm

 Funziona con qualsiasi compilatore. Come? Mi vergogno un po' a dirvelo :)
Vabbe', ve lo dico, altrimenti pensate che sia peggio di come è in realtà.
Per creare il progetto bisogna compilare, eseguire e ricompilare. Tutto 
qui. Ovviamente si può fare in modo che niente venga ricompilato se non 
necessario.
In questo modo si può fare praticamente di tutto e senza usare 
preprocessori esterni. Si tratta di una sorta di self-modifying SOURCE 
code (in realtà i file originali subiscono modifiche /veramente/ 
minime). Il vantaggio più immediato è che elimina la necessità dei 
template producendo codice che può essere debuggato in tutta comodità. 
Per es. quel codice produce varie funzioni sum come se fossero state 
scritte a mano.
Kiuhnm

 Kiuhnm

 spiega spiega
Guarda che l'idea è molto semplice.
Lungi da me realizzare una cosa del genere: preferisco di gran lunga 
partire da un dialetto di Lisp rendendolo più efficiente. E' molto più 
difficile partire dal C++ ed aggiungere feature di alto livello.
Pensa al codice automodificante:
----code1--code2---------->
In questo caso code1 scrive codice in corrispondenza di code2 e, quando 
arriva il momento, code2 viene eseguito.
La versione in compile-time è un po' più complicata, ma sempre semplice:
- il codice da compilare contiene due parti distinte:
     - "preprocessore"
     - codice utente
- Durante la prima compilazione viene compilato il codice del 
preprocessore quindi si ottiene di fatto un preprocessore.
- Il preprocessore, quando eseguito, esaminerà i file sorgenti 
modificandoli in modo appropriato o piuttosto creando dei file ausiliari 
   in modo da non modificare pesantemente quelli originali. Per non 
alterare il progetto (e dover quindi inserire altri file e rimuovere gli 
originali), gli originali ignoreranno il loro codice includendo quello 
di quelli ausiliari (basta qualche #if, #endif e #include) automaticamente.
- Alla successiva compilazione, verrà compilato il codice utente modificato.
- Il codice sarà così "intelligente" da agire ogni volta nel modo giusto:
   - Se tutti i file ausiliari trasformati sono pronti, verrà compilato 
il codice utente, altrimenti,
   - se manca anche un solo file ausiliario o deve essere aggiornato, 
verrà compilato il "preprocessore" il quale dovrà essere eseguito per 
produrre file ausiliari aggiornati, se necessario.
E' un meccanismo abbastanza semplice, ma se usato correttamente potrebbe 
dare i suoi frutti.
La difficoltà sta ovviamente nello scrivere un analizzatore di codice, 
ma questo non deve farlo l'utente, no?
L'utente dovrà solo spingere F7, F5, F7 e il gioco è fatto.
Il debug avverrà sui file ausiliari che contengono normali 
funzioni/variabili e non si dovrà combattere per es. con messaggi 
d'errore assurdi lunghi 800 righe.
Kiuhnm

Kiuhnm ha scritto:
Approfittando della tua notevole esperienza col preprocessore, 
volevo chiederti una dritta.
Sai se la possibilità di preprocessare del codice ed arrestarsi 
al sorgente "espanso" sia generalizzata ad ogni compilatore 
attuale ?
In subordine (lo so, non riguarda il C++ in sé stesso ma 
l'implementazione di dot NET), sai mica come si debba fare per 
isolare i files sorgente espansi su Visual C++ dot NET 2.0 ?
Ah .... La spiegazione che hai dato sul tuo codice l'ho capita 
solo per sommi capi, se hai tempo, potresti commentare il 
comportamento di qualche riga (dove generavi le funzioni sorgente)
Grazie in anticipo
Soviet_Mario
CUT ALL

Kiuhnm ha scritto:

Anche io nei tempi andati mi divertivo a realizzare improbabili hack in C++.
Non sono convinto valga la pena.
Ogni linguaggio va usato per quello per cui è stato progettato, se hai
necessità particolari usane un'altro.
Saluti  Manlio Perillo

 necessità particolari usane un'altro.
E se non esiste?
Comunque il C++ tramite i template è tutto un hack.
Kiuhnm

 Comunque il C++ tramite i template è tutto un hack.
Mi riferisco alla programmazione funzionale, ovviamente.
Comunque mi limiterò alla libreria del preprocessore. L'ho creata perché 
quella boost non mi ha soddisfatto per niente: è veramente troppo limitata.
Questo post invece riguarda un qualcosa di ipotetico che non ho neanche 
tentato di realizzare, ma che è sicuramente fattibile.
Come ho già detto altrove, quando verrà il momento mi concentrerò su 
Scheme. Non ho la minima intenzione di modificare il C++.
Kiuhnm

 qualche riga (dove generavi le funzioni sorgente)
Quello era solo un codice d'esempio. Niente di più.
La parte che fa il vero lavoro non l'ho scritta affatto.
Il punto è questo: se disponi di un preprocessore.exe fatto da te che 
supporta certe funzionalità, puoi usare programmare in un linguaggio C++ 
speciale. Il problema è che questo potrà essere compilato soltanto da 
chi possiede preprocessore.exe, infatti bisognerà passargli prova.cpp 
ottenendo new_prova.cpp da passare finalmente al compilatore.
preprocessore.exe non fa altro che trasformare il tuo codice da qualcosa 
di incomprensibile (poiché non C++ puro) a qualcosa di comprensibile per 
il compilatore C++.
Questo post parla semplicemente di un metodo alternativo che consiste di 
inglobare questo preprocessore.exe direttamente nel codice sorgente. La 
prima volta che compili il codice viene generato preprocessore.exe. 
Eseguendo quanto hai creato, verranno automaticamente generati tutti i 
file modificati. Ricompilando ancora il progetto, otterrai questa volta 
la compilazione dei codici modificati.
Il codice verrebbe trasformato, per es., in:
//////
#include <string>
double sum(int x, double y) { return x+y; }
double sum(double x, int y) { return x+y; }
std::string sum(const std::string& x, const std::string& y) {
   return x+y;
}
int main()
{
     int i = 4;
     double j = 5.0;
     double z = i*j;
     std::string p("pensavo!");
     std::cout << sum(i,j) + sum(z,2) << std::endl;
	std::cout << sum(std::string("non "), p) << std::endl;
}
//////
o qualcos'altro di tuo gradimento.
A questo punto, la compilazione successiva compilerebbe tale codice.
Kiuhnm

 
grazie in ogni caso delle risposte
CUT
ciao
Soviet

 E se non esiste?
Una combinazione di due (non riesco a immaginare casi in cui ne servano 
tre, ma lasciamo aperta anche questa ipotesi) linguaggi dovrebbe 
risolvere praticamente tutti i casi reali.
Parlo di progetti "grossi".
Per compiti semplici e specifici ... sviluppa il tuo macrolinguaggio.
Se hai un esempio di progetti importante che non è efficacemente 
sviluppabile con i linguaggi esistenti, sono curioso di conoscerne le 
specifiche.

 specifiche.
Si può fare tutto. Resta il fatto che il C++ è efficiente ma 
relativamente di basso livello. Cercare di crearsi qualche comodità in 
più non guasta. Il linguaggio D va in questa direzione, ma è ancora 
troppo giovane. Non credo che avrà molto successo. Probabilmente gli 
hard-coder resteranno col C++ e gli altri passeranno direttamente a 
Python, Ruby, ecc...
Comunque il mio post non voleva essere preso troppo sul serio.
Kiuhnm