জাভা কি কারিঙ সমর্থন করে?


90

আমি ভাবছিলাম জাভাতে এটি টানানোর কোনও উপায় আছে কিনা? আমি মনে করি বন্ধের জন্য স্থানীয় সমর্থন ছাড়া এটি সম্ভব নয়।


4
রেকর্ডের জন্য, জাভা 8 এখন কারিগরী এবং আংশিক অ্যাপ্লিকেশন সমর্থন করে এবং বন্ধ হওয়ার জন্য স্থানীয় সমর্থন রয়েছে। এটি একটি বানোয়াট পুরানো প্রশ্ন।
রবার্ট ফিশার

উত্তর:


146

জাভা 8 (18 ই মার্চ 2014 প্রকাশিত) কারিগরি সমর্থন করে। অনুপস্থিত ফ্যাক্টরের উত্তরে জাভা কোড পোস্ট করা উদাহরণটি আবার লিখে দেওয়া যেতে পারে:

import java.util.function.*;
import static java.lang.System.out;

// Tested with JDK 1.8.0-ea-b75
public class CurryingAndPartialFunctionApplication
{
   public static void main(String[] args)
   {
      IntBinaryOperator simpleAdd = (a, b) -> a + b;
      IntFunction<IntUnaryOperator> curriedAdd = a -> b -> a + b;

      // Demonstrating simple add:
      out.println(simpleAdd.applyAsInt(4, 5));

      // Demonstrating curried add:
      out.println(curriedAdd.apply(4).applyAsInt(5));

      // Curried version lets you perform partial application:
      IntUnaryOperator adder5 = curriedAdd.apply(5);
      out.println(adder5.applyAsInt(4));
      out.println(adder5.applyAsInt(6));
   }
}

... যা বেশ সুন্দর। ব্যক্তিগতভাবে জাভা 8 উপলভ্য থাকায় আমি স্কালা বা ক্লোজারের মতো বিকল্প জেভিএম ভাষা ব্যবহার করার সামান্য কারণ দেখি। তারা অবশ্যই অন্যান্য ভাষার বৈশিষ্ট্য সরবরাহ করে তবে তা রূপান্তর ব্যয় এবং দুর্বল আইডিই / সরঞ্জামিং / লাইব্রেরি সমর্থন, আইএমও প্রমাণ করার পক্ষে যথেষ্ট নয় enough


11
আমি জাভা 8 দিয়ে মুগ্ধ, তবে ক্লোজুর হ'ল কার্যকরী ভাষার বৈশিষ্ট্যগুলির বাইরে একটি বাধ্যতামূলক প্ল্যাটফর্ম। ক্লোজুরে অত্যন্ত দক্ষ, অপরিবর্তনীয় ডেটা স্ট্রাকচার এবং সফটওয়্যার-লেনদেনের মেমরির মতো অত্যাধুনিক সমঝোতা কৌশল সরবরাহ করে।
মাইকেল ইস্টার

4
সমাধানের জন্য ধন্যবাদ, ভাষা খননের জন্য এতটা নয় :) দুর্বল আইডিই সমর্থন একটি সমস্যা, তবে টুলিং / লাইব্রেরিগুলি ক্লোজারের পরে জাভা 8 এ ফিরে আসার পরে, আমি সত্যিই সরঞ্জামগুলি মিডজে হারিয়েছি, কোরের মতো লাইব্রেরি .ync, এবং ম্যাক্রো এবং সহজ কার্যকরী বাক্য গঠন যেমন ভাষার বৈশিষ্ট্য language (def adder5 (partial + 5)) (prn (adder5 4)) (prn adder5 6)
ক্লোজারে কার্লিংয়ের

4
ক্লোজার একটি দুর্দান্ত ভাষা হতে পারে তবে সমস্যাটি হ'ল এটি বেশিরভাগ জাভা বিকাশকারীদের পক্ষে কেবল "প্রচলিত" যা কেবলমাত্র প্রচলিত সি-স্টাইল সিনট্যাক্সের জন্য ব্যবহৃত হয়; ভবিষ্যতে ক্লোজুরে (বা অন্য কোনও বিকল্প জেভিএম ভাষা) তে উল্লেখযোগ্য স্থানান্তর দেখা খুব কঠিন, বিশেষত বিবেচনা করে যে এই জাতীয় বেশ কয়েকটি ভাষা ইতিমধ্যে বহু বছর ধরে বিদ্যমান এবং এটি ঘটেনি (নেট ঘটনাটিতে একই ঘটনা ঘটে, যেখানে এফ # এর মতো ভাষা প্রান্তিক থাকে)।
রোজিরিও

