Error processing request

Parameters

CONTENT_LENGTH0
REQUEST_METHODGET
REQUEST_URI/revision/Controlling+iteration+in+the+loop+body?V=3
QUERY_STRINGV=3
CONTENT_TYPE
DOCUMENT_URI/revision/Controlling+iteration+in+the+loop+body
DOCUMENT_ROOT/var/www/nikit/nikit/nginx/../docroot
SCGI1
SERVER_PROTOCOLHTTP/1.1
HTTPSon
REMOTE_ADDR172.70.39.98
REMOTE_PORT47446
SERVER_PORT4443
SERVER_NAMEwiki.tcl-lang.org
HTTP_HOSTwiki.tcl-lang.org
HTTP_CONNECTIONKeep-Alive
HTTP_ACCEPT_ENCODINGgzip, br
HTTP_X_FORWARDED_FOR3.81.221.121
HTTP_CF_RAY86bbfa75ca610830-IAD
HTTP_X_FORWARDED_PROTOhttps
HTTP_CF_VISITOR{"scheme":"https"}
HTTP_ACCEPT*/*
HTTP_USER_AGENTclaudebot
HTTP_CF_CONNECTING_IP3.81.221.121
HTTP_CDN_LOOPcloudflare
HTTP_CF_IPCOUNTRYUS

Body


Error

Unknow state transition: LINE -> END

-code

1

-level

0

-errorstack

INNER {returnImm {Unknow state transition: LINE -> END} {}} CALL {my render_wikit {Controlling iteration in the loop body} {mpr 2016-08-19: This proc is a useful little tool for parsing options to a command.
iter acts exactly like a foreach loop, but exposes the [next] command
inside the body of the loop, which jumps the iterating variable to the
next value in the list and returns that value.

======    
proc iter { var list body } {
    coroutine next apply [subst {{} {
        yield
        foreach x {$list} { yield \$x }
        return -code break
    }}]
    
    while 1 {
        uplevel [list set $var [next]]
        uplevel $body
    }
}
======

Here is an example.

Say we want to write a command, scrape, which pulls down
webpages. scrape has a '-o' option which takes a filename to
write the data to, and a '-ssl' option that enables ssl in the
http request. A scrape call that pulls down
www.foo.com/index.html might look like this

    scrape www.foo.com/index.html -o foo.html -ssl

Here's how we can use iter to parse the options to scrape

======
proc scrape { addr args } {
    set outfile [lindex [split $addr /] end]
    set usessl  0

    iter op $args {
        switch $op {
            -o {
                set outfile [next]
            }
            -ssl {
                set usessl 1
            }
        }
    }
        
    # do scraping here
}
======


When the '-o' option is seen, the variable 'outfile' is set to
the [next] element in the list, which is the filename passed
after -o. In our case 'foo.html'. When that iteration finishes,
and iter gets to the top of its loop, it will assign the variable
after 'foo.html' to op. In our case this is '-ssl', which will be
matched and the variable usessl will be set to 1. Theoretically
you can nest loops that keep [next]ing, but I haven't tried that
yet.

-- About a month later... --

Looking over this code now, I think I see how it can be
abstracted another level. We can bundle the call to [iter] and
[switch] inside a command, [argparse]. Then we can write the
above like this.

======
argparse $args {
    -o   { set outfile [next] }
    -ssl { set usessl 1 }
}
======

     
Nice. So what does the argparse command look like?

======
proc argparse { options switch_body } {
    uplevel [subst {iter op $options { switch \$op { $switch_body } }}]
}
======
     
And now we write scrape with the new abstraction

======
proc scrape { addr args } {
    set outfile [lindex [split $addr /] end]
    set usessl  0

    argparse $args {
        -o   { set outfile [next] }
        -ssl { set usessl 1 }
    }
        
    # do scraping here
}} regexp2} CALL {my render {Controlling iteration in the loop body} {mpr 2016-08-19: This proc is a useful little tool for parsing options to a command.
iter acts exactly like a foreach loop, but exposes the [next] command
inside the body of the loop, which jumps the iterating variable to the
next value in the list and returns that value.

======    
proc iter { var list body } {
    coroutine next apply [subst {{} {
        yield
        foreach x {$list} { yield \$x }
        return -code break
    }}]
    
    while 1 {
        uplevel [list set $var [next]]
        uplevel $body
    }
}
======

Here is an example.

Say we want to write a command, scrape, which pulls down
webpages. scrape has a '-o' option which takes a filename to
write the data to, and a '-ssl' option that enables ssl in the
http request. A scrape call that pulls down
www.foo.com/index.html might look like this

    scrape www.foo.com/index.html -o foo.html -ssl

Here's how we can use iter to parse the options to scrape

======
proc scrape { addr args } {
    set outfile [lindex [split $addr /] end]
    set usessl  0

    iter op $args {
        switch $op {
            -o {
                set outfile [next]
            }
            -ssl {
                set usessl 1
            }
        }
    }
        
    # do scraping here
}
======


When the '-o' option is seen, the variable 'outfile' is set to
the [next] element in the list, which is the filename passed
after -o. In our case 'foo.html'. When that iteration finishes,
and iter gets to the top of its loop, it will assign the variable
after 'foo.html' to op. In our case this is '-ssl', which will be
matched and the variable usessl will be set to 1. Theoretically
you can nest loops that keep [next]ing, but I haven't tried that
yet.

-- About a month later... --

Looking over this code now, I think I see how it can be
abstracted another level. We can bundle the call to [iter] and
[switch] inside a command, [argparse]. Then we can write the
above like this.

======
argparse $args {
    -o   { set outfile [next] }
    -ssl { set usessl 1 }
}
======

     
Nice. So what does the argparse command look like?

======
proc argparse { options switch_body } {
    uplevel [subst {iter op $options { switch \$op { $switch_body } }}]
}
======
     
And now we write scrape with the new abstraction

======
proc scrape { addr args } {
    set outfile [lindex [split $addr /] end]
    set usessl  0

    argparse $args {
        -o   { set outfile [next] }
        -ssl { set usessl 1 }
    }
        
    # do scraping here
}}} CALL {my revision {Controlling iteration in the loop body}} CALL {::oo::Obj1174657 process revision/Controlling+iteration+in+the+loop+body} CALL {::oo::Obj1174655 process}

-errorcode

NONE

-errorinfo

Unknow state transition: LINE -> END
    while executing
"error $msg"
    (class "::Wiki" method "render_wikit" line 6)
    invoked from within
"my render_$default_markup $N $C $mkup_rendering_engine"
    (class "::Wiki" method "render" line 8)
    invoked from within
"my render $name $C"
    (class "::Wiki" method "revision" line 31)
    invoked from within
"my revision $page"
    (class "::Wiki" method "process" line 56)
    invoked from within
"$server process [string trim $uri /]"

-errorline

4