[ 
https://issues.apache.org/jira/browse/CAMEL-24921?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18118281#comment-18118281
 ] 

Claus Ibsen commented on CAMEL-24921:
-------------------------------------

The full write-up is attached as [^simple-operators-analysis.md]. The options 
it weighs, and the reasoning, are below so they are readable here.

h3. What the alternatives are

*A. Full expression inside the braces.* The inside becomes an expression in 
every case. Maximum consistency with EL and Groovy, maximum risk: it changes 
what {{$\{header.foo-bar\}}} means, and the parser has to grow.

*B. Predicate first, with the whitespace rule.* If the inside parses as a 
predicate or an arithmetic expression with whitespace-separated operators at 
the top level, evaluate it as one; otherwise it is a function, exactly as 
today. Zero collisions in the corpus, and it subsumes the ternary instead of 
sitting beside it. {{$\{body != null && body.size() > 0\}}} works, 
{{$\{header.Content-Length\}}} is untouched.

*C. Leave the language, keep improving the message.* The hint already prints 
the corrected expression back, and the numbers say that is not enough: 56 
refusals across the four benchmark series, and of the 52 followed by another 
attempt only 17 were free of the same mistake.

*D. Fix the ternary gap only* (CAMEL-24920). {{$\{a > 0 && b < 10 ? 'x' : 
'y'\}}} failing is hard to defend on its own terms, independent of anything 
above.

h3. Recommendation

D now, B as the design question worth taking seriously.

D is a plain gap: the ternary accepts a condition but only a single comparison, 
so any real condition has to be lifted out of the braces - which is the very 
move that confuses everyone.

B is the change that removes the whole class of mistake, and the corpus says it 
can be made without breaking a single expression in Camel, the Kamelets or the 
examples. It should not be written until the prototype has run the 
3425-expression corpus as a regression suite.

h3. Where the evidence comes from

The AI route benchmark, series s10-s13: 20 runs of four HTTP integration 
examples with a local model (qwen3.6:35b-a3b) driving the camel-jbang MCP 
tools. _Operators go outside the function_ is the most repeated validation 
error in the series and the blocker on one rung that has never passed in 15 
runs. The model is not confused about Camel; it is writing EL.

The corpus numbers are reproducible: take every {{$\{...\}}} from Camel 
contexts only (the {{simple(...)}} string literal in Java, route YAML and XML, 
kamelets), strip quoted text, {{[...]}} and {{(...)}}, skip the colon-prefixed 
functions, and count what is left that has whitespace-separated operators at 
the top level.

> camel-core: read a predicate inside ${ } in the Simple language, as EL and 
> Groovy do
> ------------------------------------------------------------------------------------
>
>                 Key: CAMEL-24921
>                 URL: https://issues.apache.org/jira/browse/CAMEL-24921
>             Project: Camel
>          Issue Type: Improvement
>          Components: camel-core
>            Reporter: Claus Ibsen
>            Priority: Major
>         Attachments: simple-operators-analysis.md
>
>
> h3. What the language does today
> Tested on 4.23.0-SNAPSHOT:
> || expression || today ||
> | {{$\{header.n > 0 ? 'positive' : 'negative'\}}} | works |
> | {{$\{header.n > 0\}}} | error: _Operators go outside the function_ |
> | {{$\{header.n\} > 0}} | works |
> | {{$\{header.n > 0 && header.n < 10 ? 'in' : 'out'\}}} | error (CAMEL-24920) 
> |
> Operators inside the braces are already parsed - as the condition of a 
> ternary - but only comparisons, never {{&&}} or {{||}}, and never a compound 
> condition. Outside a ternary the same characters are refused. A person has to 
> hold three overlapping rules in their head.
> h3. Why the wrong form is the natural one
> Every other language that uses {{$\{ \}}} treats the braces as a complete 
> expression: Jakarta EL ({{$\{user != null && !user.list.isEmpty()\}}}), 
> Groovy GString, JavaScript template literals, Thymeleaf with SpEL. In Simple, 
> {{$\{ \}}} delimits a value and the template is what surrounds it. Both 
> models are defensible - the trouble is that Simple looks like EL and is not.
> h3. Evidence that a better message does not fix it
> In the AI route benchmark (20 runs of four HTTP examples with a local model 
> driving the camel-jbang MCP tools), _Operators go outside the function_ fired 
> 56 times across four series. The message already prints the corrected 
> expression back. Of the 52 refusals followed by another attempt, only *17 
> were free of the same mistake* - it is repeated two times out of three. For 
> comparison, the hint for {{handled: true}} (CAMEL-24915) was obeyed 11 times 
> out of 11. A message cures a shape nobody has seen before; it does not cure a 
> habit carried in from another language.
> h3. What it would cost, measured
> Corpus: every {{$\{...\}}} in a Camel context across camel (route tests via 
> the {{simple(...)}} literal, route YAML and XML), camel-kamelets, 
> camel-examples and camel-jbang-examples. Maven properties and prose excluded. 
> *3425 uses, 804 unique expressions.*
> How many would an expression parser re-read?
> || rule || re-read ||
> | any operator character anywhere | 564 uses (16%) |
> | ignoring quotes, {{[...]}} and {{(...)}}, and colon-prefixed functions 
> ({{date:}}, {{bean:}} ...) | 61 uses (1.8%) |
> | and requiring whitespace around the operator | *1 use (0.03%)* |
> The 61 are all one shape: a dotted name whose last segment has a hyphen - 
> {{$\{header.Content-Length\}}}, {{$\{exchangeProperty.aws-s3-bucket\}}}. None 
> has a space around the hyphen. The single remaining use is an existing 
> ternary, which is meant to be an expression. The bracket form is already 
> safe: {{$\{header[Content-Type]\}}} and {{$\{header[ce-file]\}}} - 516 of the 
> 564 raw hits - live inside {{[...]}}, which a top-level scanner never enters.
> h3. Proposal
> If the inside of {{$\{ \}}} parses as a predicate or an arithmetic expression 
> *with whitespace-separated operators at the top level*, evaluate it as one; 
> otherwise it is a function, exactly as today. Simple already requires 
> whitespace around the ternary's {{?}} and {{:}}, so the rule is not new. This 
> subsumes the ternary instead of sitting beside it, and CAMEL-24920 disappears 
> with it.
> Before any code:
> # a prototype parser with the 3425-expression corpus as a regression suite - 
> every expression must produce the same value before and after
> # a decision on the template case: {{$\{header.n\} > 5}} in a text template 
> produces {{5 > 5}}, while {{$\{header.n > 5\}}} would produce {{true}}. Both 
> are useful and they must not collide
> # the error message when the inside does not parse, which is where the 
> current design pays off - it can say what is wrong and where, instead of 
> refusing the shape



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to