View Full Version : Linguaggi di programmazione con tipi statici
Sto studiando per un'esame sui linguaggi di programmazione. Mi sono imbattuto in questa domanda..
Si consideri il seguente frammento in uno pseudolinguaggio con tipi statici, dove f e una certa funzione di due argomenti:
int i,j;
float y,z;
y = f(i,j);
z = f(y,i);
Si fornisca (i) una possibile intestazione per la funzione f e (ii) le ipotesi che occorre fare sul sistema di tipi dello pseudolinguaggio anche l'intestazione data in (i) sia corretta.
La prima risposta che mi viene in mente è che se il linguaggio supporta funzioni polimorfe, potrei semplicemente avere una funzione f così definita:
float f(<T1> param1, <T2> param2)
:confused:
Riordian
12-11-2013, 09:13
cavolo la teoria è anni che non la vedo in questi termini... tieni conto di una cosa. A una funzione che richiede float puoi passare degli int quindi la firma
potrebbe essere benissimo float f(float paramA, float paramB) e funzionare tranquillamente ;)
Oceans11
12-11-2013, 09:38
tieni conto di una cosa. A una funzione che richiede float puoi passare degli int quindi la firma potrebbe essere benissimo float f(float paramA, float paramB) e funzionare tranquillamente
in realtà potrebbe anche essere:
int f (int paramA, int paramB)
come pure:
double f (double paramA, double paramB)
e ogni possibile combinazione di tipi numerici dei parametri e del valore di ritorno.
In alcuni casi perdi precisione o avrai troncamento, in altri "sprechi" memoria.
Mentre non credo che tu possa usare tipi parametrici, vista la tipizzazione statica.
Riordian
12-11-2013, 10:36
in realtà potrebbe anche essere:
int f (int paramA, int paramB)
come pure:
double f (double paramA, double paramB)
e ogni possibile combinazione di tipi numerici dei parametri e del valore di ritorno.
In alcuni casi perdi precisione o avrai troncamento, in altri "sprechi" memoria.
Mentre non credo che tu possa usare tipi parametrici, vista la tipizzazione statica.
non penso che in questo caso gli convenga fare una cosa del genere perchè, come dici giustamente anche te, avresti perdita dei dati. A un int non puoi passare float a meno di cast, il compilatore darebbe un errore o comunque, anche se il compilatore facesse dei cast impliciti e non ti desse errore (con c# per esempio non compila proprio comunque, appena provato), perderesti info sul dato. Per esempio se passi un float 3.5 a un int questo legge 3 e perdi info. Visto che questa è la domanda di un test secondo me meglio non fare una cosa del genere ;)
Oceans11
12-11-2013, 11:04
non penso che in questo caso gli convenga fare una cosa del genere perchè, come dici giustamente anche te, avresti perdita dei dati. A un int non puoi passare float a meno di cast, il compilatore darebbe un errore o comunque, anche se il compilatore facesse dei cast impliciti e non ti desse errore (con c# per esempio non compila proprio comunque, appena provato), perderesti info sul dato. Per esempio se passi un float 3.5 a un int questo legge 3 e perdi info. Visto che questa è la domanda di un test secondo me meglio non fare una cosa del genere ;)
#include <stdio.h>
int f (int paramA, int paramB) {
return paramA+paramB;
}
int main(int argc, char *argv[]) {
float a = 5.5f;
float b = 6.6f;
printf("somma: %d\n", f(a,b));
return 0;
}
codice stupido, tanto per provare.
compilato con
gcc -Wall -pedantic -o test test.c
neanche un warning. Dà il risultato che mi aspettavo senza cast.
gcc 4.8.2
tra l'altro c# permette i generici, non credo sia un linguaggio fortemente tipizzato
Riordian
12-11-2013, 11:47
#include <stdio.h>
int f (int paramA, int paramB) {
return paramA+paramB;
}
int main(int argc, char *argv[]) {
float a = 5.5f;
float b = 6.6f;
printf("somma: %d\n", f(a,b));
return 0;
}
codice stupido, tanto per provare.
compilato con
gcc -Wall -pedantic -o test test.c
neanche un warning. Dà il risultato che mi aspettavo senza cast.
gcc 4.8.2
tra l'altro c# permette i generici, non credo sia un linguaggio fortemente tipizzato
guarda ho provato, una cosa del genere o la casto o non compila. E il risultato che mi darebbe è 11 invece di 12.1.
Oceans11
12-11-2013, 11:49
guarda ho provato, una cosa del genere o la casto o non compila. E il risultato che mi darebbe è 11 invece di 12.1.
11 è il risultato che mi aspetto infatti. Il problema della compilazione starà nel compilatore che usi. Qual'è?
Oceans11
12-11-2013, 11:53
wikipedia (http://it.wikipedia.org/wiki/C_sharp#Differenze_con_C_e_C.2B.2B)
Gli ultimi due punti dell'elenco:
* Le sole conversioni implicite consentite sono quelle "safe", ovvero che non espongono al rischio di perdita di dati causata dalla diversa tipologia di dato. Ad esempio non sono consentite conversioni implicite fra integer e boolean o fra enumerati ed integer.
* C# non possiede i "template" (tipici del C++), ma nella versione 2.0 sono stati introdotti i "generic".
alla luce di questo dicevo che c# non ha tipizzazione statica, quindi non è questo il caso. In c89 invece si può fare, se sai cosa stai facendo.
Riordian
12-11-2013, 12:08
wikipedia (http://it.wikipedia.org/wiki/C_sharp#Differenze_con_C_e_C.2B.2B)
Gli ultimi due punti dell'elenco:
alla luce di questo dicevo che c# non ha tipizzazione statica, quindi non è questo il caso. In c89 invece si può fare, se sai cosa stai facendo.
è proprio questo il punto, troppi rischi per farlo secondo me. Sono pochi i casi in cui sei assolutamente sicuro che una chiamata del genere non provochi danni all'applicazione. ;)
Riordian
12-11-2013, 12:19
wikipedia (http://it.wikipedia.org/wiki/C_sharp#Differenze_con_C_e_C.2B.2B)
Gli ultimi due punti dell'elenco:
alla luce di questo dicevo che c# non ha tipizzazione statica, quindi non è questo il caso. In c89 invece si può fare, se sai cosa stai facendo.
http://msdn.microsoft.com/it-it/library/ms173105%28v=vs.90%29.aspx (http://msdn.microsoft.com/it-it/library/ms173105%28v=vs.90%29.aspx)
Oceans11
12-11-2013, 12:22
è proprio questo il punto, troppi rischi per farlo secondo me. Sono pochi i casi in cui sei assolutamente sicuro che una chiamata del genere non provochi danni all'applicazione. ;)
Posso essere d'accordo, ma al quesito "si fornisca una possibile intestazione per la funzione f" non mi sento di escludere anche queste. Sono quantomeno da considerare, anche per sottolineare il comportamento di un linguaggio staticamente tipizzato e dei suoi compilatori.
Detto questo, personalmente, tra le varie risposte poi, sceglierei quella che procuri meno problemi. ;)
ps: grazie per il link, devo non aver capito le differenze tra staticamente tipizzato e le conversioni di tipo.
Riordian
12-11-2013, 12:29
Posso essere d'accordo, ma al quesito "si fornisca una possibile intestazione per la funzione f" non mi sento di escludere anche queste. Sono quantomeno da considerare, anche per sottolineare il comportamento di un linguaggio staticamente tipizzato e dei suoi compilatori.
Detto questo, personalmente, tra le varie risposte poi, sceglierei quella che procuri meno problemi. ;)
Questo è sicuro,
Di nulla per il link ;) servirà anche al ragazzo che ha aperto il post magari che si sarà perso nelle nostre discussioni ;)
Oceans11
12-11-2013, 12:33
ok, in realtà non avevo proprio capito una mazza! :oink:
per tipizzazione statica si intende che il tipo di una variabile è deciso a compile time.
c, java, c#, c++ vs javascript (ad esempio) o python.
(Non riesco ad ogni modo a spiegarmi i generici e i template, o il polimorfismo)
le conversioni (implicite ed esplicite) dipendono dunque dal compilatore e linguaggio, a prescindere dalla tipizzazione.
@g0t3nk5: sorry per il leggero OT, spero sia stato utile.
vendettaaaaa
12-11-2013, 12:34
tra l'altro c# permette i generici, non credo sia un linguaggio fortemente tipizzato
I generici sono come i template del C++ dal punto di vista della tipizzazione, che rimane forte e statica. C# è anche più tipizzato di C++ perchè non permette appunto di assegnare un double ad un int senza cast esplicito, cosa permessa in C++ perchè si porta dietro la retrocompatibilità col C.
Oceans11
12-11-2013, 12:39
I generici sono come i template del C++ dal punto di vista della tipizzazione, che rimane forte e statica. C# è anche più tipizzato di C++ perchè non permette appunto di assegnare un double ad un int senza cast esplicito, cosa permessa in C++ perchè si porta dietro la retrocompatibilità col C.
e la questione del polimorfismo?
Riordian
12-11-2013, 12:47
e la questione del polimorfismo?
non sono un bravo prof per cui ti passo un link ;)
http://msdn.microsoft.com/it-it/library/ms173152.aspx
poi io mi ricordo che anche l'overload era una tecnica per il polimorfismo oltre l'override
http://msdn.microsoft.com/it-it/library/vstudio/ms229029%28v=vs.100%29.aspx
vendettaaaaa
12-11-2013, 13:08
e la questione del polimorfismo?
Parli di ereditarietà. Il polimorfismo è una conseguenza dell'ereditarietà.
E' una cosa necessaria perchè altrimenti si escluderebbe una grossa fetta di problemi risolvibili con il linguaggio.
Semplicemente: in alcuni casi non è in alcun modo possibile stabilire a compile time il tipo di oggetti che saranno utilizzati nel programma. Ad esempio, se il programma chiede all'utente di riempire un array di forme geometriche con triangoli, quadrati, cerchi a suo piacimento.
Tieni conto però che ereditarietà non significa mancanza di tipizzazione. Il tuo programma in C++/C#/Java eccetera dovrà maneggiare, nel senso che allocherà, puntatori alla classe base, ad esempio "FormaGeometrica", e poi assegnerà a questi puntatori oggetti di classe derivata,
FormaGeometrica* forma = new Cerchio(raggio);
allocati dinamicamente nella heap. Quindi non farti ingannare: la tipizzazione è cmq statica, perchè a compile time sai che nella stack allocherai memoria per tenere un puntatore a FormaGeometrica, e solo a runtime assegnerai un oggetto a quel puntatore.
Il polimorfismo è una conseguenza: a prescindere dal fatto che la tua forma geometrica sia un cerchio o un rettangolo, ad un certo punto nel codice vorrai calcolarne l'area. Però il tuo codice viene compilato prima di sapere cosa maneggerai, e quindi devi metterci una funzione che vada bene per tutte le possibili forme geometriche. Allora si stabilisce un'interfaccia comune alle forme geometriche, cioè che ogni oggetto che deriva dalla classe base abbia dei metodi con lo stesso nome, cosicchè il codice scritto a compile time sia valido, ma poi a runtime venga chiamata la versione "specializzata" per quella particolare forma geometrica in modo automatico. Il polimorfismo significa questo: stesso nome della funzione (o metodo) per tutte le classi che derivano da, e quindi hanno proprietà in comune con, una classe base più generica, ma comportamento diverso in base alla vera natura dell'oggetto di quella classe (nell'esempio, cambia la formula con cui si vuole calcolare l'area).
Oceans11
12-11-2013, 13:44
Parli di ereditarietà. Il polimorfismo è una conseguenza dell'ereditarietà.
Tieni conto però che ereditarietà non significa mancanza di tipizzazione. Il tuo programma in C++/C#/Java eccetera dovrà maneggiare, nel senso che allocherà, puntatori alla classe base [...] allocati dinamicamente nella heap.
Quindi non farti ingannare: la tipizzazione è cmq statica, perchè a compile time sai che nella stack allocherai memoria per tenere un puntatore.
perfetto, non potevo chiedere di meglio.
Vi ringrazio a tutti delle risposte, non mi aspettavo una discussione così accesa. :D
Ne approfitto per porre un altro quesito sempre sulla tipizzazione.
Si consideri il seguente frammento di codice Java, dove A e B sono due classi diverse, di tipo non confrontabile:
A[] as = new A[10];
Object[] ao = as;
B[0] = new B();
Si dica se il precedente frammento e corretto oppure no dal punto di vista dei tipi.
Sulla terza riga, ovvero l'assegnamento di B[0], non c'è un errore in quanto l'array B non eiste/non è stato inizializzato??? :confused:
Un'altra domanda che mi ha messo in difficoltà è questa:
Nello scope delle dichiarazioni:
int n;
string s;
int g(int x, real y){...}
si consideri l'espressione
g(f(n), f(s))
Si diano ipotesi sul linguaggio e/o sul nome f anche tale espressione sia correttamente tipizzata.
A differenza della prima domanda del thread in questo caso una variabile è numerica e l'altra di tipo string, che non sono tipi compatibili tra loro (nel senso che non credo che il compilatore farebbe cast implicito).
Grazie di nuovo. ;)
Riordian
12-11-2013, 14:01
Vi ringrazio a tutti delle risposte, non mi aspettavo una discussione così accesa. :D
Grazie di nuovo. ;)
ala fine di tutto la firma della funzione da utilizzare secondo me è questa:
float f(float paramA, float paramB)
a cui puoi passare sia float che int con tipizzazione statica :D
vendettaaaaa
12-11-2013, 14:20
Vi ringrazio a tutti delle risposte, non mi aspettavo una discussione così accesa. :D
Ne approfitto per porre un altro quesito sempre sulla tipizzazione.
Si consideri il seguente frammento di codice Java, dove A e B sono due classi diverse, di tipo non confrontabile:
A[] as = new A[10];
Object[] ao = as;
B[0] = new B();
Si dica se il precedente frammento e corretto oppure no dal punto di vista dei tipi.
Sulla terza riga, ovvero l'assegnamento di B[0], non c'è un errore in quanto l'array B non eiste/non è stato inizializzato??? :confused:
Un'altra domanda che mi ha messo in difficoltà è questa:
Nello scope delle dichiarazioni:
int n;
string s;
int g(int x, real y){...}
si consideri l'espressione
g(f(n), f(s))
Si diano ipotesi sul linguaggio e/o sul nome f anche tale espressione sia correttamente tipizzata.
A differenza della prima domanda del thread in questo caso una variabile è numerica e l'altra di tipo string, che non sono tipi compatibili tra loro (nel senso che non credo che il compilatore farebbe cast implicito).
Grazie di nuovo. ;)
int f(int i);
real f(string str);
Queste sono dichiarazioni di funzioni con lo stesso nome ma lista parametri diversa. Perfettamente lecito, si chiama overloading.
Nel tuo caso, se si ipotizza che ci debba essere una sola f, l'espressione g(f(n), f(s)) come dici tu è sbagliata, non si può convertire da string a numero qualsivoglia. Se prendiamo in conto l'overloading allora è lecita.
Non conosco java, ma il linguaggio dev'essere C++ o C# per via della classe (nel caso di C++) / keyword (nel caso di C#) "string".
n.b.:
int f(int i);
float f(int i);
Questo è illegale: il compilatore non può dedurre quale funzione delle due tu voglia usare se cambia solo il tipo del valore di ritorno, perchè in molti contesti quest'informazione non basta (e i due tipi sono convertibili).
int f(int i);
real f(string str);
Queste sono dichiarazioni di funzioni con lo stesso nome ma lista parametri diversa. Perfettamente lecito, si chiama overloading.
Stupidamente non avevo pensato al fatto che posso usare overloading e non devo per forza avere un unica funzione f, hai perfettamente ragione. :muro:
Thank you! :sofico:
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.