On Mon, 8 Dec 2014 10:45:03 +0100 (CET) Dimitrios Apostolou <
ji...@cfengine.com> wrote:
DA> I think I get it now. So wouldn't it be enough to be able to call
DA> string functions in the promiser string?
DA> concat("comment_matches_", canonify("$(i)")) int => countlinesmatching("...$(i)...", $(edit.filename))
DA> Certainly not as terse as what you suggest, but wouldn't it solve the
DA> problem of intermediate assignments?
I think that would be useful, yes. But, knowing the parser and evaluator
a little bit, I think it would actually be harder to implement than the
syntax I proposed.
IMO the language will get terribly verbose if you require function calls
for everything (Lisp suffers this problem). Almost every language,
including the super-verbose Java, has a way to concatenate strings
without calling a function, so you could say
"comment_matches_" + canonify($(i))
in the promiser. (Even C sort of does this, with the "x" "y" preprocessor
syntax that comes out to "xy". Handy in macro hacks.)
So with a first-class string concatenation operator everywhere, not just
in promisers, I think your alternative is very good and answers my need
for the ability to call functions anywhere you can use a string. My only
concern, as I said, is that the implementation will be hard.
>> "comment_matches_$(~i)"
>>
>> which I think is *much* more readable.
DA> My opinion: No, because the tilde operator doing canonification is not
DA> common among languages, I would have to learn it first. The more
DA> special characters a language has, the less readable it is to
DA> outsiders.
I understand the concern. Still, canonification is already special to
CFEngine. Every DSL and programming language (I think CFEngine sits in
the middle) has domain-specific shortcuts. So I think it makes sense to
give CFEngine users some they will use *all* the time. Guaranteed.
Those who want crystal clarity can use canonify(). CFEngine's own
masterfiles could use the syntax in dozens of places to reduce code and
complexity.
The same argument goes for $(\i) to escape the variable i.
I implemented both of these with a little bit of work for scalars and
really think they would make life better for CFEngine users.
>> Another issue is that "classic" arrays don't take arbitrary strings as
>> keys, so `$(~i)` to canonify the variable i is more powerful.
>> [...]
DA> Can you please elaborate on that? Do you mean that they reject
DA> non-canonified characters as index? What if the arrays were fixed, and
DA> they were proper dictionaries? IMHO this is a very reasonable feature
DA> request. I'm not sure it's possible though, mostly because of ordering
DA> issues...
MB> Arrays used to accept arbitrary string keys, but I vaguely remember a
MB> discussion about changing that a year or two ago. I was against a
MB> change, but I don't know what the outcome was.
MB> Having generic string keys has several important use cases.
Fortunately, data containers support generic string keys, which solves
many use cases. But the need here is for dynamically created arrays,
maparray()-style, with the keys and values transformed on the fly.
That's not easy for data containers because they are read-only so you
have to iterate. You can sort of hack it with mergedata() but it
doesn't work too well.
I wrote a PR for a mapjson() function that could do what maparray() did
but for data containers. A more general solution would be great, and if
the string concatenation syntax is implemented, it would be pretty easy
to write a data_maparray() or mapjson() function that looks like
"result" data => data_maparray("the key " + $(this.k), "the value " + $(this.v), myarray);
DA> Maybe using the existing syntax of @(variable) would be an intuitive
DA> way for printing all of variable (container or slist) in one line,
DA> without iterating.
Oh, you mean like:
reports:
"my container is @(container)";
That would work, but it may break backwards compatibility because the
string "@(mylist)" is used very often when you call bundles or
functions. I'm in favor of it, if it's possible.
DA> If you also need function calls for formating, canonifying etc then
DA> this wouldn't be enough, you would need a separate variable.
Yes, typically when you're debugging you want to see the actual contents
of the variable, so you don't need to transform them further. I think
that's the most important use case.
>> Do you think that's better that `$(= 2+4-$(total))` or `$(~i)`?
DA> Well if you factor out the ugly syntax of eval() (which can easily be
DA> fixed by omitting the "math" and "infix" arguments and making them
DA> defaults)
That's not a bad idea :)
DA> then yes, I am clearly in favor of function calling.
I think we should poll experienced CFEngine policy writers (maybe on
help-cfengine). I feel these very specific shortcuts would cut out a lot
of code, but I may be wrong about how much they are needed.
Thanks
Ted