Thanks to Richard I think I now understand what goes on. The definition
g(s) := arrayapply(s, [4]);
seems to work correctly in all cases.
Explanation(?): s is protected inside g but not s[4] (if s[4] has a
global meaning then it is evaluated immediately before subsituting
the parameter s with the argument to g).
Using arrayapply(s, [4]) is a trick(?) to avoid using s[4] directly.
====
As explained above gg(s):=s[4]; does not work. s[4] is evaluated
immediately before any parameter subsitutions take place.
====
ggg(s):=block([],local(s),s[4]);
does not work since now ggg(s) returns s_4 (unevaluated). Explanation:
since s is now local to ggg, s[4] is protected but unfortunately ggg
also does no longer know the global meaning of s_4.
Note however that ggg(t) does work! After replacing the parameter s by t
the result is t_4 but since t is not defined as local, maxima can look
up the definition of t_4 in the global environment and evaluate it further.
======
Wouldn't is be more natural if things like s[4] were automatically
protected inside a function body if s is a parameter?
It seems to me this is the way other languages behave.
Michel