4
আমাকে ডাউনভোট করতে হবে, কারণ এটি সাধারণ কেস দেখায়। স্ট্রিং থেকে নিজের ক্লাস তৈরি করে এমন একটি চেষ্টা করুন যা অন্য কোনও শ্রেণিতে রূপান্তরিত করে কোডের পরিমাণের তুলনা করুন
এম 4ks

11
@ এম 4ks প্রশ্নটি কেবল জাভা কারী করা সমর্থন করে কিনা, অন্যান্য ভাষার তুলনায় কোডের পরিমাণ সম্পর্কে নয়।
Rogério

67

জাভাতে কারিং এবং আংশিক প্রয়োগ একেবারে সম্ভব, তবে প্রয়োজনীয় পরিমাণের কোড আপনাকে সম্ভবত বন্ধ করে দেবে।


জাভাতে কারীং এবং আংশিক প্রয়োগ প্রদর্শনের জন্য কিছু কোড:

interface Function1<A, B> {
  public B apply(final A a);
}

interface Function2<A, B, C> {
  public C apply(final A a, final B b);
}

class Main {
  public static Function2<Integer, Integer, Integer> simpleAdd = 
    new Function2<Integer, Integer, Integer>() {
      public Integer apply(final Integer a, final Integer b) {
        return a + b;
      }
    };  

  public static Function1<Integer, Function1<Integer, Integer>> curriedAdd = 
    new Function1<Integer, Function1<Integer, Integer>>() {
      public Function1<Integer, Integer> apply(final Integer a) {
        return new Function1<Integer, Integer>() {
          public Integer apply(final Integer b) {
            return a + b;
          }
        };
      }
    };

  public static void main(String[] args) {
    // Demonstrating simple `add`
    System.out.println(simpleAdd.apply(4, 5));

    // Demonstrating curried `add`
    System.out.println(curriedAdd.apply(4).apply(5));

    // Curried version lets you perform partial application 
    // as demonstrated below.
    Function1<Integer, Integer> adder5 = curriedAdd.apply(5);
    System.out.println(adder5.apply(4));
    System.out.println(adder5.apply(6));
  }
}

FWIW এখানে জাভা কোডের উপরের হাস্কেল সমতুল্য:

simpleAdd :: (Int, Int) -> Int
simpleAdd (a, b) = a + b

curriedAdd :: Int -> Int -> Int
curriedAdd a b = a + b

main = do
  -- Demonstrating simpleAdd
  print $ simpleAdd (5, 4)

  -- Demonstrating curriedAdd
  print $ curriedAdd 5 4

  -- Demostrating partial application
  let adder5 = curriedAdd 5 in do
    print $ adder5 6
    print $ adder5 9

@ ওপ: দু'টিই এক্সিকিউটেবল কোড স্নিপেটস এবং আপনি এডিটোন.কম এ চেষ্টা করে দেখতে পারেন।
মিসিংফ্যাক্টর

16
এই উত্তরটি জাভা 8 মুক্তির পর থেকে পুরানো হয়েছে 8. আরও সংক্ষিপ্ত উপায়ে রোগারিওর উত্তর দেখুন।
ম্যাথিয়াস ব্রাউন

15

জাভা ৮ এর সাথে কারি করার জন্য প্রচুর বিকল্প রয়েছে Fun ফাংশন টাইপ জাভাসলং এবং জুও λ উভয়ই বক্সের বাইরে কারিঙের প্রস্তাব দিচ্ছে (আমার মনে হয় এটি জেডিকে একটি তদারকি ছিল), এবং সাইক্লোপস ফাংশন মডিউলে জেডিকে ফাংশনগুলি কারি করার জন্য স্থির পদ্ধতিগুলির একটি সেট রয়েছে has এবং পদ্ধতি রেফারেন্স। যেমন

  Curry.curry4(this::four).apply(3).apply(2).apply("three").apply("4");

  public String four(Integer a,Integer b,String name,String postfix){
    return name + (a*b) + postfix;
 }

