[VPM] FYI - Muldis D whole app code example

Darren Duncan darren at darrenduncan.net
Fri Apr 24 02:31:18 PDT 2009


Hello,

This message is a follow-up to my post of a couple weeks ago, that showed 
examples of individual Muldis D routine definitions side by side with SQL 
statements (from the SQL::Abstract 2 module docs) whose work they did.

Today's message is a demonstration of the fact that (loosely SQL-alike) Muldis D 
is computationally complete, that you actually could write a standalone program 
in it if you wanted to, though in practice you would just use it for parts of 
programs like you do SQL, which AFAIK is *not* computationally complete.

Below the dashed line in this message is a 3K example program which prompts the 
user to enter the name and address of 3 people, with which it populates a 
(lexical) relvar/table, and then it prompts the user to enter a name to search 
for, and then it searches for and prints out the address that went with that 
name, if it was found, and a not-found message otherwise.

All of the features that this program uses are already specced (see 
http://search.cpan.org/dist/Muldis-D/ ) as usual, but that most of the concrete 
syntax it uses is not formally specced yet.

A few notes:

1.  This demo consists of exactly one program routine, called mymain, which due 
to artifacts of the language's design such as separating pure code from impure 
code (all value literals or value expressions must be in the pure section, while 
all user interaction must be in the impure section), is internally segmented 
into 5 inner routines; in most programming languages that would all just be a 
single routine mixing pure and impure code.  An "updater" is pure (and atomic) 
while a "procedure" is impure.

2.  Declaring the mymain routine requires mounting (analogous to SQL's CONNECT 
TO) a database/depot, named myapp, to store it in (all Muldis D routines are 
stored routines save the bootloader, which is mainly limited to stuffing things 
in a depot and invoking them).  In this case, the depot used is declared 
temporary and so it is just kept in RAM, no disk file being created.  Some other 
time I'll demonstrate using a persisting depot like one would normally use for 
data.  In practice, an application would use 2 depots (each being their own 
namespaces), one persistent for mainly data like a normal database, and one 
possibly temporary for mainly code specific to that app; the example in this 
email is like the latter.

3.  One demonstrated improvement from the last email is that when invoking a 
routine, up to 2 arguments may be passed without names (rather than just one 
shown before), which is one readonly argument and one subject-to-update 
argument, when just one of their respective kinds of parameters exists; they are 
told apart in that subject-to-update are marked with an ampersand and readonly 
doesn't have one.

4.  Unlike the previous emails, this one includes examples of: user I/O (simple 
command line STDIN/OUT), generic if/else expressions, factoring out an 
otherwise-repeated part of a value expression into a named sub-expression 
("matched_people"), and procedural iteration (but most iteration in a Muldis D 
program would be functional).

-- Darren Duncan

----------

Muldis_D:"http://muldis.com":"0.65.0":PTMD_Tiny:bootloader

create depot_mount myapp {
     is_temporary => true
     we_may_update => true
}

within depot myapp create {

#=========================================================================#

procedure mymain () {
     # This is the program's main procedure. #

     main {
         var Text $msg_gather_name
         var Text $msg_gather_addr
         var Text $msg_search_name
         var Text $msg_result_addr
         var Relation $people
         var Text $name
         var Text $addr
         var NNInt $loop_count

         inn.init_vars( &msg_gather_name => $msg_gather_name,
             &msg_gather_addr => $msg_gather_addr,
             &msg_search_name => $msg_search_name,
             &msg_result_addr => $msg_result_addr, &people => $people,
             &loop_count => $loop_count )

         loop $loop_count {
             inn.gather_person( &$people,
                 msg_gather_name => $msg_gather_name,
                 msg_gather_addr => $msg_gather_addr )
         }

         prompt_Text_line( &$name, $msg_search_name )
         inn.search_for_address( &$addr, people => $people, name => $name )
         write_Text( $msg_result_addr )
         write_Text_line( $addr )
     }

     inner_updater init_vars (Text &$msg_gather_name,
             Text &$msg_gather_addr, Text &$msg_search_name,
             Text &$msg_result_addr, Relation &$people,
             NNInt &$loop_count ) {
         # Initializes main routine's variables. #
         $msg_gather_name := 'Enter a person\as name: '
         $msg_gather_addr := 'Enter that person\as address: '
         $msg_search_name := 'Enter a name to search for: '
         $msg_result_addr := 'Found address for that person is: '
         $people := Relation:{ name, addr }
         $loop_count := 3
     }

     inner_procedure gather_person (Relation &$people,
             Text $msg_gather_name, Text $msg_gather_addr) {
         # Gathers person info from user. #
         var Text $name
         var Text $addr
         prompt_Text_line( &$name, $msg_gather_name )
         prompt_Text_line( &$addr, $msg_gather_addr )
         inn.add_person( &$people, name => $name, addr => $addr )
     }

     inner_updater add_person (Relation &$people, Text $name, Text $addr) {
         # Adds a person to our db of people. #
         assign_insertion( &$people,
             Tuple:{ name => $name, addr => $addr } );
     }

     inner_updater search_for_address
             (Text &$addr, Relation $people, Text $name) {
         # Look up person by name, get their address. #
         $matched_people = ($people matching Relation:{ { name => $name } })
         $addr := (
             if ((cardinality of $matched_people) === 1)
                 then ((tuple from $matched_people){A:addr})
             else '<Not Exactly One Person Matched>'
         )
     }
}

#=========================================================================#

} # within depot myapp create #

boot_stmt fed.lib.myapp.mymain()



More information about the Victoria-pm mailing list