[GRASS-dev] r.mapcalc eval function: syntax and existing maps

Hi,

I have two r.mapcalc problems to think about.

You probably remember Glynn’s example of eval function usage in r.mapcalc expression. The example is now in the manual and says:

r.mapcalc << EOF
eval(elev_200 = elevation - 200,
elev_5 = 5 * elevation,
elev_p = pow(elev_5, 2))
elevation_result_1 = (0.5 * elev_200) + 0.8 * elev_p
EOF

However, the function descriptions says that:

eval([x,y,…,]z) evaluate values of listed expr, pass results to z

And the section NULL support (btw, why this one?) says that:

The eval() function always returns its last argument

So, as a consequence I tried this:

r.mapcalc << EOF
elevation_result_2 = eval(elev_200 = elevation - 200,
elev_5 = 5 * elevation,
aspect = pow(elev_5, 2),
(0.5 * elev_200) + 0.8 * aspect)
EOF

And it works.

The questions are now: Are both versions valid? And if yes, is one of them best practice? And should both be in the manual?

The site note is that manual perhaps defines how the function/syntax behaves but does not provide examples nor conclusion about what is allowed and possible. In my opinion, manual should not require user to infer how to use the module, it should show how to do it.

The second think to discuss is the behavior when you use name aspect in the eval function, although the aspect map exists. I described the behavior in r58765. Please review.

Vaclav

[r58765] https://trac.osgeo.org/grass/changeset/58765

[r.mapcalc] http://grass.osgeo.org/grass70/manuals/r.mapcalc.

[GRASS-user] Trying to reclassify raster using non-linear functions in GRASS
http://lists.osgeo.org/pipermail/grass-user/2013-November/069225.html

Vaclav Petras wrote:

The questions are now: Are both versions valid?

Yes, for sufficiently-recent versions of r.mapcalc. The first version
won't work in older versions, which required each top-level expression
to be an assignment. This was changed in r33674 to allow top-level
expressions to be either assignments or function calls (it doesn't
actually require that the function is eval(), but nothing else makes
sense in that context).

And if yes, is one of them best practice? And should both be in the
manual?

I'm not really sure.

I prefer the second form for a single map. Where a set of variables
are being defined for use in the expressions for multiple output maps,
I would prefer the first form. But this is purely a stylistic issue.

The site note is that manual perhaps defines how the function/syntax
behaves but does not provide examples nor conclusion about what is allowed
and possible. In my opinion, manual should not require user to infer how to
use the module, it should show how to do it.

The second think to discuss is the behavior when you use name `aspect` in
the `eval` function, although the `aspect` map exists. I described the
behavior in r58765. Please review.

The key point are:

1. For each assignment at the top-level, a map will created having the
same name as the variable on the left-hand side of the assignment.
Assignments nested within expressions create a variable but not a map.

2. All variables are global; there are no scope rules.

3. eval() returns its last argument, ignoring the others. Typically
all of its arguments except for (possibly) the last argument would be
assignments. As the values aren't used, arguments other than the last
are only useful for their side effects, so expressions other than
assignments aren't useful.

--
Glynn Clements <glynn@gclements.plus.com>