Funzioni brevi tutto in una linea...

di il
13 risposte

Funzioni brevi tutto in una linea...

Ciao a tutti,
guardando i sorgenti scritti da vari programmatori, mi sto rendendo conto che il modo in cui un programmatore scrive il suo codice è molto personale.
Ci sono delle linee guida da seguire ma vedo che ogni programmatore poi ci mette del suo, cosa che faccio anch'io perchè alcune regole delle linee guida non rientrano nel mio stile (mentale)
Tutto questo per chiedervi cosa ne pensate delle funzioni brevi tutte in una riga.
Mi spiego meglio con un esempio:

Questo sarebbe l'approccio classico:
//Prototipi
int GetX(void);

//Funzioni
int main(void)
{
   printf("%d\n", GetX());
}

int GetX(void)
{
   return 10;
}
Questo sarebbe l'approccio per il quale vi sto chiedendo un parere.
L'ho visto in un codice sorgente che ho guardato e non mi dispiace perchè a mio avviso rende il codice più breve e più leggibile, ma questo è sempre e solo un mio parere.

//Prototipi
int GetX(void) {return 10;}

//Funzioni
int main(void)
{
   printf("%d\n", GetX();
}
Che ne pensate?
Chiedo perchè nonostante questo approccio mi piaccia, non voglio comunque usare stili di scrittura del codice che agli occhi di un esperto possano risultare palesemente sbagliati.
Grazie.

Stefano

13 Risposte

  • Re: Funzioni brevi tutto in una linea...

    Sicumente è più compatto e leggibile il secondo.

    Il vero problema è che fai una chiamata a funzione inutile, quindi sarebbe meglio usare inline (se il compilatore lo supporta) oppure una macro (con le dovute precauzioni) per le funzioni da una riga
  • Re: Funzioni brevi tutto in una linea...

    Il vero problema è che fai una chiamata a funzione inutile, quindi sarebbe meglio usare inline (se il compilatore lo supporta) oppure una macro (con le dovute precauzioni) per le funzioni da una riga
    Vista così hai ragione, ma ho ovviamente buttato giù un esempio banale.
    Se il caso reale fosse che GetX() è una funzione pubblica che mi restituisce il valore di una variabile static all'interno del file primo.c e io richiamo GetX() dal file secondo.c ecco che non sarebbe più una chiamata a funzione inutile, inline non avrebbe senso e anche la macro perderebbe di valore.
    Sto dicendo cose corrette o sbagliate?
  • Re: Funzioni brevi tutto in una linea...

    Se hai più moduli, i prototipi delle funzioni staranno in un header o in altro modulo con un extern, quindi ti servono per forza...
  • Re: Funzioni brevi tutto in una linea...

    Si ovvio, quello che volevo dire è che in questo caso, se la variabile è privata ed accessibile solo da GetX(), l'uso di Inline o delle macro non sarebbe possibile.
  • Re: Funzioni brevi tutto in una linea...

    Anche SE ogni programmate (SCORRETTAMENTE) usa un suo stile di programmazione,
    LA SOLUZIONE MIGLIORE e' seguire gli standard per quel linguaggio (in generale c'e' ne sono piu' di uno)

    https://isocpp.org/wiki/faq/coding-standard

    anche perche', banalmente, ci sono i ""formatter"" che formattano il codice secondo uno degli standard selezionati.
  • Re: Funzioni brevi tutto in una linea...

    La risposta è : dipende
    Alcuni hanno uno stile "arioso" (io ad esempio), altri più sincopati, altri via di mezzo.
    Paradossalmente ho trovato un famoso programmatore ex sovietico che scrive... come me.

    Suggerimento: guardare su github i sorgenti dei principali programmi open
  • Re: Funzioni brevi tutto in una linea...

    Grazie a tutti per i consigli.
    Detto questo, non ho ancora capito se è corretto scrivere le funzioni brevi in una sola riga

    @migliorabile: Il tuo link parla principalmente di C++, io sto parlando di C, ma essendo fratelli credo di poter fare affidamento lo stesso ai consigli di quel link, tu che dici?

    @+m2+: Mi piace il suggerimenti di guardare i sorgenti dei programmi open più famosi
  • Re: Funzioni brevi tutto in una linea...

    stefanoxjx ha scritto:


    Grazie a tutti per i consigli.
    Detto questo, non ho ancora capito se è corretto scrivere le funzioni brevi in una sola riga
    E chi te lo vieta?
    Se ti piace, fallo.
    Diciamo che non è così scontato che una sola riga sia ben comprensibile
    Se son banali tipo
    
      size_t size() const {return n;}  // get size
    
    ci può anche stare
    già questa è meno immediata
    
      T& operator()(size_t i) {assert(n>0 && (n&(n-1))==0); return data[i&(n-1)];}

    Puoi guardare anche i sorgenti dei sistemi operativi, direttamente, e dei relativi comandi GNU più diffusi.
    O delle librerie.

    Questo è un esempio di stile "semiarioso"
    https://github.com/jemalloc/jemalloc/blob/dev/src/extent.c

    Stile "arioso"
    https://github.com/Bulat-Ziganshin/FARSH/blob/master/farsh.c

    Stdlib, stile MOLTO arioso
    https://github.com/lattera/freebsd/blob/master/lib/libc/stdlib/rand.c

    In sostanza non hai che da sbizzarrirti
  • Re: Funzioni brevi tutto in una linea...

    Volevo aggiungere un commento su un qualcosa tipo questo
    Another emotional reaction against coding standards is caused by coding standards set by individuals with obsolete skills. For example, someone might set today’s standards based on what programming was like N decades ago when the standards setter was writing code. Such impositions generate an attitude of mistrust for coding standards
    ovvero (parlo di C++ più che di C, e ancor peggio Java) nel corso del tempo sono stati aggiunti una caterva di (pressochè) inutili modifiche, talvolta sottilissime, che avrebbero dovuto fornire chissà quali miglioramenti.
    Ciò non è avvenuto (miglioramenti sostanziali), è pressochè tutto o quasi "zucchero sintattico", ma con un effetto collaterale negativissimo: la portabilità è andata a farsi friggere, già più di quanto fosse necessario.

    Mentre un programma C o C++ "vecchio stile" (N decadi fa) potresti riuscire anche a compilarlo oggi, uno scritto con le ultimissime "sticazzievoluzioni" funzionerà solo con le ultimissime versioni dei compilatori X.
    E non riuscirai minimamente a compilarlo su FreeBSD, o Mac OS (che è cugino stretto), magari Windows 32 e perchè no su un non-linux con CPU Annapurna (un NAS), un orologio o quello che ti pare.

    Ecco dunque che, dopo aver speso che so 10 anni per inventarsi un non so che complicatissimo (che praticamente tutti vanno a rileggersi ogni volta nella documentazione internet) introduci una nuova "superfica" evoluzione.
    Peccato che appena lo dovrai compilare su un CentOS 3 (per fare un binario per ESXi) il compilatore si metterà letteralmente a ridere, anzi ti manda una e-mail con "ma sei pazzo?"

    Dunque tutti son capaci a scrivere "hello world" in un nuovo superlinguaggio come "hello world".
    Poi però ti trovi a dover portare che so Excel su un iPhone, e lì vedi subito che la regola

    SE E' SEMPLICE, FORSE, E RIBADISCO FORSE, FUNZIONA

    è d'oro, anzi di platino
    Una sorta di rasoio di Occam al quadrato
  • Re: Funzioni brevi tutto in una linea...

    Vabbè poi una ulteriore osservazione.
    Personalmente NON metto mai e poi mai i prototipi delle funzioni (se non sono esterne), bensì organizzo il codice in modo che siano definite prima del loro utilizzo.
    A parte la velocità di compilazione maggiore (ma non un granchè) non sono costretto a dovermi "sbattere" per - di nuovo - sottigliezze come i parametri di default variati.

    Anzi dirò di più: ultimamente mi capita di fare singoli programmi C/C++ in singolo sorgente (neppure con header), per rendere più facile il deploy su sistemi automatizzati di compilazione (i ports di freebsd nella fattispecie).
    Certo si possono fare makefile giganteschi, che fanno pure la pizza ai quattro formaggi, si possono "diluire" in 100 sorgentini etc.

    Ma resta sempre il punto: che devi fare col programma? Compilarlo su Windows 10 e bon, finita lì?
    Devi farlo funzionare su windows-linux-bsd-mac e magari anche "resto del mondo"?
    Magari nel "resto del mondo" non hai un gmake, ma un make-puro-e-duro, e solo per scrivere quello patirai le pene dell'inferno e, poi, lo dovrai tenere man mano allineato.
    Aggiungi il nuovo pippone.c all'albero dei sorgenti?
    OK, via a rifare tutti i makefile

    Magari proprio quel pippone.c richiede un -wpermissive che NON puoi mettere, perchè per motivi di sicurezza su X non te lo fanno impostare?

    Versione breve: guarda i sorgenti, trovi quelli di google, facebook, insomma di buona parte del "mondo"
  • Re: Funzioni brevi tutto in una linea...

    
    int main(int b,char**i){long long n=B,a=I^n,r=(a/b&a)>>4,y=atoi(*++i),_=(((a^n/b)*(y>>T)|y>>S)&r)|(a^r);printf("%.8s\n",(char*)&_);}
    
    
    #include <stdio.h> 
    
    #define N(a)       "%"#a"$hhn"
    #define O(a,b)     "%10$"#a"d"N(b)
    #define U          "%10$.*37$d"
    #define G(a)       "%"#a"$s"
    #define H(a,b)     G(a)G(b)
    #define T(a)       a a 
    #define s(a)       T(a)T(a)
    #define A(a)       s(a)T(a)a
    #define n(a)       A(a)a
    #define D(a)       n(a)A(a)
    #define C(a)       D(a)a
    #define R          C(C(N(12)G(12)))
    #define o(a,b,c)   C(H(a,a))D(G(a))C(H(b,b)G(b))n(G(b))O(32,c)R
    #define SS         O(78,55)R "\n\033[2J\n%26$s";
    #define E(a,b,c,d) H(a,b)G(c)O(253,11)R G(11)O(255,11)R H(11,d)N(d)O(253,35)R
    #define S(a,b)     O(254,11)H(a,b)N(68)R G(68)O(255,68)N(12)H(12,68)G(67)N(67)
    
    char* fmt = O(10,39)N(40)N(41)N(42)N(43)N(66)N(69)N(24)O(22,65)O(5,70)O(8,44)N(
                45)N(46)N    (47)N(48)N(    49)N( 50)N(     51)N(52)N(53    )O( 28,
                54)O(5,        55) O(2,    56)O(3,57)O(      4,58 )O(13,    73)O(4,
                71 )N(   72)O   (20,59    )N(60)N(61)N(       62)N (63)N    (64)R R
                E(1,2,   3,13   )E(4,    5,6,13)E(7,8,9        ,13)E(1,4    ,7,13)E
                (2,5,8,        13)E(    3,6,9,13)E(1,5,         9,13)E(3    ,5,7,13
                )E(14,15,    16,23)    E(17,18,19,23)E(          20, 21,    22,23)E
                (14,17,20,23)E(15,    18,21,23)E(16,19,    22     ,23)E(    14, 18,
                22,23)E(16,18,20,    23)R U O(255 ,38)R    G (     38)O(    255,36)
                R H(13,23)O(255,    11)R H(11,36) O(254    ,36)     R G(    36 ) O(
                255,36)R S(1,14    )S(2,15)S(3, 16)S(4,    17 )S     (5,    18)S(6,
                19)S(7,20)S(8,    21)S(9    ,22)H(13,23    )H(36,     67    )N(11)R
                G(11)""O(255,    25 )R        s(C(G(11)    ))n (G(          11) )G(
                11)N(54)R C(    "aa")   s(A(   G(25)))T    (G(25))N         (69)R o
                (14,1,26)o(    15, 2,   27)o   (16,3,28    )o( 17,4,        29)o(18
                ,5,30)o(19    ,6,31)o(        20,7,32)o    (21,8,33)o       (22 ,9,
                34)n(C(U)    )N( 68)R H(    36,13)G(23)    N(11)R C(D(      G(11)))
                D(G(11))G(68)N(68)R G(68)O(49,35)R H(13,23)G(67)N(11)R C(H(11,11)G(
                11))A(G(11))C(H(36,36)G(36))s(G(36))O(32,58)R C(D(G(36)))A(G(36))SS
    
    #define arg d+6,d+8,d+10,d+12,d+14,d+16,d+18,d+20,d+22,0,d+46,d+52,d+48,d+24,d\
                +26,d+28,d+30,d+32,d+34,d+36,d+38,d+40,d+50,(scanf(d+126,d+4),d+(6\
                -2)+18*(1-d[2]%2)+d[4]*2),d,d+66,d+68,d+70, d+78,d+80,d+82,d+90,d+\
                92,d+94,d+97,d+54,d[2],d+2,d+71,d+77,d+83,d+89,d+95,d+72,d+73,d+74\
                ,d+75,d+76,d+84,d+85,d+86,d+87,d+88,d+100,d+101,d+96,d+102,d+99,d+\
                67,d+69,d+79,d+81,d+91,d+93,d+98,d+103,d+58,d+60,d+98,d+126,d+127,\
                d+128,d+129
    
    char d[538] = {1,0,10,0,10};
    
    int main() {
        while(*d) printf(fmt, arg);
    }
    
    insomma...
    http://www.ioccc.org

    !!!
  • Re: Funzioni brevi tutto in una linea...

    
    int main(int b,char**i){long long n=B,a=I^n,r=(a/b&a)>>4,y=atoi(*++i),_=(((a^n/b)*(y>>T)|y>>S)&r)|(a^r);printf("%.8s\n",(char*)&_);}
    
    Non è proprio una funzione breve in singola riga come intendevo io

    Il secondo esempio mi piace di più, purtroppo io non ho senso artistico e non riuscirei mai a fare una cosa simile
  • Re: Funzioni brevi tutto in una linea...

    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/ioctl.h>
    #include <sys/time.h>
    #include <termios.h>
    #include <time.h>
    #include <unistd.h>
    int t(){struct timeval t;gettimeofday(&t,0);return t.tv_usec/1000+t.tv_sec*1000;}
    
                                                                #define g(x,y,u,v,s)\
      for(int j=0,X=x,Y=y;j<v&&Y+j<h-X/w&&Y>=0&&X>=0;++j)memcpy(&f[Y+j][X],&s[j*u],u)
                                                          #define l(x,y,w,h,a,b,c,d)\
                        !((x-a>c&&x>=a)||(a-x>w&&a>=x)||(y-b>d&&y>=b)||(b-y>h&&b>=y))
    
                                                                          int main(){
                 struct termios z,o;tcgetattr(0,&z);o=z;z.c_lflag&=~ICANON&~ECHO;
                          z.c_cc[VMIN]=0;z.c_cc[VTIME]=0;tcsetattr(0,TCSANOW,&z);
              srand(time(0));struct winsize v;ioctl(STDOUT_FILENO,TIOCGWINSZ,&v);
                     int h=v.ws_row,w=v.ws_col,A=w*h/100,l=t(),k,s=0,g=1,i,c=0,L;
                              struct V{float x,y;}p={w/2,h/2},b={-3*h},a[A],m[A];
                             char*r=" /\\ /__\\ ^^ ",*n="o0o0OO",u=0,q,f[h+1][w];
                                                                    while(u^'q'){
                                                        float d=(t()-l)*.001;
                                 q=u;do read(0,&u,1);while((u&'p')>=(u|'p'));
                                                         l=t();c+=15;i=h*w-1;
                                                                               K:
                                            L=c*d;L=abs(((i/w)-L)*(i%w)+h*w);
                            (*f)[i]=L%3+L%5+L%7+L%11+L%13+L%17+L%19>14?32:46;
                                                               if(i--)goto K;
                                             u^' '?0:(b.x=p.x+2,b.y=p.y,u=q);
                                                   q^'a'?q^'d'?q^'w'?q^'s'?0:
                                                             (p.y+=d*15):
                                                            (p.y+=d*-15):
                                                             (p.x+=d*20):
                                                            (p.x+=d*-20);
                                                p.x=p.x<0?0:p.x>=w-4?w-4:p.x;
                                                p.y=p.y<0?0:p.y>=h-3?h-3:p.y;
                                                                  b.y+=d*-20;
                                       int Y=b.y,X=b.x;Y*w+X>=0?f[Y][X]=64:0;
                                                                       i=A-1;
                                                                               L:
                                               k=0;struct V*e=&a[i],*z=&m[i];
                                                   e->x+=d*z->x;e->y+=d*z->y;
                         l(b.x,b.y,1,1,e->x,e->y,6,4)&&!g?k=1,s++,b.y=-3*h:0;
                                        e->x<0-3||e->x>=w+3||e->y>=h+2||k||g?
                                                    e->y=-rand()%h*(1+g),
                                                           e->x=rand()%w,
                                                       z->x=-8+rand()%15,
                                                      z->y=10+rand()%5:0;
                                        l(p.x,p.y,4,3,e->x,e->y,3,2)?u='q':0;
                                                          g(e->x,e->y,3,2,n);
                                                               if(i--)goto L;
                                                            g(p.x,p.y,4,3,r);
                                                                   *(f[h])=0;
                    printf("\033[0;4H%s\033[0;0H    \033[4D%i\n",&f[0][4],s);
                                                          while(t()-l<9);g=0;
                                                                                }
                                                       tcsetattr(0,TCSADRAIN,&o);
                                                                                    }
    
Devi accedere o registrarti per scrivere nel forum
13 risposte