'কারিঙ' গ্রাহকদের জন্যও উপলব্ধ। উদাহরণস্বরূপ 3 টি প্যারামের সাহায্যে কোনও পদ্ধতি ফিরে আসার জন্য এবং ইতিমধ্যে প্রয়োগ করা 2 জনের মধ্যে আমরা এর অনুরূপ কিছু করি

 return CurryConsumer.curryC3(this::methodForSideEffects).apply(2).apply(2);

জাভাদোক


আইএমও, সোর্স কোডে curryingএটি সত্যই বলা হয়েছিল Curry.curryn
লেবেকা

13

সম্পাদনা : ২০১৪ এবং জাভা ৮-এর হিসাবে, জাভাতে কার্যকরী প্রোগ্রামিং এখন কেবল সম্ভব নয়, কুৎসিতও নয় (আমি সুন্দর বলতে সাহস করি)। উদাহরণস্বরূপ রোজারিওর উত্তর দেখুন

পুরানো উত্তর:

জাভা সেরা পছন্দ নয়, যদি আপনি কার্যকরী প্রোগ্রামিং কৌশল ব্যবহার করতে যাচ্ছেন। অনুপস্থিতি যেমন লিখেছেন, আপনি যা চান তা অর্জন করতে আপনাকে বেশ বড় পরিমাণে কোড লিখতে হবে।

অন্যদিকে, আপনি জেভিএম-তে জাভাতে সীমাবদ্ধ নন - আপনি স্কালা বা ক্লোজার ব্যবহার করতে পারেন যা কার্যকরী ভাষা (স্কালা আসলে, উভয় কার্যকর এবং ওও)।


8

কারি করার জন্য একটি ফাংশন ফেরত আসা দরকার । জাভা দিয়ে এটি সম্ভব নয় (কোনও ফাংশন পয়েন্টার নেই) তবে আমরা কোনও ফাংশন পদ্ধতি সম্বলিত কোনও ধরণের সংজ্ঞা এবং ফিরিয়ে দিতে পারি:

public interface Function<X,Z> {  // intention: f(X) -> Z
   public Z f(X x);
}

এখন একটি সহজ বিভাগ কারি করা যাক । আমাদের একটি ডিভাইডার দরকার :

// f(X) -> Z
public class Divider implements Function<Double, Double> {
  private double divisor;
  public Divider(double divisor) {this.divisor = divisor;}

  @Override
  public Double f(Double x) {
    return x/divisor;
  }
}

এবং একটি ডিভাইড ফাংশন :

// f(x) -> g
public class DivideFunction implements Function<Double, Function<Double, Double>> {
  @Override
  public function<Double, Double> f(Double x) {
    return new Divider(x);
  }

এখন আমরা একটি তরকারি বিভাগ করতে পারি:

DivideFunction divide = new DivideFunction();
double result = divide.f(2.).f(1.);  // calculates f(1,2) = 0.5

4
এখন যেহেতু আমি আমার উদাহরণটি (স্ক্র্যাচ থেকে উন্নত) শেষ করেছি, এটি প্রমাণিত হয়েছে যে অনুপস্থিত কোডগুলির উত্তরের একমাত্র পার্থক্য হ'ল আমি বেনাম ক্লাস ব্যবহার করি না;)
আন্দ্রেস ডলক

4
@ মিসিংফাক্টর - মিয়া কুলপা;)
আন্দ্রেয়াস ডল্ক

5

ওয়েল, স্কেলা , ক্লোজার বা হাস্কেল (বা অন্য কোনও কার্যকরী প্রোগ্রামিং ল্যাঙ্গুয়েজ ...) অবশ্যই কারিরিং এবং অন্যান্য কার্যকরী কৌশলগুলির জন্য ব্যবহৃত ভাষা

এমনটি বলা সম্ভবত জাওয়ারের সাথে তর্ক করা সম্ভব মাত্রাতিরিক্ত পরিমাণে বয়লারপ্লেট ছাড়াই প্রত্যাশা করা যায় (ভাল, প্রকারের বিষয়ে স্পষ্ট করে বলা যদিও অনেক ব্যথা করে - কেবল curriedউদাহরণটি দেখুন ;-))।

পরীক্ষাগুলি দুটোকেই প্রদর্শন করে, এর মধ্যে একটি কারিFunction3 করে Function1 => Function1 => Function1:

