control(3tcl)

πŸ“¦
version 2.0 Β· 2 versions
, in debian trixie, ubuntu questing, ubuntu resolute, ubuntu stonking

πŸ’– control β€” Procedures for control flow structures πŸ’–

okay bestie, so this is control(3tcl), aka the Tcl Control Flow Commands page from tcllib. it's all about making Tcl do the lil flow-control tricks other languages get for free. no cap, it's giving "keywords but make them just commands". let's get into it πŸ¦‹


✨ SYNOPSIS ✨

package require Tcl 8.5 9

package require control ?0.1.4?

control::control command option ?arg arg ...?

control::assert expr ?arg arg ...?

control::do body ?option test?

control::no-op ?arg arg ...?

🌸 DESCRIPTION 🌸

so the control package hands you a whole lil collection of commands that give you extra flow-of-control structures on top of the ones Tcl already ships with. these are the kinds of things that in a lot of programming languages would just be keywords, like, baked right into the language itself. but in Tcl? control flow structures are just commands like everything else. iconic behavior honestly πŸ’…


πŸŽ€ COMMANDS πŸŽ€

πŸ’œ control::control β€” the config queen

control::control command option ?arg arg ...?

control::control is the configuration command for customizing all the other public commands in the control package. the command argument names whichever command you wanna customize. the valid options and whatever args come after them depend entirely on the command you're customizing, and they're documented with that command. so like, iykyk β€” go read the specific command's section πŸ”₯

πŸ’œ control::assert β€” the vibe checker

control::assert expr ?arg arg ...?

when it's disabled, assert behaves exactly like the no-op command. like, literally identical energy.

when it's enabled, assert evaluates expr as an expression (same way expr evaluates its argument). now listen:

  • if evaluating shows that expr is not a valid boolean expression (per [string is boolean -strict]), an error is raised. oop 😭
  • if expr evaluates to a true boolean value (as recognized by if), then assert returns an empty string. slay, everything's fine.
  • otherwise β€” bestie, we got a problem β€” the remaining arguments to assert get used to build a message string:
    • if there are no arguments, the message string is "assertion failed: $expr".
    • if there are arguments, they get joined by join to form the message string.
    • then that message string is appended as an argument to a callback command, and the completed callback command is evaluated in the global namespace.

the assert command can be customized by the control command in two ways, bestie, pay attention πŸ‘‘

  • [control::control assert enabled ?boolean?] β€” queries or sets whether control::assert is enabled. call it with no boolean argument and you get back a boolean value saying whether control::assert is enabled. call it with a valid boolean value as the boolean argument and the control::assert command gets enabled or disabled to match, and an empty string comes back.
  • [control::control assert callback ?command?] β€” queries or sets the callback command that an enabled assert will call on assertion failure. call it with no command argument and you get the current callback command. call it with a command argument and that argument becomes the new assertion failure callback command. note: an assertion failure callback command is always defined, even when assert is disabled. the default callback command is [return -code error].

and here's the cute part: control::assert was written so that, in combination with [namespace import], you can have enabled assert commands in some namespaces and disabled assert commands in other namespaces at the same time. that's lowkey super useful because it means debugging efforts can be controlled independently, module by module. main character energy fr fr ✨

% package require control
% control::control assert enabled 1
% namespace eval one namespace import ::control::assert
% control::control assert enabled 0
% namespace eval two namespace import ::control::assert
% one::assert {1 == 0}
assertion failed: 1 == 0
% two::assert {1 == 0}

πŸ’œ control::do β€” the looper

control::do body ?option test?

do evaluates the script body over and over until the expression test becomes true, or for as long as (while) test is true β€” depending on whether option is until or while.

if option and test are omitted, the body is evaluated exactly once. after normal completion, do returns an empty string.

exceptional return codes (break, continue, error, etc.) that happen during evaluation of body get handled the same way the while command handles them β€” except as noted in LIMITATIONS, down below πŸ‘‡

πŸ’œ control::no-op β€” the do-nothing icon

control::no-op ?arg arg ...?

no-op takes any number of arguments and does absolutely nothing with them. it returns an empty string. that's it, that's the whole command. honestly? relatable. πŸ’€


😭 LIMITATIONS 😭

so several of the commands the control package gives you accept arguments that are scripts to be evaluated. and because of fundamental limitations of Tcl's catch and return commands, it is not possible for these commands to properly evaluate the command [return -code $code] inside one of those script arguments, for any value of $code other than ok.

which means the commands of the control package are limited compared to Tcl's built-in control flow commands (like if, while, etc.) and compared to control flow commands that can be provided by packages coded in C. here's what that difference actually looks like:

% package require control
% proc a {} {while 1 {return -code error a}}
% proc b {} {control::do {return -code error b} while 1}
% catch a
1
% catch b
0

see? not the same. no cap. 🫢


πŸ› BUGS, IDEAS, FEEDBACK πŸ›

this document, and the package it describes, will undoubtedly contain bugs and other problems. (they said it, not me!) please report such in the category control of the Tcllib Trackers at http://core.tcl.tk/tcllib/reportlist. also please report any ideas for enhancements you may have for either the package and/or the documentation. we wanna hear it πŸ’–

when proposing code changes, please provide unified diffs, i.e. the output of diff -u.

note further that attachments are strongly preferred over inlined patches. attachments can be made by going to the Edit form of the ticket immediately after its creation, and then using the left-most button in the secondary navigation bar. πŸ“Ž

🌈 SEE ALSO 🌈

break, continue, expr, if, join, namespace, return, string, while


⭐ KEYWORDS ⭐

assert, control, do, flow, no-op, structure


πŸ‘‘ CATEGORY πŸ‘‘

Programming tools


and that's the whole page bestie, we ate and left no crumbs πŸ“ this was tcllib version 0.1.4, filed under control(3tcl) β€” mwah, go write some flow control, you got this πŸ’…βœ¨πŸŽ€

πŸ“¦ where this page comes from