@dolist
Description
COMMAND: @dolist[/<switch>] [<delimiter>] <list>=<action>
list is a list of strings, which can be object numbers, attributes, or arbitrary words. action is a command to perform once for each item in list, replacing the special symbol ## with the corresponding item from list, and the symbol #@ with the position in the list, starting with one. By default, @dolist considers each item in list to be separated with spaces. If you specify the /delimit switch, then each item is considered to be separated by delimiter. delimiter must be a single character.
If present, switch can be any of:
- /space - (Default) List elements are separated by spaces.
- /delimit - List elements are separated by delimiter.
- /notify - Queues a '@notify' after all commands in the list.
This command is particularly handy with lcon() and lexits().
@dolist and the Queue
TinyMUX command processing is queue-based. Commands are put on the queue as they are invoked, and they execute in order-- first in, first out (with exceptions for commands entered by players, which always take precedence). This is important to remember, as @dolist, by its nature, is used to invoke one or more additional commands. As mentioned in the discussion of the queue, consider the following:
&trig.saynames me=@dolist lcon(here)=@pemit me=[space(3)][name(##)] &cmd.saynames me=$+saynames:@tr me/trig.saynames;@pemit me=Items In Room: +saynames
While you might expect that you would see the list of names followed by the @pemit, in reality you see the "Items In Room:" header first, followed by the contents of the @dolist. This is because commands are queued as they are executed. In this case when you type +saynames, the @trigger runs and the @dolist is queued as 1, and then the @pemit is queued as 2. The @dolist is executed, and its @pemits are put at the bottom of the queue. The queue moves to the next position and the header is printed. Finally, the queue reaches the @pemits queued by the @dolist, which are then printed accordingly.
As a consequence of this, if you intend to use semaphores in conjunction with @dolist, it is necessary to use the /notify switch. This is because using a @dolist followed by a @notify will result in the @notify executing first, since the contents of the @dolist will end up being queued AFTER the @notify. Using @dolist/notify will automatically queue the notification to happen after the execution of the @dolist has finished.
&list.recitation me=I like|chickens, but|I do not like|cows. &cmd.recite me=$+recite:@wait me=say Done!;@dolist/delimit/notify | [v(list.recitation)]="## +recite >You say, "I like" >You say, "chickens, but" >You say, "I do not like" >You say, "cows." >You say, "Done!"
This works as expected, because each line is queued right away, and an @notify is queued after them.
&trig.command1 me=say I like &trig.command2 me=say chickens, but &trig.command3 me=say I do not like &trig.command4 me=say cows. &cmd.recite me=$+recite:@wait me=say Done!;@dolist/notify [secure(lattr(me/trig.command?))]=@tr/quiet me/## +recite > You say, "Done!" > You say, "I like" > You say, "chickens, but" > You say, "I do not like" > You say, "cows."
This does not work as some might expect. The @dolist queues up all of its @triggers followed by an @notify. As the queue executes, each @trigger puts its command at the end of the queue, then the @notify executes, and then the individual say commands execute.
Examples
- @dolist [lcon(here)] = "[name(##)](##)
- @dolist [lcon(here)] = @switch [get(##/last)]=*1990*,"[name(##)]
- @va me = va vb vc
- @do list [get(me/va)] = @emit [get(me/##)]
- @dolist Frodo Bilbo Gandalf = page ## = HELP!!!! I've fallen into a pit.
- @dolist/delimit , {Frodo, Bilbo Baggins, Gandalf} = page ## = HELP!!!!
- @wait me="This is a semaphore.
- @dolist/notify lnum(3)=say ##
- > You say, "0"
- > You say, "1"
- > You say, "2"
- > You say, "This is a semaphore."
Related Topics
iter(), parse(), @notify, Semaphores, Queue.