@Test
public void shouldCurryFunction() throws Exception {
  // given
  Function3<Integer, Integer, Integer, Integer> func = (a, b, c) -> a + b + c;

  // when
  Function<Integer, Function<Integer, Function<Integer, Integer>>> cur = curried(func);

  // then
  Function<Integer, Function<Integer, Integer>> step1 = cur.apply(1);
  Function<Integer, Integer> step2 = step1.apply(2);
  Integer result = step2.apply(3);

  assertThat(result).isEqualTo(6);
}

পাশাপাশি আংশিক প্রয়োগ , যদিও এটি উদাহরণস্বরূপ এটি টাইপসেফ নয়:

@Test
public void shouldCurryOneArgument() throws Exception {
  // given
  Function3<Integer, Integer, Integer, Integer> adding = (a, b, c) -> a + b + c;

  // when
  Function2<Integer, Integer, Integer> curried = applyPartial(adding, _, _, put(1));

  // then
  Integer got = curried.apply(0, 0);
  assertThat(got).isEqualTo(1);
}

এটি একটি ধারণার প্রুফ থেকে নেওয়া হয়েছে আমি আগামীকাল এক ঘন্টার মধ্যে জাভাওনের আগে মজাদার জন্য বাস্তবায়ন করেছি "কারণ আমি বিরক্ত হয়েছি" ;-) কোডটি এখানে উপলভ্য: https://github.com/ktoso/jcurry

সাধারণ ধারণাটি ফাংশনএন => ফাংশনএম-তে তুলনা করা যায় তুলনামূলকভাবে সহজেই, যদিও "রিয়েল টাইপসফটি" পার্টিয়া অ্যাপ্লিকেশন উদাহরণের জন্য একটি সমস্যা হিসাবে রয়ে গেছে এবং কারিগরীকরণের উদাহরণটিতে জ্যাকুরিতে নরকের প্রচুর পরিমাণে বয়লারপ্ল্যাটি কোড লাগবে , তবে এটি কার্যক্ষম

সব মিলিয়ে এটি করণীয়, তবু স্কেলে এটি বাক্সের বাইরে ;-)


5

এক জাভা 7 MethodHandles সঙ্গে সংবাহন অনুকরণ করতে পারেন: http://www.tutorials.de/threads/java-7-currying-mit-methodhandles.392397/

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;

public class MethodHandleCurryingExample {
    public static void main(String[] args) throws Throwable {
        MethodHandles.Lookup lookup = MethodHandles.lookup();
        MethodHandle sum = lookup.findStatic(Integer.class, "sum", MethodType.methodType(int.class, new Class[]{int.class, int.class}));
        //Currying
        MethodHandle plus1 = MethodHandles.insertArguments(sum,0,1);
        int result = (int) plus1.invokeExact(2);
        System.out.println(result); // Output: 3
    }
}

5

হ্যাঁ, নিজের জন্য কোড উদাহরণটি দেখুন:

import java.util.function.Function;

public class Currying {

    private static Function<Integer, Function<Integer,Integer>> curriedAdd = a -> b -> a+b ;

    public static void main(String[] args) {

        //see partial application of parameters
        Function<Integer,Integer> curried = curriedAdd.apply(5);
        //This partial applied function can be later used as
        System.out.println("ans of curried add by partial application: "+ curried.apply(6));
        // ans is 11

        //JS example of curriedAdd(1)(3)
        System.out.println("ans of curried add: "+ curriedAdd.apply(1).apply(3));
        // ans is 4

    }

}

এই সঙ্গে সহজ উদাহরণ curriedAdd একটি curried ফাংশন যা অন্য ফাংশনটি হচ্ছে, এবং এই জন্য ব্যবহার করা যেতে পরামিতি আংশিক আবেদন সঞ্চিত যেমন curried নিজেই একটি ফাংশন পারে। এটি এখন পরে পুরোপুরি প্রয়োগ করা হয় যখন আমরা এটি স্ক্রিনে মুদ্রণ করি।

তদতিরিক্ত, পরে আপনি দেখতে পাবেন যেভাবে আপনি এটি জেএস স্টাইলের মতো ব্যবহার করতে পারেন

curriedAdd.apply(1).apply(2) //in Java
//is equivalent to 
curriedAdd(1)(2) // in JS

4

