11 March 2009

Consider operator proposal

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.

It makes language to be more natural for human and generics easier to use.

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 ...
  }
Would be compiled to:
  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

Consider operator proposal

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