Friday, March 21, 2014

Java: Անանուն ֆունկցիաները Java 8 լեզվում

Պատահաբար հանդիպեցի Java 8 լեզվում անանուն ֆունկցիաների իրականացման մասին Oracle ֆիրմայի մի հաղորդագրության։ Այդտեղ օրինակներ էր բերված, թե ինչ նպատակների համար են նախատեսված Java 8 լեզվի լյամբդա ֆունկցիաները, և թե ինչպես կարելի է օգտագործել դրանք։
     Իմ բլոգի «Բարձր կարգի ֆունկցիաներ և անանուն ֆունկցիաներ» գրառման մեջ ես ֆունկցիայի ինտեգրալի թվային հաշվման օրինակով համեմատել էի Common Lisp և C++11 լեզվի անանուն ֆունկցիաները։ Այս գրառման մեջ ուզում եմ նույն այդ օրինակը ցույց տալ Java 8 լեզվի անանուն ֆունկցիաների օգտագործմամբ։

Մաթեմատիկական ֆունկցիան, որ կարելի է ինտեգրել, իրականացնում է MathFunc ինտերֆեյսը։ Այն սահմանված է MathFunc.java ֆայլում։
package integral;

public interface MathFunc {
 public double apply( double x );
}
Թվային ինտեգրման մեթոդն իրականացնում է Method ինտերֆեյսը, որը սահմանված է Method.java ֆայլում՝ հետևյալ կերպ։
package integral;

public interface Method {
 public double apply( MathFunc f, double a, double b );
}
Սահմանեմ Integral դասը և սահմանեմ այդ դասի evaluate մեթոդը, որն արգումենտում սպասում է ինտեգրման մեթոդը, ինտեգրվող ֆունկցիան, ինտեգրման միջակայքը և միջակայքի՝ հատվածների տրոհման գործակիցը։ Հաշվելու եղանակը պարզագույնն է. meth օբյեկտի apply մեթոդին են փոխանցվում ինտեգրվող ֆունկցիան և այն փոքր հատվածը, որի վրա նշված թվային մեթոդով հաշվվում է ինտեգրալը։
package integral;

public class Integral {
    public static double evaluate(Method meth, MathFunc func, 
                                double left, double right, double epsilon)
    {
        double result = 0.0;
        for( double x = left; x < right; x += epsilon )
            result += meth.apply(func, x, x + epsilon);
        return result;
    }
}
Որպեսզի, օրինակ, Integral դասի evaluate ստատիկ մեթոդի օգնությամբ հաշվեմ \(f(x)=3x^2-2x+1\) ֆունկցիայի ինտեգրալը, պետք է նախ՝ \(f(x)\) ֆունկցիան սահմանեմ որպես MathFunc ինտերֆեյս իրականացնող օբյեկտ, իսկ ինտեգրման մեթոդը, օրինակ սեղանների կանոնը, սահմանեմ որպես Method ինտերֆեյսն իրականացնող օբյեկտ։
     Սահմանեմ Calc դասը՝ main մուտքի կետով։
package integral;

public class Calc {
    /**/ 
    public static void main( String[] args )
    {
        // ինտեգրման մեթոդ
        Method Simple = new Method() {
            @Override
            public double apply( MathFunc f, double a, double b )
            { return (b - a) * f.apply((b + a) / 2); }
        };

        // ինտեգրվող ֆունկցիա 
        MathFunc Sin = new MathFunc() {
            @Override
            public double apply( double x )
            { return 3*x*x - 2*x + 1; }
        };

        // ինտեգրալի հաշվումն ու արտածումը
        double r0 = Integral.evaluate(Simple, Sin, 0, 1, .0001);
        System.out.println( r0 );
    }
}
Բայց սա հնացած եղանակն է։ Անանուն ֆունկցիաների օգտագործմամբ գրվում է շատ ավելի համառոտ, գեղեցիկ ու հասկանալի կոդ։ Ստորև բերված main ֆունկցիայում ինտեգրման մեթոդն ու ինտեգրվող ֆունկցիան evaluate ֆունկցիային փոխանցված են որպես անանուն ֆունկցիաներ։
package integral;

public class Calc {
    /**/ 
    public static void main( String[] args )
    {
        double r1 = Integral.evaluate( (f,a,b)->(b-a)*f.apply((b+a)/2), 
                                       (x)-> 3*x*x - 2*x + 1, 0, 1, .0001 );
        System.out.println( r1 );
    }
}
* * *
Java 8 լեզվում անանուն (լյամբդա) ֆունկցիան սահմանվում է հետևյալ քերականությամբ․

(արգումենտների ցուցակ) -> ֆունկցիայի մարմին

Օրինակ, թվային մոտավոր ինտեգրման սեղանների կանոնի բանաձևը վերը բերված օրինակում սահմանված է ահա այսպես․
(f, a, b) -> (b - a) * f.apply((b + a) / 2)
Կարելի է անանուն ֆունկցիան կապել որևէ փոփոխականի հետ, օրինակ, թվային մոտավոր ինտեգրման Սիմպսոնի կանոնի բանաձևը սահմանված է որպես անանուն ֆունկցիա և վերագրված է simpson փոփոխականին․
public static Method simpson = 
   (f, a, b) -> ((b - a) / 6) * (f.apply(a) + f.apply(b) + 4*f.apply((a+b)/2));
Ինտեգրալը հաշվելիս կարելի է evaluate ֆունկցիային փոխանցել simpson փոփոխականը․
double r2 = Integral.evaluate( simpson, (x)-> 3*x*x - 2*x + 1, 0, 1, .0001 );

Առայժմ այսքանը։ Ես դեռ նոր եմ ուսումնասիրում Java 8-ի անանուն ֆունկցիաները։ Հետքգայում միգուցե նորից անդրադառնամ այս թեմային ու ներկայացնեմ ավելի հետաքրքիր օրինակներ։

No comments:

Post a Comment