PROPOSAL: fold keyword

Gabriel Belingueres belingueres at gmail.com
Tue Mar 10 07:01:20 PDT 2009


Hi,

First, thanks you for the input.

The main issue I wanted to avoid was creating new objects/anonymous
classes for executing the body of the loop, acting on the elements of
the collection. The ideal case would be to have closures in place, but
since this was not possible, using the current code in the for body
was my second choice.

There might be two benefits on doing it this way though, assuming the
following simple example:

  Integer sum = 0;
  for (Integer n : list)
    sum += n;:


1) In the current way, you want to compute a unique value from the
collection, but you are accumulating on the same variable unwanted
values of the target result, meaning this could potentially introduce
bugs if in the middle of the iteration an exception is thrown, leaving
your variable with garbage. With the fold version, the resulting
variable is scoped to the for loop, therefore an exception doesn't
touch the final result variable.

2) In the current way, you can't assign the result to a "final"
variable, which is something a programmer might want to do:

  final Integer sum = 0; // wrong
  for (Integer n : list)
    sum += n;

  so you need to introduce the code inside a new method:

  final Integer sum = sumAll(list);

  private Integer sumAll(List<Integer> l) {
    Integer sum = 0;
    for(Integer x : l)
      sum += x;
    return sum;
  }

  with the fold keyword:

  final Integer sum = fold(Integer n : list; Integer s = 0) {
    s += n;
  }


You are right in that the current for is somewhat simpler, and maybe
this is all because I don't like to see "break" or "continue" in
loops, but I think that the idiom would be a little more readable when
you introduce the break condition in the loop. For example: sum all
elements in the collection until the first prime number is found:

Now:

Integer sum = 0;
for(Integer x: list)
  if (isPrimeNumber(x))
    break;
  else
    sum += x;

with fold:

Integer sum =
  fold(Integer x : list; Integer s = 0; isPrimeNumber(x)) {
    s += x;
  }

Regards,
Gabriel



2009/3/5 Joshua Bloch <jjb at google.com>:
> Gabriel,
>
> This doesn't seem compelling.
>
> Here's your simple example:
>
>     // sum all numbers in the list
>     Integer sum =
>     fold(Integer n : list;     // iterating collection element n
>          Integer result = 0) { // Where to accumulate the result, and
>              the initial value
>              result += n;
>          };
>     }
>
> And here's how it looks today (with no change to the language or libraries):
>
>     Integer sum = 0;
>     for (Integer n : list)
>         sum += n;
>
>
> Here's one of your complex examples:
>
>   // returns a new collection with the salaries of the employees not on
> vacation
>  List<BigDecimal> salaries =
>    fold(Employee e : emps;
>         List<BigDecimal> newList = new ArrayList<BigDecimal>()) {
>      if (!e.onVacation()) {
>        newList.add(e.getSalary());
>      }
>    }
>
> And here's how it looks today:
>
>      List<BigDecimal> salaries = new ArrayList<BigDecimal>();
>      for (Employee e : emps)
>          if (!e.onVacation())
>              salaries.add(e.getSalary());
>
> To my eyes, the current version is clearer as well as shorter.
>
>             Josh
>
>
>
>
>



More information about the coin-dev mailing list