Repository navigation
More Liberal Assignment Instruction
Previously, you could only put an identifier on the left-hand side of an assignment, as in:
[#assign foo = "bar"]
Basically, the target of the assignment could only be a top-level variable defined either in the template's namespace or a local variable, i.e. defined within the scope of a macro call.
Now, you can write:
#set foo.bar = "baz"
And this maps onto the Java code foo.put("bar", "baz") assuming, of course, that foo is an instanceof java.util.Map. If not, it will try to use the typical Java beans naming pattern and thus try to call:
foo.setBar("baz")
Of course, it is perfectly possible that there is no appropriate setBar method, so then, as one would expect, an exception will be thrown in this spot.
Likewise, you can set an element in a list, as in:
#set foo[n] = bar
which, of course, maps onto list.set(n, bar);
I might as well admit that I (revusky) agonized over these (probably long-due) enhancements because it does deviate from the MVC paradigm, in which the 'M', the model, should typically be treated as immutable. However, finally, I decided that since we're (at least by default) exposing the Java API, and you can certainly write:
#exec foo::put("bar","baz")
we might as well allow the more natural syntax of:
#set foo.bar = "baz"
And, of course, if programmers want to prevent anybody working on the template layer from mutating the data, they can expose immutable maps to the template layer.
When I said above that you could only assign to the template's namespace or the local scope of a macro, that was actually not quite true. (A little white lie.) Actually, FreeMarker has long allowed you to write:
[#import "someLib.ftl" as lib]
[#assign foo = "bar" in lib]
So you could assign the foo variable in another scope. And, in fact, since the scope object is really just a HashMap, the above would be equivalent to: lib.put("foo", "bar");
Of course, the above construct was really only necessary because it was not possible to write:
[#assign lib.foo = "bar"]
So, it is perfectly maintainable that the #set var in lib notation is now superfluous and thus should be deprecated. Well, for now, I have decided to leave it there. Surely this is used extensively in existing code with macro libraries, and quite possibly, some people could consider it clearer to read. So, the bottom line is that you can still write:
#set foo = "bar" in mylib
but you can also write:
#set mylib.foo = "bar"
I guess one would still not really describe FreeMarker's template language (FTL) as a full-blown programming language. However, it is certainly complex enough that there are frequently multiple ways of writing the same thing.
So, it's your call.