Tablica funkcji o różnych argumentach w argumencie funkcji

0

Czy da się zrobić tak:

void ff(void[] f(?))
{
for(void f(?))
{
f();
}
}
ff(x(10,10).y(10,20),o("cjscnjsncj"));
1

Zamiast wklejać kawałek bezsensownego kodu następnym razym opowiedz co chcesz zrobić.

Podejrzewam, że chcesz przekazywać funkcję jako parametr. Od Javy 8 masz lambdy, więc możesz ich użyć, ale najpierw musisz o nich poczytać, żeby załapać co i jak. Będziesz musiał sobie stworzyć interface (@FunctionalInterface) dla twojej metody przyjmującej wiele argumentów i zwracającej voida, będzie to wyglądać mniej więcej tak:

@FunctionalInterface
public interface MyLambda {
  public void apply(Object... params);
}

(tylko to nazwij jakoś sensownie dla twojego zastosowania)
I wtedy będziesz mógł używać tego jako typ twojej lambdy.

Jeżeli chodzi o metody przyjmujące wiele parametrów to są to tzw. Varags. Chociaż, jak wspomniał @niezdecydowany, pewnie lepiej będzie użyć zamiast tego jakiejś kolekcji.

Jeżeli chodzi o parametry tych metod to musiałbyś je przekazywać osobno, albo w jakiejś tupli, albo mapie. Może ktoś inny ma jakiś lepszy pomysł.

1
Wizzie napisał(a):

Jeżeli chodzi o parametry tych metod to musiałbyś je przekazywać osobno, albo w jakiejś tupli, albo mapie. Może ktoś inny ma jakiś lepszy pomysł.

Zależy co chce zrobić, ja bym trzymał te "funkcje" jak Function<T> w jakies collekcji i potem je aplikował. function.stream().forEach(...)

3

@Wizzie, nie do końca o to chodzi o czym piszesz. W javie będzie to dość paskudnie wyglądać, ale da się:

public class Test {

	public static void main(String[] args) throws ParserConfigurationException {
		// tu mamy listę funkcji
		Function<Object, String> f1 = o -> o.toString();
		Function<Integer, Long> f2 = o -> (long) (o * 2);

		// opcjonalnie argumenty "z zewnątrz"
		Object name = "Ala";
		ff(() -> f1.apply(name), () -> f2.apply(1));
	}

	static void ff(Supplier<?>... fs) {
		Arrays.stream(fs).forEach(f -> System.out.println(f.get()));
	}
}

I teraz jak to działa

Najpierw mamy sobie listę funkcji, które będziemy chcieli wywołać. Następnie przekazujemy je do metody ff, która jako argumenty przyjmuje Supplier, który pod spodem aplikuje funkcję. Argumenty do funkcji możemy przekazać "z zewnątrz" jak w przypadku f1 jak i na poziomie suppliera jak w f2. Funkcja ff wywołuje get z suppliera by uzyskać wynik działania funkcji. Funkcja jest wywoływana dopiero w tym momencie.

Dlaczego tak? Ponieważ nie możemy w ff bezpośrednio dostać się do argumentów dla funkcji f1 i f2. Musimy zatem wprowadzić pewnego pośrednika, który opakuje nam wywołanie funkcji i będzie miał dostęp do jej argumentów.

... a ten kod i tak jest paskudny.

0
  1. Pierwszy raz widzę w kodzie strzałkę !
  2. Co to dokładnie jest Suppiler ?
  3. I co to Arrays.stream(fs).forEach(f -> System.out.println(f.get()));
4
Xix napisał(a):
  1. Pierwszy raz widzę w kodzie strzałkę !
  2. Co to dokładnie jest Suppiler ?
  3. I co to Arrays.stream(fs).forEach(f -> System.out.println(f.get()));

@Koziołek jest indianinem dlatego używa strzałek, a historię jego plemienia możesz poznać tutaj:

http://tutorials.jenkov.com/java-collections/streams.html

3

@Xix strzałka to element notacji wykorzystywany przy lambdach (java 8). Supplier to interfejs generyczny posiadający jedną metodę get, która powinna zwracać obiekt danego typu. Zapis z Arrays to taka bardziej hipsterska pętla. Ma jednak tą przewagę nad zwykłą pętlą, że pozwala na silniejszą separację logiki i danych oraz na to, że narzędzia typu sonar nie bluzgają jak to zagłębisz (pętla w pętli itp.).

0

OK Jak się wcoraj zastanawiałem to połowę wymyśliłem ale co dokładnie zwraca Suppiller ?
I czy da się zrobić tak:

void ff(Function<int,void>[] f)
{
 for(Function<int,void> fu : f)
 {
  f(1);
 }
}
0

Dalej nie łapie Suppilera :)
Zwraca mi typ ale czego ? Funkcji ? Jej Argumenty ? To jak ją wywołać ?

1
Xix napisał(a):

Dalej nie łapie Suppilera :)

ty nie masz problemu z suppilerem tylko javą, proponuje zacząć od podstaw.

Ale mam dobry dzień, więc nie będę cię obrażał (a powinienem)

Suppiler<T> to inteface generyyczny


        Supplier<Integer> dajMiIntegerRysiek = () -> new Integer(3);
        Integer asd = dajMiIntegerRysiek.get();
        
        Supplier<Integer> asdasd = new Supplier<Integer>() {
            @Override
            public Integer get() {
                return new Integer(3);
            }
        };
        
        Integer asd2 = asdasd.get(); 

