control(n)

πŸ“¦
version 2.0 Β· 2 versions
, in fedora 43, fedora 44, nixos 26.05, nixpkgs unstable

πŸ’– control(n) β€” the Tcl Control Flow Commands era πŸ’–

okay bestie, sit down, we're talking about the control package, no cap. it lives in the control(n) manual, it's giving "extra control flow structures for Tcl," and honestly? it ate. ✨


🌸 NAME 🌸

control β€” Procedures for control flow structures. literally that's the whole vibe. πŸ¦‹


✨ 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 ...?

look at her. four little commands and a package requirement. main character energy fr fr. πŸ‘‘


πŸŽ€ DESCRIPTION πŸŽ€

The control package hands you a whole lineup of commands that give you additional flow of control structures beyond the built-in ones Tcl already ships with. like, these are the things that in a lot of other programming languages would be keywords, or baked straight into the language itself. πŸ’…

but Tcl said "no ❀️" β€” in Tcl, control flow structures are just commands like everything else. periodt. that's the whole philosophy and we respect it deeply. 🌈


πŸ’– COMMANDS πŸ’–

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

so control here is the configuration command, aka the lil settings panel for all the other public commands in the package. the command argument names which command you're customizing. 🧚

the set of valid options and the arguments that come after them is decided by the command being customized, and each one documents its own stuff. so go read that command's section, bestie, it's all there. πŸ“–

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

when it's disabled, assert behaves exactly like the no-op command. like, a whole nothing-burger. πŸ”

when it's enabled, though? oh she's working. assert evaluates expr as an expression β€” same way expr evaluates its own argument. then:

  • if the evaluation reveals that expr isn't a valid boolean expression (according to [string is boolean -strict]), an error is raised. 😭
  • if expr evaluates to a true boolean value (as recognized by if), then assert returns an empty string. cute, clean, done. ✨
  • otherwise, the remaining arguments to assert get used to construct a message string:
    • if there are no arguments, the message string is "assertion failed: $expr".
    • if there are arguments, they're joined by join to form the message string.

then the message string gets appended as an argument to a callback command, and that completed callback command is evaluated in the global namespace. 🫢

now, assert can be customized by the control command in two ways:

  • [control::control assert enabled ?boolean?] β€” queries or sets whether control::assert is enabled. called without a boolean argument, you get back a boolean value telling you whether the control::assert command is enabled. called with a valid boolean value as the boolean argument, the control::assert command is enabled or disabled to match, and an empty string comes back at you.
  • [control::control assert callback ?command?] β€” queries or sets the callback command that an enabled assert will call on assertion failure. called without a command argument, you get the current callback command. called with a command argument, that argument becomes the new assertion failure callback command. heads up: an assertion failure callback command is always defined, even when assert is disabled. the default callback command is [return -code error].
not me being obsessed with this next 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. πŸ’€ so useful β€” it means debugging efforts can be independently controlled module by module. iykyk.
% 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}

see how one::assert screamed and two::assert said absolutely nothing? that's the whole point, bestie. πŸŽ€

control::do body ?option test?

do evaluates the script body repeatedly until the expression test becomes true, or 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.) during the evaluation of body are handled the same way the while command handles them β€” except as noted in LIMITATIONS below. go read that bit, it matters. πŸ‘€

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

takes any number of arguments and does nothing. returns an empty string. she's just standing there, existing, thriving, contributing nothing. iconic. πŸ’…


😭 LIMITATIONS 😭

Several of the commands in the control package accept arguments that are scripts to be evaluated. but due to fundamental limitations of Tcl's catch and return commands, it is not possible for these commands to properly evaluate the command [return -code $code] within one of those script arguments for any value of $code other than ok. 🫠

so yeah β€” the commands of the control package are limited compared to Tcl's built-in control flow commands (like if, while, etc.) and compared to those control flow commands that can be provided by packages coded in C. an example of this difference:

% 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

a catches as 1, b catches as 0. that's the difference. not me crying over $code values. 😭


πŸ’œ BUGS, IDEAS, FEEDBACK πŸ’œ

ngl, this document β€” and the package it describes β€” will undoubtedly contain bugs and other problems. it's giving "we're all just doing our best." πŸ™ˆ

please report such things in the category control of the Tcllib Trackers at [http://core.tcl.tk/tcllib/reportlist]. and please also report any ideas for enhancements you may have for either the package and/or the documentation. we want them fr fr. 🫢

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. slay, thank you. ✨


🌈 SEE ALSO 🌈

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

the whole squad. all present and accounted for. πŸ’–


⭐ KEYWORDS ⭐

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


πŸŽ€ CATEGORY πŸŽ€

Programming tools


and that's the page, bestie!! written by tcllib, version 0.1.4, filed under control(n) β€” go forth and assert responsibly, enable your callbacks, and remember: in Tcl, control flow is just commands like everything else. πŸ’…βœ¨πŸ¦‹πŸ’–

πŸ“¦ where this page comes from