আরও একটি জাভা 8 সম্ভাব্যতা গ্রহণ:

BiFunction<Integer, Integer, Integer> add = (x, y) -> x + y;

Function<Integer, Integer> increment = y -> add.apply(1, y);
assert increment.apply(5) == 6;

আপনি এইগুলির মতো ইউটিলিটি পদ্ধতিগুলিও সংজ্ঞায়িত করতে পারেন:

static <A1, A2, R> Function<A2, R> curry(BiFunction<A1, A2, R> f, A1 a1) {
    return a2 -> f.apply(a1, a2);
}

যা আপনাকে বিতর্কিতভাবে আরও বেশি পঠনযোগ্য সিনট্যাক্স দেয়:

Function<Integer, Integer> increment = curry(add, 1);
assert increment.apply(5) == 6;

3

জাভাতে কোনও পদ্ধতিতে কারি তৈরি করা সর্বদা সম্ভব, তবে এটি স্ট্যান্ডার্ড উপায়ে সমর্থন করে না। এটি অর্জনের চেষ্টা জটিল এবং কোডটি বেশ অপঠনযোগ্য করে তোলে। জাভা এর জন্য উপযুক্ত ভাষা নয়।


3

জাভা 6+ এর জন্য আরেকটি পছন্দ এখানে

abstract class CurFun<Out> {

    private Out result;
    private boolean ready = false;

    public boolean isReady() {
        return ready;
    }

    public Out getResult() {
        return result;
    }

    protected void setResult(Out result) {
        if (isReady()) {
            return;
        }

        ready = true;
        this.result = result;
    }

    protected CurFun<Out> getReadyCurFun() {
        final Out finalResult = getResult();
        return new CurFun<Out>() {
            @Override
            public boolean isReady() {
                return true;
            }
            @Override
            protected CurFun<Out> apply(Object value) {
                return getReadyCurFun();
            }
            @Override
            public Out getResult() {
                return finalResult;
            }
        };
    }

    protected abstract CurFun<Out> apply(final Object value);
}

তাহলে আপনি এইভাবে কারিটিং অর্জন করতে পারেন

CurFun<String> curFun = new CurFun<String>() {
    @Override
    protected CurFun<String> apply(final Object value1) {
        return new CurFun<String>() {
            @Override
            protected CurFun<String> apply(final Object value2) {
                return new CurFun<String>() {
                    @Override
                    protected CurFun<String> apply(Object value3) {
                        setResult(String.format("%s%s%s", value1, value2, value3));
//                        return null;
                        return getReadyCurFun();
                    }
                };
            }
        };
    }
};

CurFun<String> recur = curFun.apply("1");
CurFun<String> next = recur;
int i = 2;
while(next != null && (! next.isReady())) {
    recur = next;
    next = recur.apply(""+i);
    i++;
}

// The result would be "123"
String result = recur.getResult();

2

আপনি জাভাতে কারিইং করতে পারেন, এটি কুরুচিপূর্ণ (কারণ এটি সমর্থিত নয়) জাভাতে প্লেইন লুপ এবং সরল এক্সপ্রেশন ব্যবহার করা কি সহজ এবং দ্রুত। আপনি কোথায় কারিঙ ব্যবহার করবেন এমন একটি উদাহরণ পোস্ট করলে আমরা একই বিকল্পের বিকল্পগুলির পরামর্শ দিতে পারি।


4
কার্পিংয়ের সাথে লুপগুলি কী করতে পারে ?! আপনি এটি সম্পর্কে কোনও প্রশ্নের উত্তর দেওয়ার আগে শব্দটির সন্ধান করুন।
মিসিংফ্যাক্টর

@ মিসিং ফ্যাক্টর, ত্রিযুক্ত ফাংশনগুলি সাধারণত সংগ্রহগুলিতে প্রয়োগ করা হয়। উদাহরণস্বরূপ list2 = list.apply (curriedFunction) যেখানে curriedFunction 2 * ?জাভাতে আপনি এটি একটি লুপ দিয়ে করতে পারেন।
পিটার লরে

@ পিটার: এটি আংশিক প্রয়োগ, কারি হচ্ছে না ing এবং উভয়ই সংগ্রহ কার্যক্রমের জন্য সুনির্দিষ্ট নয়।
মিসিংফ্যাক্টর