Za T możesz podstawić cokolwiek, więc get() zwróci to co podstawiłeś za T.
Suppiler to po prostu interface, jeżeli nie rozumiesz to wyrzuć komputer przez okno i chwyć łopatę.

0

Rozumiem co to interface ale co dokładnie zwraca get ?
No bo skoro chdziło o wywołanie funkcji podanej w argumentach to dlaczego akurat Suppiler ?
Czyli to zwraca ty, OK rozumiem to jaki to typ zwraca i o co w ogóle chodzi w tym:

 static void ff(Supplier<?>... fs) {
        Arrays.stream(fs).forEach(f -> System.out.println(f.get()));
    }

To co mi to ma zwrócić ? Function<Object, String> ?
I co z tym: () -> f1.apply(name)

0

Dobra wiem już chyba po co suppiler ale jak ich użyć ?! Przecież mam tylko jej typ ( no tak to przynajmniej rozumiem )!

1
Xix napisał(a):

Dobra wiem już chyba po co suppiler ale jak ich użyć ?! Przecież mam tylko jej typ ( no tak to przynajmniej rozumiem )!

Wydaje mi się że nie jesteś trollem, po prostu jesteś trochę wolniejszy, także postaram ci się to przybliżyć:

class PrzykladowaImplementacjaSuppilera implements Supplier<Integer> {
    @Override
    public Integer get() {
        return new Integer(666);
    }
}

//gdzies dalej

PrzykladowaImplementacjaSuppilera test = new PrzykladowaImplementacjaSuppilera();
test.get(); //da ci 666

Zrobienie lambdy jest teoretycznie(bo praktycznie jako bytecode realizowane jest inaczej)
robi taką właśnie instancje, czyli to na górze, tylko bez nazwy

Supplier<Integer> labdaTest = () -> Integer(666);
//i teraz
labdaTest.get() // też da ci 666

albo w ramach ciekawostki

Supplier<Integer> labdaTest = () -> { return Integer(666); }

tutaj przy użyciu {} musi pojawić się return - żeby rozróżnić statement i expression

Jeżeli będzie ci prościej możesz myśleś że to

() -> Integer(666);

, czyli ciało lambdy jest jakby ciałem metody get()


bo przecież robie to samo:
```java
    //z klasy
    public Integer get() {
        return new Integer(666);
    }
   
   //z lambdy
   () -> Integer(666);

Z tego też wynika () -> dlatego że get() nie przyjmuje parametrów.

0

To rozumiem ale jak wywołać jakąś funkcję ?

2
Xix napisał(a):

To rozumiem ale jak wywołać jakąś funkcję ?

urwa, bo trace cierpliwość...

A CO TO ROBI ?

Supplier<Integer> labdaTest = () -> Integer(666);
//i teraz
labdaTest.get() // też da ci 666

zresztą w javie nie ma funkcji , to zawsze jest METODA W OBIEKCIE

0

Dobra no ale czy to z void też zadziała ?
No bo to co mi dałeś zawiera gotową wartość a ja bym chciał wywołać funkcję z własnymi parametrami.

0

Dobra co do void mnie olśniło (interfejsy) ale co do tych funkcji to nie wiem

0

Ostatecznie wymyśliłem by podawać w String typ funkcji a potem parametry najlepiej w jakimś objekcie. Jak coś to nadal czekam na odp. :)

0

Widzę, że zamieszałem więc tłumaczę co i jak.

W swoim problemie chcesz przekazywać do pewnej funkcji ff kolekcję funkcji fx(x == lista dowolnych argumentów) gdzie każdą z funkcji wywołasz w pętli w ramach ff.

W tym celu zdefiniujemy funkcję ff:

static void ff(Supplier<?>... fs) {
    Arrays.stream(fs).forEach(f -> System.out.println(f.get()));
}

Co jest równoważne z zapisem z pętlą, ale zwięźlej. Argumentem funkcji ff jest tablica Supplier-ów, które mogą dostarczać dowolne obiekty - znak ? w generyku.

Funkcję ff wywołujesz przekazując jej tablicę, zapis z ..., obiektów Supplier w następujący sposób:

ff(() -> f1.apply(name), () -> f2.apply(1));

tak skonstruowane suppliery należy czytać w następujący sposób w momencie pobrania wartości zwróć wynik wywołania funkcji fx.

Inaczej mówiąc w funkcji ff przechodzisz pętlą po pewnych abstrakcyjnych bytach, zwanych Supplier, które dostarczają wyników wywołania pewnych funkcji.

0

Mi chodzi o to by ff po prostu wywoływało te funkcje a nie brało od nich tylko wynik. Ale załużmy że mamy tylko funkcje typu String i jej argumenty String i Int, to jak ją wywołać dając jej konkretne argumenty. No bo po prostu teraz mam chyba tylko jej wartość a ana się nie wywołuje tak ?
No a jak by było String xxx(String) to jak wywołać ? Function<String,String> w parametrach do ff i co ? Zresztą nadal nie rozumiem jak wywołać tą funkcję no bo skoro suppiller zwraca tylko wynik... Ale może Suppiler wywołuje tą funkcję i mi oddajeje wynik ale nie teraz przy podawaniu argumentów tylko na końcu ? Tyle możliwości :)

0

To wywoła te funkcje.

Suuplier.get, wywoła Function.apply bo skąd inaczej ma mieć wynik takiej funkcji?

1 użytkowników online, w tym zalogowanych: 0, gości: 1