OVERVIEW
FEATURE SUMMARY:
Consider operator extends language with full value support and assign value to name and return it.
MAJOR ADVANTAGE:
It introduces natural division in variables and values.
MAJOR BENEFIT(s):
- If we need to get a value, we can do that quite simple (without splitting expression or duplicating code).
- Decrease number of potential bugs (value cannot be assigned).
- It can help in splitting code to proper parts; nowdays, we need to declare variable regardless we need it or not (or make it final).
- Decrease size of unnecessary code.
- Method can be itself multi-thread with this, but it's far future.
MAJOR DISADVANTAGE:
Possibility to be unclear at start.
ALTERNATIVES:
Some time 'final' variables can be used, but it's more like for-each, life is better with it.
EXAMPLES
SIMPLE EXAMPLE:
public static void standard(Resource<String,Container<Unit>> resource) {
Comparator<Resource<String,Container<Unit>>> resourceComparator
= (standard? Resource.baseComparator : Resource.extdComparator);
if (resourceComparator.compare(resource,this.last)==0) return; // duplicate
...
}
public static void consider(Resource<String,Container<Unit>> resource) {
(standard? Resource.baseComparator : Resource.extdComparator) :: resourceComparator;
if (resourceComparator.compare(resource,this.last)==0) return; // duplicate
...
}
public static void standard_2(ArrayList<Resource<String,Container<Unit>>> resources){
for (Resource<String,Container<Unit>> resource: resources){
System.out.println(resource);
}
}
public static void consider_2(ArrayList<Resource<String,Container<Unit>>> resources){
for (::resource:resources){
System.out.println(resource);
}
}
ADVANCED EXAMPLE:
public void validLastElementState(ArrayList<Data> list){
if (list.get(list.size()::size-1)::data.reportStare().getState()!=validState){
throw new IllegalStateException(Data.class.getSimpleName()+"("+data+") of "+size+" elements is in wrong "+State.class.getSimpleName());
}
... other operations ...
}
public void validLastElementState(ArrayList<Data> list){
{
list.size()::size;
list.get(size-1)::data
if (data.reportStare().getState()!=validState){
throw new IllegalStateException(
Data.class.getSimpleName()+"("+data+") of "+size+" elements is in wrong "+State.class.getSimpleName());
}
}
... other operations ...
}
DETAILS
SPECIFICATION:
Value :: name
Assign left side value to given name and return it.
JLS 14.14.2
EnhancedForStatement:
for ( VarDeclaration : Expression) Statement
VarDeclaration: al least one of
VariableDeclaration
ValueDeclaration
VariableDeclaration
VariableModifiersopt Type Identifier
ValueDeclaration
:: ValueName
COMPILATION:
While value is same as final variable compiling is not big problem.
TESTING:
Same as final variable.
LIBRARY SUPPORT:
No.
REFLECTIVE APIS:
No.
OTHER CHANGES:
No.
MIGRATION:
No need.
COMPATIBILITY
Compiled code can be normally executed.
REFERENCES
Instrukcje
Człowiek nie myśli sekwencyjnie, tak więc i pisanie sekwencyjnych algorytmów nie jest czymś zupełnie naturalnym dla niego. Dlatego założenie, że sekwencyjny algorytm będzie czytać się łatwo jest co najmniej nie trafione.
Proponowany operator '::' ma ułatwić myślenie o wynikach jak o wynikach a nie zmiennych, a wiązał by on wartość z nawą: wartość::nazwa, (wartość po ktorej możemy iterować):::(nazwa wartości iterowanych) bądź wartość::nazwa::{blok w którym obowiązuje wartość}. Nie należy zapominać że pewnym ukłonem (bardzo sensownym zresztą) w te stroną są 'zmienne' final.
Aby w pełni zrozumieć sytuacje przyjrzyjmy tytułowi jednego z rozdziałów JLS: „Types, Values, and Variables” wygląda pięknie jednak nie do końca odpowiada rzeczywistości która rysuję się raczej jak: „Types, Variables and their Values”, gdyż tak naprawdę wartości są tylko częściowo wspierane przez Jave. 'Zawężenie' myślenia do kategorii zmiennych wynika z asemblera i obecnie znacznie ogranicza nas przed myśleniem o niektórych bytach jako lokalnie nie zmiennych (wartość nie może się zmienić).
Jak wyglądała by Java wspierająca wartości:
Częściowo(czyli tak jak obecnie) :
public void validLastElementState(ArrayList<Data> list) {
{
int size = list.size();
Data data = list.get(size - 1);
if (data.reportStare().getState()!=validState){
throw new IllegalStateException(Data.class.getSimpleName()+"("+data+") of "+size+" elements is in wrong "+State.class.getSimpleName());
}
}
... other operations ...
}
W ogóle (+/-) :
public void validLastElementState(ArrayList<Data> list) {
{
int size = list.size();
int position =size -1;
Data data = list.get(position);
StateReporter stateReporter = data.reportStare();
State state = stateReporter.getState();
if (state!=validState){
throw new IllegalStateException(Data.class.getSimpleName()+"("+data+") of "+size+" elements is in wrong "+State.class.getSimpleName());
}
}
... other operations ...
}
W pełni :
public void validLastElementState(ArrayList<Data> list){
if (list.get(list.size()::size-1)::data.reportStare().getState()!=validState){
throw new IllegalStateException(Data.class.getSimpleName()+"("+data+") of "+size+" elements is in wrong "+State.class.getSimpleName());
}
... other operations ...
}
Przegląd
Główne zalety / korzyści:
- Naturalny zapis algorytmów bez niepotrzebnych rozbić tylko dla wyciągnięcia zmiennej.
- Możliwość naturalnego rozbicia odpowiednio napisanych metod na wiele wątków(daleka przyszłość).
- Mniejsza ilość bugów.
- Ułatwia rozdzielenie kodu na więcej mniejszych linijek (nie trzeba deklarować zmiennych).
- Mniejsza ilość niepotrzebnego kodu.
Najistotniejsze wady:
- Dla niektórych taki zapis może być czymś problematycznym.
- Konieczność rozważenia widoczności wartości.
- Pewnym problemem może być fakt, że w warunkach logicznych && operator '::' mógłby znajdować się tylko z lewej strony wyrażenia (prawa może zostać pominięta).
Inne rozwiązania:
- Używanie 'zmiennych' final.
Podsumowanie:
Powyższe rozwiązanie nie wprowadza do języka nic nowego, pozwala jednak zapisywać algorytmy w sposób bardziej naturalny/intuicyjny. Nie należy zapominać iż daje także możliwość większego 'narzygania' do kodu.
Przykłady:
W pełni :
public void validLastElementState(ArrayList<Data> list){
list.size()::size;
list.get(size-1)::data
if (data.reportStare().getState()!=validState){
throw new IllegalStateException(Data.class.getSimpleName()+"("+data+") of "+size+" elements is in wrong "+State.class.getSimpleName());
}
... other operations ...
}
public static void printAll(ArrayList<ArrayList<SomeGeneric<String, Integer>>> param) {
for (ArrayList<SomeGeneric<String, Integer>> l1 : param) {
for (SomeGeneric<String, Integer> l2 : l1) {
System.out.println(l2);
l2=null;//ok
}
}
}
public static void printAll(ArrayList<ArrayList<SomeGeneric<String, Integer>>> param) {
for (param:::l1) {
for (l1:::l2) {
System.out.println(l2);
l2 = null;//error
}
}
}
Detale rozwiązania:
Wartość sama z siebie nie może się zmienić, gdyż była by inną wartością, a co za tym idzie wszelkie próby podstawienia kończyły by się błedem w czasie kompilacji.
Kompatybilność:
Wsteczna:
Pełna.
W przód:
Brak.
0 comments / komentarz(y):
Post a Comment