Summary
Calling a user-defined action in expression position without the call keyword does not call the action — the expression parses as with-concatenation of the action value plus a logical and chain of the intended arguments — and the program runs anyway, producing garbage output. The only diagnostic is a non-fatal typechecker warning, so the failure is easy to ship.
Minimal reproduction
define action called build_reply with parameters user_text and model_id and via_text:
return "hello " with user_text
end action
store reply_text as build_reply with "world" and "m1" and "t1"
display reply_text
Actual output:
That is: build_reply stringifies as action build_reply, then with concatenates the result of "world" and "m1" and "t1" evaluated as logical And (truthy → yes). The typechecker does warn —
error[ERROR]: Cannot perform logical And on Boolean and Text - Expected Boolean but found Text
— but the program still executes (warnings are non-fatal), so in a server context this surfaced as a chatbot streaming the literal reply "action build_replyyes" to the browser.
The working form is store reply_text as call build_reply with "world" and "m1" and "t1" (as used in TestPrograms/action_overloading_comprehensive.wfl).
Why this matters
Principle 4 (clear, actionable errors) and the No-Unlearning Invariant: add with 5 and 3-style call syntax appears in learning materials, and the statement form call name with args teaches that with introduces arguments — so store x as name with args is exactly what a beginner writes. Getting a silently-wrong value with only a type warning (whose message points at and, not at the missing call) is a trap.
Environment
- wfl 26.7.52, built from source at
ed704e6 (current main), rustc 1.94.1, Linux
Suggested improvements (any of)
- When an expression's leading identifier resolves to an action and is followed by
with, either parse it as a call, or
- make it a hard parse/analyze error ("
build_reply is an action — did you mean call build_reply with ...?"), or
- at minimum, special-case the typechecker diagnostic to suggest the missing
call when the left operand of the offending with/and chain is an action value.
Summary
Calling a user-defined action in expression position without the
callkeyword does not call the action — the expression parses aswith-concatenation of the action value plus a logicalandchain of the intended arguments — and the program runs anyway, producing garbage output. The only diagnostic is a non-fatal typechecker warning, so the failure is easy to ship.Minimal reproduction
Actual output:
That is:
build_replystringifies asaction build_reply, thenwithconcatenates the result of"world" and "m1" and "t1"evaluated as logical And (truthy →yes). The typechecker does warn —— but the program still executes (warnings are non-fatal), so in a server context this surfaced as a chatbot streaming the literal reply "action build_replyyes" to the browser.
The working form is
store reply_text as call build_reply with "world" and "m1" and "t1"(as used inTestPrograms/action_overloading_comprehensive.wfl).Why this matters
Principle 4 (clear, actionable errors) and the No-Unlearning Invariant:
add with 5 and 3-style call syntax appears in learning materials, and the statement formcall name with argsteaches thatwithintroduces arguments — sostore x as name with argsis exactly what a beginner writes. Getting a silently-wrong value with only a type warning (whose message points atand, not at the missingcall) is a trap.Environment
ed704e6(current main), rustc 1.94.1, LinuxSuggested improvements (any of)
with, either parse it as a call, orbuild_replyis an action — did you meancall build_reply with ...?"), orcallwhen the left operand of the offendingwith/andchain is an action value.