Updated 2012-09-10 14:49:22 by LkpPo

Read My Mind And Do What I Mean - a frequently requested functionality

See TIP 131 [1]

RS 2004-07-28 - The RMM part still awaits implementation, but if you transport mind over stdin, here's an initial implementation:
 proc do args {
    puts [uplevel 1 $args]
 }

 proc what {who verb} {
    puts -nonewline "what do you $verb? "
    flush stdout
    uplevel 1 [gets stdin]
 }

 while 1 {do what I mean}

PT 2004-07-29 The division between the functional aspects of RMMADWIM into RMM and a separate DWIM leads me to think about alternative transports than just stdin. The implementation above could trivially be recoded as a network server or even a Web service. Sticking with KISS I consider that the ideal network protocol for the correct transport of DWIM data will be the LOAF protocol. LOAF is unique compared to other network protocols in that everything is specified to just work which is in keeping with the spirit of the RMMADWIM specification.

RS Hm.. but LOAF does nothing, doesn't it? The code above implements at least the classic read-eval-print loop as known from Lisp, or any interactive tclsh... :)

PT No - it may be that LOAF seems to be doing nothing. However, in fact it is doing just what is expected. However, I don't mean that the LOAF protocol should be replacing your read-eval-print loop. Instead I offer the concept of RMMADWIM over LOAF. In the above example stdin would be replaced by a LOAFful stream implementation. In a similar manner we can envisage RMMADWIM/SOAP, or RMMADWIM/BEEP [2] or encapsulation within IP [3] or [BLOAT] [4] datagrams.

Jos Decoster As a first step to implement RMMADWIM, a solve function is required. This will allows us to already solve well defined problems. The mind-reading may be one of the first problems to solve! This skeleton is provided with a BSD license.
 #----------------------------------------------------------------------
 #
 # solve1 --
 #
 #        Solve the specified problem
 #
 # Parameters:
 #        A problem
 #
 # Results:
 #        The solved problem
 #
 # Side effects:
 #        Once implemented this function may cause other problems
 #       - less stress put on developers will decrease the demand of coffee
 #         and as such increase poverty among coffee farmers in third world
 #         countries
 #       - solving problems with this function will decrease the demand for
 #         developers and as such increase the demand for alcohol among 
 #         unemployed developers, which as a side side effect may compensate
 #         for the decreased demand for coffee beans and in the end help
 #         farmers in third world countries after converting the production
 #         to alcohol base products, which leaves the developers problem...
 #
 #----------------------------------------------------------------------
 proc solve1 problem {
     # To be done
 }

 #----------------------------------------------------------------------
 #
 # solve --
 #
 #        Solve the specified problems, based on implementation by 
 #       Richard Suchenwirth found on #tcl
 #
 # Parameters:
 #        A list of problem
 #
 # Results:
 #        A list of solved problems, in the same order as the problems 
 #       were specified
 #
 # Side effects:
 #       See solve1
 #
 # Notes:
 #       Modified following coding style suggested by my first employer
 #       to never use pointers and to never use recursion ('to avoid 
 #       problems'),
 #
 #----------------------------------------------------------------------
 proc solve problems {
     if { [llength $problems] == 0 } {
         return
     }
     set results [list]
     foreach problem $problems {
         lappend results [solve1 $problem]
     }
     return $results
 }

As a test, it is possible to implement solve1 as a general expression solver like this:
 proc solve1 problem {
    return [expr $problem]
 }

And test this with tcltest:
 package require tcltest

 tcltest::test solve1-1 {test solve1 expr implementation} {
     solve1 1+1
 } {2}

 tcltest::test solve1-2 {test solve1 expr implementation} {
     solve1 1-1
 } {0}

 tcltest::test solve-1 {test solve expr implementation} {
     solve [list "1+1" "1-1"]
 } {2 0}

 ::tcltest::cleanupTests

Note this implementation can already be useful in detecting syntax errors:
 solve [list "varible refereces require precding \$"]

This will return the correct answer:
 syntax error in expression "varible refereces require precding $": variable references require preceding $

AM (6 march 2007) I just read in a classic article by Henry Spencer and Geoff Collyer (seach for "#ifdef considered harmful") that it is better to avoid problems than solve them. So, perhaps an alternative to the above is:
    # avoid --
    #      Worker procedure for RMMMADWIM: try to avoid problems at all costs
    # Arguments:
    #      problems       List of problem descriptions
    # Result:
    #      OK
    proc avoid {problems} {
        return OK
    }

DKF: It's important to allow for localization with these things:
  proc avoid {problems {locale C}} {
     if {[string match en_AU* $locale]} {
        return "No worries, mate!"
     }
     return OK
  }

RS: Wouldn't it be more state of the art to write
    package require msgcat
    namespace import msgcat::*
    proc avoid {problems} {
        return [mc OK]
    }

and let the msgcat mechanism sort that out? :^)

MAKR It seems there is one implementation already in the wild: Chuck Norris doesn’t program with a keyboard. He stares the computer down until it does what he wants. [5] - SCNR