Pagina 1 di 4 1 2 3 ... ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 35
  1. #1

    [Reflection] PrtialFunction & PartialMethod

    La butto qui

    ho trovato interessante questo post di John Resig sulle funzioni parziali in JavaScript.

    Magari vi sembrera' un'assurdita', ma per un problema al lavoro ho pensato di sfruttare la stessa tecnica, peccato che il linguaggio sia PHP.

    A volte PHP e' comunque piu' flessibile di quello che si pensa (almeno di quello che IO penso).
    Ecco il risultato:

    codice:
    class ReflectionPartialFunction extends ReflectionFunction {
    
        protected   $args;
    
        public  function    __construct($name){
            parent::__construct($name);
            $this->args = func_get_args();
            array_splice($this->args, 0, 1);
        }
    
        public  function    invoke($args){
            $args = func_get_args();
            return  $this->invokeArgs($args);
        }
    
        public  function    invokeArgs(array $args){
            return  parent::invokeArgs(array_merge($this->args, $args));
        }
    }
    
    class ReflectionPartialMethod extends ReflectionMethod {
    
        protected   $args;
    
        public  function    __construct($class, $name){
            parent::__construct($class, $name);
            $this->args = func_get_args();
            array_splice($this->args, 0, 2);
        }
    
        public  function    invoke($object, $args){
            $args = func_get_args();
            return  $this->invokeArgs(array_shift($args), $args);
        }
    
        public  function    invokeArgs($object, array $args){
            return  parent::invokeArgs($object, array_merge($this->args, $args));
        }
    }
    Ed ecco un paio di tests facili facili:
    codice:
    function    mul($fixedParam, $num){
        return  $fixedParam * $num;
    }
    
    class Test{
        protected   $num;
        public  function    __construct($num){
            $this->num  = $num;
        }
        public  function    me($fixedParam, $num){
            return  $this->num * $fixedParam * $num;
        }
    }
    
    $partial = new ReflectionPartialFunction('mul', 12);
    echo    $partial->invoke(2);                // 24
    
    $partial = new ReflectionPartialMethod('Test', 'me', 12);
    echo    $partial->invoke(new Test(2), 2);   // 48
    A voi trovarne applicazioni
    Formaldehyde a new Ajax PHP Zero Config Error Debugger

    WebReflection @WebReflection

  2. #2
    andr3a leggere i tuoi post è come al solito istruttivo.

    Peccato che questa volta... non ci abbia capito proprio niente.

    Ora ci riprovo.
    Olio Extravergine d'Oliva Magino
    Prodotti tipici: in vendita olio, pesto ligure e altri prodotti alimentari tradizionali.

  3. #3
    Si, forse sono stato un po' criptico ... facciamo cosi'


    Quante volte chiami una funzione o un metodo all'interno di un loop?
    Quante volte ti capita di passare gli stessi argomenti piu' un paio diversi?

    codice:
    while($row = mysql_fetch_row($query)){
    	$doStuff[] = parseMyRow($db, $oneObject, $regexp, $row[0], $row[1], $row[2]);
    }
    ora puoi fare, se vuoi, cosi'

    codice:
    $parseMyRow = new ReflectionPartialFunction('parseMyRow', $db, $oneObject, $regexp);
    while($row = mysql_fetch_row($query)){
    	$doStuff[] = $parseMyRow->invokeArgs($row);
    
    	// oppure
    	$doStuff[] = $parseMyRow->invoke($row[0], $row[1], $row[2]);
    }
    Meglio ora?

    Le applicazioni sono tante, io sto implementando un parser in cronjob e queste classi si stanno rilevando molto utili.

    Occhio alle performances, se ne siete maniaci, la reflection e' piu' veloce di call_user_func e/o call_user_func_array ma circa 3 volte piu' lenta di una chiamata diretta a funzione
    Formaldehyde a new Ajax PHP Zero Config Error Debugger

    WebReflection @WebReflection

  4. #4
    successone, al solito
    Formaldehyde a new Ajax PHP Zero Config Error Debugger

    WebReflection @WebReflection

  5. #5
    Originariamente inviato da andr3a
    successone, al solito

    tu rintracciami l'australiana e poi cerco di capire quello che dici...

    anche se ti pongo un primo quesito: alla praticità/comodità che impatto hai sulle prestazioni?

  6. #6
    sulle prestazioni ci sono da fare un paio di punti:

    - alcuni progetti enterprise si basano su Rhino (JavaScript server side) che sfrutta invoke Java fino all'estremo, nessuno s'è mai lamentato delle performances, il problema non è li, casomai del db se il progetto è veramente grande

    - sul mio laptop datato e ormai stanco, ma ancora fedele, su 1000 interazioni da 1 a N parametri le performance si sono dimostrate circa 3 volte più lente della chiamata diretta

    All'ultimo punto va aggiunto che:
    - difficile chiamare mille volte una funzione, se non in un loop ... ma se looppate 1000 volte qualcosa la pagina sarà lenta con o senza reflection
    - rispetto la call_user_function e la call_user_function array, la reflection è dalle 2 alle 3 volte più veloce ... ergo è la più vicina alla chiamata diretta
    - con la chiamata diretta ci si scorda l'invoke, l'invokeArgs, la Reflection in generale, e cigliegina nella torta, la possibilità di rendere funzioni e metodi estremamente più portabili/flessibili grazie alla creazione di funzioni e/o metodi parziali, condivisibili tra oggetti, variabili, scripts, altro.

    per l'australiana lasciame lavurà
    Formaldehyde a new Ajax PHP Zero Config Error Debugger

    WebReflection @WebReflection

  7. #7
    si ma non puoi basare l'impatto delle prestazioni sull'esecuzione di una sola pagina anche 10000000 di volte su un computer sul quale sta lavorando un solo utente...vedila anche nell'ottica di un grosso progetto che lavora con diversi utenti concorrenti...

  8. #8
    io la vedo che a volte preferisco un codice più snello ed agile nonchè facile da mantenere, portabile e/o scalabile, che uno 0.0002 sull'esecuzione finale.

    Voglio dire, non è che la devi usare per ogni chiamata a funzione del tuo applicativo ... solo quando serve, lo davo per scontato ... ma ora c'è anche questa possibilità.

    Non capisco questo terrore diffuso dei piaccapari sulla Reflection, voglio dire se avete paura delle performance avete sbagliato linguaggio a priori ma la Reflection grazie a qualcuno esiste ed è capace di fare cose interessanti impensabili prima, fatte da anni con quasi tutti gli altri linguaggi.

    Comunque per dover di cronaca, avevo scritto il tutto per le mie esigenze ma di fatto ho invertito gli argomenti

    nel senso che è più comoda da usare quando ci sono dei default da cambiare in fondo alla callback o al metodo ... ergo ho aggiornato le classi e per ottenere lo stesso risultato del primo esempio dovete usare rinvoke o rinvokeArgs invece di invoke ed invokeArgs
    codice:
    class ReflectionPartialFunction extends ReflectionFunction {
    
    	protected	$args;
    
    	public	function	__construct($name){
    		parent::__construct($name);
    		$this->args	= func_get_args();
    		array_splice($this->args, 0, 1);
    	}
    
    	public	function	invoke($args){
    		$args	= func_get_args();
    		return	$this->invokeArgs($args);
    	}
    
    	public	function	invokeArgs(array $args){
    		return	parent::invokeArgs(array_merge($args, $this->args));
    	}
    
    	public	function	rinvoke($args){
    		$args	= func_get_args();
    		return	$this->rinvokeArgs($args);
    	}
    
    	public	function	rinvokeArgs(array $args){
    		return	parent::invokeArgs(array_merge($this->args, $args));
    	}
    }
    
    class ReflectionPartialMethod extends ReflectionMethod {
    
    	protected	$args;
    
    	public	function	__construct($class, $name){
    		parent::__construct($class, $name);
    		$this->args	= func_get_args();
    		array_splice($this->args, 0, 2);
    	}
    
    	public	function	invoke($object, $args){
    		$args	= func_get_args();
    		return	$this->invokeArgs(array_shift($args), $args);
    	}
    
    	public	function	invokeArgs($object, array $args){
    		return	parent::invokeArgs($object, array_merge($args, $this->args));
    	}
    
    	public	function	rinvoke($object, $args){
    		$args	= func_get_args();
    		return	$this->rinvokeArgs(array_shift($args), $args);
    	}
    
    	public	function	rinvokeArgs($object, array $args){
    		return	parent::invokeArgs($object, array_merge($this->args, $args));
    	}
    }
    P.S. la r sta per metti gli argomenti ricevuti a destra ... di default li mette a sinistra permettendovi di snellire chiamate a metodi con un default che vorreste cambiare ...
    codice:
    function test($a, $b = 1, $c = 0){
        return $a * $b + $c;
    }
    $ref = new ReflectionPartialFunction('test', 2, 1);
    $ref->invoke(3); // 3 * 2 + 1
    $ref->rinvoke(3); // 2 * 1 + 3
    Formaldehyde a new Ajax PHP Zero Config Error Debugger

    WebReflection @WebReflection

  9. #9
    ma tu non eri andato a dormire?


    sei proprio sborò

  10. #10
    ti faccio un altro esempio:

    devi inviare qualche mail ... usi mail perchè ti fa comodo ... o usi una libreria, quella che ti pare.

    Gli headers sono sempre gli stessi, magari anche il body, ma devi usare parametri extra ... hai due opzioni ...

    codice:
    // opzione classica
    mail($to, $subject, $body, $headers, $parameters);
    devi avere sempre tutte le variabili dietro e/o protartele in giro per ogni funzione ... può capitare ... opzione numero due
    codice:
    // partial function
    $mail	= new ReflectionPartialFunction('mail', $subject, $body, $headers, $parameters);
    Hai una sola variabile da portarti in giro, un solo punto dove viene configurata, zero paranoie per i parametri (variabili ridefinite, mancanti, dimenticate, resettate) ... e questo per completare l'operazione dove ti pare:
    codice:
    $mail->invoke($to);
    ora dimmi se non è stra comoda la ReflectionPartial

    ok, mi sbavo da solo, ma come ho detto di implementazioni ce ne sono a bizzeffe e ad esempio tante volte può sostituire oggetti usati a mo di wrappers, ed in questo caso è anche più veloce degli oggetti
    Formaldehyde a new Ajax PHP Zero Config Error Debugger

    WebReflection @WebReflection

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.