2016-02-21 10 views
5

stworzyłem dosłownego mapę zamknięć, coś jak:W Dart, czy można mieć mapę konstelacji zamknięć?

Map<String, Function> mapOfFuncs = { 
    'foo': (a, b, c) => ... , 
    'bar': (a, b, c) => ... , 
    ... 
} 

wszystko dobre do tej pory. Potem chciałem zrobić tę mapę, ponieważ jest ona globalna w moim programie i nigdy nie powinna być modyfikowana.

const Map<String, Function> MAP_OF_FUNCS = const { 
    'foo': (a, b, c) => ... , 
    'bar': (a, b, c) => ... , 
    ... 
} 

Dart dławiki na to jako dosłownych zamknięć na mapie nie są const.

Na Dartpad: https://dartpad.dartlang.org/817d2cfd141b0a56fc7d

bym nie pomyślał, że literalne zamknięcia są const. Czy istnieje sposób, aby je tak zrobić?

Odpowiedz

2

Zamknięcia nie są obsługiwane w wyrażeniach const.Istnieje otwarty numer https://github.com/dart-lang/sdk/issues/4596 i https://github.com/Pajn/dep-const-function-literals/issues/1

Jeśli zamiast tego tworzysz funkcje statyczne, możesz odwoływać się do nich w literałach stałych, ale obecnie nie możesz ich zdefiniować w linii.

+0

Świetne odkrycie, umieściłem komentarze wywołania zwrotnego w problemach, aby autorzy mogli w przyszłości podać prawidłowe odpowiedzi. W przeciwnym razie ciągnij informacje;) –

5

I podejrzewam, że może nie być możliwe, spojrzeć na ten kod:

int test1(int a, int b, int c) { 
    return a; 
} 
int test2(final int a, final int b, final int c) { 
    return a; 
} 

const Function f1 = test1; 
const Function f2 = (final a,b,c) => a; 

const Map<String, Function> MAP_OF_FUNCS = const { 
    'foo': test1, 
    'fam': test2, 
    'bam': f1, 
    'bar': f2 
}; 

Tylko pierwsze dwie wersje odwoływania się do metody statycznej odwołuje test1 i test2 prac w tej konstelacji. Nawet f1 powoduje błąd kompilacji, ale kompiluje używając dartJS jako @irn z wskazanych komentarzy. Wtedy nie jest jasne, dlaczego wersja z f2 nie działa.

Prawdopodobnie jest to operator przypisania, który nie jest w stanie utworzyć statycznie skompilowanej referencji dla danego stałego wyrażenia lambda lub statycznego odwołania do metody dla jego argumentu RHS (prawa ręka).

The documentation wskazał mi na testowanie kombinacji static const, ale generalnie działa tylko na elementach nie najwyższej klasy, takich jak członkowie klasy. W ten sposób dodanie nowej klasy umożliwia przetestowanie tego.

class A { 
    static const Function a1 = test1; 
    static const Function a2 = (final a, final b, final c) => a; 
} 
const Map<String, Function> MAP_OF_FUNCS = const { 
    'foo': A.a1, 
    'bar': A.a2 
}; 

Jednak te definicje funkcji są prawidłowe, ale przypisanie ich do mapy kończy się niepowodzeniem, tak jak poprzednio. Dokumentacja dotycząca map w sekcji built in types pokazuje, jak utworzyć mapę stałej czasu kompilacji za pomocą słowa kluczowego final.

final constantMap = const { 
    2: 'helium', 
    10: 'neon', 
    18: 'argon', 
}; 

Niestety, takie podejście ma tę samą wadę. Może to być niezgodne z ograniczeniami symboli:

Obiekt Symbol reprezentuje operator lub identyfikator zadeklarowany w programie Dart. Możesz nigdy nie używać symboli, ale są one nieocenione dla interfejsów API, które odwołują się do identyfikatorów po nazwie, ponieważ nazwy identyfikujące zmiany zmieniają nazwę, ale nie oznaczają identyfikatora. ... Literały symboli są stałymi w czasie kompilacji.

Aby uzyskać więcej informacji na temat symboli, zobacz dart:mirrors - reflection.

Może ktoś inny ma lepszy pomysł, ale dla mnie nie wydaje się to możliwe w tej chwili.

+1

Stała 'f1' powinna być stała, a dart2js nie ma problemu ze skompilowaniem go, więc wygląda na to, że błąd analizatora jest ostrzeżeniem. – lrn

+0

@lrn Zaktualizowano odpowiedź. –

+0

Powód, dla którego 'f2' nie działa, polega na tym, że wyrażenie funkcji nie jest wyrażeniem stałym w czasie kompilacji. Specyfikacja zawiera listę możliwych wyrażeń stałych w czasie kompilacji, a wyrażeń funkcji nie ma wśród nich, a wyrażenie inicjalizacyjne zmiennej stałej musi być wyrażeniem stałym w czasie kompilacji. – lrn

Powiązane problemy