'''Everything is a Constructor''' is an idea for the improvement of Tcl in which additional information about values is given first-class status. ** Description ** [PYK] 2017-06-01: '''[EIAS]''' is a principle of the current Tcl implementation in which every argument to a command is interpreted as if a certain literal string had been passed as the argument. In fact, Tcl processes words in a command for substitutions before it passes them to a routine, but any information generated by this processing is subsequently only used in a way that is semantically equivalent to the processing that would have occurred had a corresponding string with no additional information been passed. This means for example that in order for `[puts]` to take as its optional argument either a channel or a file name, it would have to devise some string format to differentiate a channel from a file name. Since a file can have an arbitrary name, this can't be done. In [Changes in Tcl/Tk 8.5%|%Tcl 8.5], a new processing directive was was admitted at the script level and it was implemented as a change to the syntax: A literal `[{*}]` in a script at the beginning of a word tells the interpreter to unpack that word into multiple words, which has the effect of expanding the number of arguments handed to a routine when it is called. This is a welcome bit of functionality, but did it have to be a syntactic change to Tcl? One thing that seems to be conspicuously absent from the discussions that led up to the implementation of `[{*}]` is any substantive proposal to accomplish the task by inspecting the internal representation of the value. Rather than introducing new syntax, a command which returned an "expand me" value could have been introduced: ====== set [expand {name Bob}] ====== This approach harmonizes with the principle that nearly all functionality is exposed in terms of commands. Commands such as `[lreplace]`, operate this way, using any existing list structure to get the job done more efficiently. The same trick can be used to allow the interpreter to perform argument expansion. The very existence of Rule 5 illustrates the flexibility that the interpreter has in this regard. That flexibility could be better articulated by making small change to the wording of [dodekalogue%|%Rule 2]: : ''..., then all of the words of the command are passed to the command procedure.'' , Rule 2 could have been modified to say, : ''..., then the resulting values are passed as arguments to the command procedure.'' Eliminating that second use of "word" to describe the result of the substitutions makes it clear that words are processed into arguments to the routine, and since Tcl itself is in charge of the creation and use of these processed values, it is free to put them to work. '''Everything is a Constructor''' conveys the idea that while the words in a command produce the values in a Tcl script, but they are not in themselves the values. If values rather than words are the arguments to a routine, commands can relax in regards to [EIAS]. In the earlier example, `[puts]` could inspect its optional second argument to determine that it is in fact not a channel, and then treat it as a filename instead. ** `is` ** '''`string is`''' is currently available to determine whether a string representation of a value conforms to a certain format. Once words and values are no longer being conflated, a similar command, perhaps named '''`is`''', could be introduced to provide a system for inspecting the value itself: '''`is`''' ''`value1`'' ''`value2`'' : Returns `true` if ''value1'' is the same type of value as as value2, and `false` otherwise. [extension%|%extensions] that provide their own value types could use some implementation-level mechanism to register a function for `is` to use when it encounters values of that type . A [proc%|%procedure] could use `is` to condition its operation on these comparisons. For example, an enhanced `[puts]` procedure might look like this: ====== proc newputs args { set opened 0 if {[llength $args == 1]} { set target [chan lookup stdout] } elseif {[llength $args] == 2} { lassign $args target string if {![is $target [chan type]]} { set target [open $target w] set opened 1 } } try { ::puts $target $string } finally { if {$opened} { close $target } } } ====== `[chan type]` returns a value to be used only by `is`, and not for any real channel operations. For other values such as lists, `[list]` could be used: ====== if {[is $somevariable [list]]} { puts {found a list} } ====== Also needed in the example was `[chan lookup stdout]` which returns the corresponding channel value based on a name. ** To Be Continued ** That's it from now. More to come.