Updated 2017-10-22 17:12:25 by Napier

xk2600 I wanted the ability to provide a constant "keyed" string mechanism (similar to enums) and liked this concept... I need to convert it into a proc which can create these on demand. The premise is simple, dynamically write a proc that contains a switch which based on a single arg returns a result.

Static Constant Enumerated Strings edit

  namespace eval httpd [list proc status {code} {switch -exact -- $code} ]
  foreach {code message} {
    100 Continue
    101 {Switching Protocols}
    102 Processing

    200 OK
    201 Created
    202 Accepted
    203 {Non-Authoritative Information}
    204 {No Content}
    205 {Reset Content}
    206 {Partial Content}
    207 Multi-Status
    208 {Already Reported}
    226 {IM Used}

    300 {Multiple Choices}
    301 {Moved Permenantly}
    302 Found
    303 {See Other}
    304 {Not Modified}
    305 {Use Proxy}
    306 {Switch Proxy}
    307 {Temporary Redirect}
    308 {Permenant Redirect}

    400 {Bad Request}
    401 Unauthorized
    402 {Payment Required}
    403 Forbidden
    404 {Not Found}
    405 {Method Not Allowed}
    406 {Not Acceptable}
    407 {Proxy Authentication Required}
    408 {Request Timeout}
    409 Conflict
    410 Gone
    411 {Length Required}
    412 {Precondition Failed}
    413 {Payload Too Large}
    414 {URI Too Long}
    415 {Unsupported Media Type}
    416 {Range Not Satisfiable}
    417 {Expectation Failed}
    421 {Misdircted Request}
    422 {Unprocessable Entity}
    423 Locked
    424 {Failed Dependancy}
    426 {Upgrade Required}
    428 {Precondition Required}
    429 {Too Many Requests}
    431 {Request Header Fields Too Large}
    451 {Unavailable For Legal Reasons}

    500 {Internal Server Error}
    501 {Not Implemented}
    502 {Bad Gateway}
    503 {Service Unavailable}
    504 {Gateway Time-out}
    505 {HTTP Version Not Supported}
    506 {Variant Also Negotiates}
    507 {Insufficient Storage}
    508 {Loop Detected}
    510 {Not Extended}
    511 {Network Authentication Required}

  } { 
    # This appends case + body onto the switch in the proc body
    # eventually resulting in a proc that looks like this:
    #   proc ::httpd::status {code} {
    #     switch -exact -- $code \
    #       100 { 
    #         return {100 {continue}} 
    #       }                           \
    #       ...
    #       511 {
    #         return {511 {Network Authentication Required}}
    #       }
    #   }
    #
    #  ...and is pretty slick if I say so myself!
    namespace eval httpd [list proc status {code}        \
         [concat [info body ::httpd::status]             \
           $code                                         \
           [list [list return [list $code $message]]]    \
    ]    ]
  }

% ::httpd::status 200
200 OK

Comments, suggestions, improvements welcome.

bll 2017-10-17 Seems complicated. Why not just:
namespace eval httpd {
  variable vars

  set vars(dict.code.msg) {
     100 Continue
  }

  proc status { code } {
    variable vars

    if { [dict exists $vars(dict.code.msg) $code] } {
      return [list $code [dict get $vars(dict.code.msg) $code]]
    }
    # handle future growth
    return [list $code "Code $code"] 
  }
}

Napier 10-17-2017

Hmm, I may be misunderstanding what you are trying to do here but I would also agree that there is more being done here than is really needed.

1. Why not simply a dict at that point? Then you can add to it extremely easily by either accepting a second value to httpd::status or by simply doing a [dict set ::httpd::STATUS_CODES $code $status] (identical to the suggestion above but without arrays as it adds an unnecessary layer in my opinion and would be slower)
namespace eval httpd {
  variable STATUS_CODES {
    100 Continue
  }
  proc status code {
    variable STATUS_CODES
    if {[dict exists $STATUS_CODES $code]} {
      return [list $code [dict get $STATUS_CODES $code]]
    } else {
      return [list $code UNKNOWN]
    }
  }
}

2. Seems like you want something like a var switch. This is also implemented within the varx package as varx::switch
package require varx 

namespace eval httpd {
  proc status code {
    ::varx::switch $code {
      100 Continue
    }
  }
}

18-Oct-2017 change
           [list [list return [list $code $message]]]    \

to
           [list [list return $message]]    \
 to get rid of the redundant code value change and the pesky extra curly brackets.