@ মিসিংফ্যাক্টর, আমার বক্তব্যটি; নির্দিষ্ট বৈশিষ্ট্যটিতে ঝাঁপিয়ে পড়ার জন্য নয় তবে একটি পদক্ষেপ ফিরে নিয়ে আরও বৃহত্তর সমস্যাটি দেখুন এবং এর সহজ সমাধান হওয়ার খুব সম্ভবত সম্ভাবনা রয়েছে।
পিটার লরি

@ পিটার: আপনি যদি প্রশ্নটির মূল বিষয়টি প্রশ্ন করতে চান তবে আপনার মন্তব্যটি উত্তর হিসাবে নয়, মন্তব্য হিসাবে পোস্ট করা উচিত। (আইএমএইচও)
অনুপস্থিত ফ্যাক্টর

2

এটি জাভাতে কারিগরীকরণ এবং আংশিক প্রয়োগের জন্য একটি গ্রন্থাগার:

https://github.com/Ahmed-Adel-Ismail/J-Cryry

এটি টিউপলস এবং ম্যাপকে কাঠামোগত সমর্থন করে method পদ্ধতি প্যারামিটারগুলিতে প্রবেশ করুন যেমন উদাহরণস্বরূপ একটি মানচিত্র পাস করা 2 এনট্রি এমন একটি পদ্ধতিতে প্রবেশ করুন যা 2 পরামিতি নেয়, সুতরাং এন্ট্রি.জেটকি () প্রথম প্যারামিটারে যাবে এবং এন্ট্রি.জেটভ্যালু () দ্বিতীয় পরামিতি যেতে হবে

README ফাইলে আরও বিশদ


2

জাভা 8-তে কারিরিং ব্যবহার করার সুবিধাটি হ'ল এটি আপনাকে উচ্চ অর্ডার ফাংশনগুলি সংজ্ঞায়িত করতে দেয় এবং তারপরে একটি শৃঙ্খলিত, মার্জিত উপায়ে একটি প্রথম অর্ডার ফাংশন এবং ফাংশন আর্গুমেন্টগুলি পাস করতে দেয়।

এখানে ক্যালকুলাসের জন্য উদাহরণ, ডেরাইভেটিভ ফাংশন।

  1. যেমন ব্যুৎপন্ন ফাংশন পড়তা সংজ্ঞায়িত দেয় (চ (এক্স + H) -f (x) এর) / ঘঃ । এটি হাই অর্ডার ফাংশন হবে
  2. আসুন ক্যালকুলেট 2 টি পৃথক ফাংশন, ডেরিভেটিভ 1 / এক্স , এবং মান গসিয়ান বন্টন

ঘ

    package math;

    import static java.lang.Math.*;
    import java.util.Optional;
    import java.util.function.*;

    public class UnivarDerivative
    {
      interface Approximation extends Function<Function<Double,Double>, 
      Function<Double,UnaryOperator<Double>>> {}
      public static void main(String[] args)
      {
        Approximation derivative = f->h->x->(f.apply(x+h)-f.apply(x))/h;
        double h=0.00001f;
        Optional<Double> d1=Optional.of(derivative.apply(x->1/x).apply(h).apply(1.0)); 
        Optional<Double> d2=Optional.of(
        derivative.apply(x->(1/sqrt(2*PI))*exp(-0.5*pow(x,2))).apply(h).apply(-0.00001));
        d1.ifPresent(System.out::println); //prints -0.9999900000988401
        d2.ifPresent(System.out::println); //prints 1.994710003159016E-6
      }
    }

0

হ্যাঁ, আমি @ Jérôme এর সাথে একমত, জাভা 8-এ কার্লিং কোনও স্ক্যান্ডা বা অন্যান্য কার্যকরী প্রোগ্রামিং ভাষার মতো স্ট্যান্ডার্ড পদ্ধতিতে সমর্থিত নয়।

public final class Currying {
  private static final Function<String, Consumer<String>> MAILER = (String ipAddress) -> (String message) -> {
    System.out.println(message + ":" + ipAddress );
  };
  //Currying
  private static final Consumer<String> LOCAL_MAILER =  MAILER.apply("127.0.0.1");

  public static void main(String[] args) {
      MAILER.apply("127.1.1.2").accept("Hello !!!!");
      LOCAL_MAILER.accept("Hello");
  }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.