Czy da się zrobić tak:
void ff(void[] f(?))
{
for(void f(?))
{
f();
}
}
ff(x(10,10).y(10,20),o("cjscnjsncj"));
Czy da się zrobić tak:
void ff(void[] f(?))
{
for(void f(?))
{
f();
}
}
ff(x(10,10).y(10,20),o("cjscnjsncj"));
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ł.
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(...)
@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.
Arrays.stream(fs).forEach(f -> System.out.println(f.get()));
Xix napisał(a):
- Pierwszy raz widzę w kodzie strzałkę !
- Co to dokładnie jest Suppiler ?
- 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:
@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.).
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);
}
}
Dalej nie łapie Suppilera :)
Zwraca mi typ ale czego ? Funkcji ? Jej Argumenty ? To jak ją wywołać ?
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ę.
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)
Dobra wiem już chyba po co suppiler ale jak ich użyć ?! Przecież mam tylko jej typ ( no tak to przynajmniej rozumiem )!
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.
To rozumiem ale jak wywołać jakąś funkcję ?
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
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.
Dobra co do void mnie olśniło (interfejsy) ale co do tych funkcji to nie wiem
Ostatecznie wymyśliłem by podawać w String typ funkcji a potem parametry najlepiej w jakimś objekcie. Jak coś to nadal czekam na odp. :)
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.
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 :)
To wywoła te funkcje.
Suuplier.get
, wywoła Function.apply
bo skąd inaczej ma mieć wynik takiej funkcji?