This is Info file pm.info, produced by Makeinfo version 1.68 from the input file bigpm.texi.  File: pm.info, Node: Language/Basic/Expression, Next: Language/Basic/Function, Prev: Language/Basic, Up: Module List Package to handle string, numeric, and boolean expressions. *********************************************************** NAME ==== Language::Basic::Expression - Package to handle string, numeric, and boolean expressions. SYNOPSIS ======== See *Note Language/Basic: Language/Basic, for the overview of how the Language::Basic module works. This pod page is more technical. # Given an LB::Token::Group, create an expression I parse it my $exp = new LB::Expression::Arithmetic $token_group; # What's the value of the expression? print $exp->evaluate; # Perl equivalent of the BASIC expression print $exp->output_perl; Expressions are basically the building blocks of Statements, in that every BASIC statement is made up of keywords (like GOTO, TO, STEP) and expressions. So expressions include not just the standard arithmetic and boolean expressions (like 1 + 2), but also lvalues (scalar variables or arrays), functions, and constants. See *Note Language/Basic/Syntax: Language/Basic/Syntax, for details on the way expressions are built. DESCRIPTION =========== BASIC expressions are represented by various objects of subclasses of Language::Basic::Expression. Most LB::Expressions are in turn made up of other LB::Expressions. For example an LBE::Arithmetic may be made up of two LBE::Multiplicative and a "plus". "Atoms" (indivisible LBE's) include things like LBE::Constants and LBE::Lvalues (variables). The LBE hierarchy ----------------- A bunch of LBE subclasses represent various kinds of BASIC expressions. These subclasses closely follow the BASIC syntax diagram. Expressions can be classified in two ways, which are sort of vertical and horizontal. One classification method is what subexpressions (if any) an expression is made of. For example, an Arith. Exp. is made up of one or more Mult. Exps. connected by plus or minus signs, while a Mult. Exp. is made up of one or more Unary Exps. This is a hierarchical (or vertical) distinction, important for building up the tree of objects that represent a BASIC expression. (Note that not all levels in the hierarchy have to be filled. We don't bother making an Arith. Exp. which contains just one Mult. Exp. which contains just one Unary Exp. Instead, we just use the Unary Exp. itself (when it's safe to do so!) The second way of classifying expressions is by their return type. A String Exp. is a string constant, a string variable, a string function, or some other expression whose value when evaluated will be a string. A Numeric Exp. evaluates to a number, and a Boolean to a True or False value. This distinction is important for typechecking and finding syntax errors in BASIC code. (Note that in BASIC - unlike Perl or C - you can't "cast" a boolean value into an integer or string. This actually makes parsing more difficult.) Some expressions don't exactly fit any of these distinctions. For example, an Arglist evaluates to a list of expressions, each of which may be Numeric or Boolean. subclass methods ---------------- Each subclass has (at least) three methods: new The "new" method takes a class and a Token::Group (and possibly some other args). It eats one or more Tokens from it, parsing them, creating a new object of that class I, and setting various fields in that object, which it returns. If the tokens don't match the class, "new" returns undef. If an expression contains just one subexpression often we'll just return the subexpression. So if an Arith. Exp. contains just one Mult. Exp., we'll just return the LBE::Multiplicative object and not an LBE::Arithmetic object. evaluate Actually calculates the value of the expression. For a string or numeric constant or variable, that just means taking the stored value of that object. For other Expressions, you actually need to do math. output_perl Gives a string with the Perl equivalent to a BASIC expression. "1+2" is converted to "1+2", but "A" becomes "$a", "A$" becomes "$a_str", and function calls may be even more complicated. LBE subclasses -------------- The hierarchical list of subclasses follows: Arithmetic An arithmetic expression is a set of multiplicative expressions connected by plus or minus signs. (String expressions can only be connected by plus, which is the BASIC concatenation operator.) Multiplicative a set of unary expressions connected by '*' or '/'. Unary a variable, a function, a string or numeric constant, or an arithmetic expression in parentheses, potentially with a unary minus sign. Constant a string or numeric constant, like "17" or 32.4 Lvalue a settable expression: a variable, X, or one cell in an array, A(17,Q). The "variable" method returns the actual LB::Variable::Scalar object referenced by this Lvalue. Function Either an Intrinsic or a User-Defined function. Arglist a list of arguments to an array or function Logical_Or a set of Logical_And expressions connected by "OR" Logical_And a set of Relational expressions connected by "AND" Relational A relational expression, like "A>B+C", optionally with a NOT in front of it.  File: pm.info, Node: Language/Basic/Function, Next: Language/Basic/Statement, Prev: Language/Basic/Expression, Up: Module List Package to handle user-defined and intrinsic Functions in BASIC. **************************************************************** NAME ==== Language::Basic::Function - Package to handle user-defined and intrinsic Functions in BASIC. SYNOPSIS ======== See *Note Language/Basic: Language/Basic, for the overview of how the Language::Basic module works. This pod page is more technical. A Function can be either an intrinsic BASIC function, like INT or CHR$, or a user-defined function, like FNX (defined with the DEF command). DESCRIPTION =========== The check_args method checks that the right number and type of function arguments were input. The evaluate method actually calculates the value of the function, given certain arguments. The lookup method looks up the function in the function lookup table. The output_perl method returns a string that's the Perl equivalent to the BASIC function. Class Language::Basic::Function::Intrinsic This class handles intrinsic BASIC functions. The initialize method sets up BASIC's supported functions at the beginning of the program. The all-important @Init holds a ref for each function to an array holding: - the function name, - the number and type of arguments (in a Perl function prototype-like style), - a subref that performs the equivalent of the BASIC function, and - a string for the output_perl method. That string is either the name of an equivalent Perl function, like "ord" for BASIC's "ASC", or (if there is no exact equivalent) a BLOCK that performs the same action. Adding intrinsic BASIC functions therefore involves adding to this array. Class Language::Basic::Function::Defined This class handles functions defined by the user in DEF statements.  File: pm.info, Node: Language/Basic/Statement, Next: Language/Basic/Syntax, Prev: Language/Basic/Function, Up: Module List Package to handle parsing and implementing single BASIC statements. ******************************************************************* NAME ==== Language::Basic::Statement - Package to handle parsing and implementing single BASIC statements. SYNOPSIS ======== See *Note Language/Basic: Language/Basic, for the overview of how the Language::Basic module works. This pod page is more technical. A Statement is something like 'GOTO 20' or 'PRINT "HELLO"'. A line of BASIC code is made up of one or more Statements. # Create the statement from an LB::Token::Group and # bless it to an LBS::* subclass my $statement = new Language::Basic::Statement $token_group; $statement->parse; # Parse the statement $statement->implement; # Implement the statement # Return a string containing the Perl equivalent of the statement $str = $statement->output_perl; DESCRIPTION =========== Take a program like: 5 LET A = 2 10 IF A >= 3 THEN GOTO 20 ELSE PRINT "IT'S SMALLER" Line 5 has just one statement. Line 10 actually contains three. The first is an IF statement, but the results of the THEN and the ELSE are entire statements in themselves. Each type of statement in BASIC has an associated LB::Statement class. For example, there's LB::Statement::Let and LB::Statement::If. (But no LB::Statement::Then! Instead the "then" field of the LB::Statement::If object will point to another statement. In the above program, it would point to a LB::Statement::Goto.) Parsing a line of BASIC starts with removing the line number and lexing the line, breaking it into Tokens which are held in an LB::Token::Group. LB::Statement::new, refine, and parse, are all called with a Token::Group argument. These methods gradually "eat" their way through the Tokens. LBS::new simply creates an LBS object. However, it then calls LBS::refine, which looks at the first Token of the command and blesses the object to the correct LBS::* subclass. Each LBS subclass then has (at least) the methods parse, implement, and output_perl. The parse method goes through the text and digests it and sets various fields in the object, which are used by implement and output_perl. The implement method actually implements the BASIC command. The output_perl method returns a string (with ; but not \n at the end) of the Perl equivalent of the BASIC statement.  File: pm.info, Node: Language/Basic/Syntax, Next: Language/Basic/Token, Prev: Language/Basic/Statement, Up: Module List Pod file describing syntax understood by Language::Basic module *************************************************************** NAME ==== Syntax - Pod file describing syntax understood by Language::Basic module SYNOPSIS ======== There is no Language::Basic::Syntax module. This is just a pod file describing the syntax that's supported by the Language::Basic module. DESCRIPTION =========== Things in *italics* are objects. Things in *boldface* are actual strings (reserved words or punctuation). "[]" means optional, "..." means optionally more copies of the same thing, and things between slashes that look like Perl regexps are Perl regexps. This syntax description probably isn't exactly correct from a computer science standpoint, but the idea is just to show what LB supports. Line Syntax ----------- Line: *Line_Num* Statement [: Statement ...] Statement Syntax ---------------- * DATA Constant [ *,* Constant ...] * DIM *Var-Name* [ Arglist ] [ *,* *Var-Name* [ Arglist ] ...] Arglist must be made up of constant arithmetic expressions. * DEF *Func-Name* ( *Var-Name* [ *,* *Var-Name* ...] ) = *Arith-Exp* *Var-Name*s must be scalar variables. * END * FOR Lvalue = *Arith-Exp* TO *Arith-Exp* [ *STEP* *Arith-Exp*] * GOTO *Arith-Exp* * IF *Or-Exp* *THEN* Statement [ : Statement ...] [ ELSE Statement [ : Statement ...]] IF *Or-Exp* *THEN* *Line_Num* [ ELSE *Line_Num* ] * INPUT [ *Str-Const* *;* ] Lvalue [ *,* Lvalue ...] * [LET] Lvalue = *Arith-Exp* * NEXT Lvalue * ON *Arith-Exp* GOTO/GOSUB *Arith-Exp* [ *,* *Arith-Exp* ...] * PRINT [ Expression [ *Print_Sep* ] [ Expression [ *Print_Sep* ] ...] ] * READ Lvalue [ *,* Lvalue ...] * Comment Expression Syntax ----------------- Note that, unlike C or Perl, Boolean values cannot be "cast" to non-Boolean (string or numeric) values and vice versa. By the way, the classes in module Language::Basic::Expression rather closely mimic this syntax description. Expression: *Arith-Exp* *Or-Exp* *Arithmetic Expression*: *Mult-Exp* *Arith-Op* *Mult-Exp* *String-Exp* + *String-Exp* *Multiplicative Expression*: *Unary-Exp* *Mult-Op* *Unary-Exp* *Unary Expression*: - *Unary-Exp* (*Arith-Exp*) Lvalue Function Constant Lvalue: *Var-Name* [ Arglist ] Arglist: ( Expression [ *,* Expression ...] ) Function: *Func-Name* Arglist Constant: *Str-Const* *Num-Const* *String Expression*: *Str-Const* *Arith-Exp* The *Arith-Exp* must be made from *Str-Exp*s. *Logical Or Expression*: *And-Exp* [ *OR* *Or-Exp* ] *Logical And Expression*: *Rel-Exp* [ AND *And-Exp* ] *Relational Expression*: *NOT* *Rel-Exp* *Arith-Exp* *Rel-Op* *Arith-Exp* *String-Exp* *Rel-Op* *String-Exp* ( *Or-Exp* ) Identifier Syntax ----------------- *Variable Name*: *Numeric Identifier* *String Identifier* *Function Name*: /FN[A-Z]\w+/ *Numeric Identifier*: /[A-Z]\w*/ *String Identifier*: /[A-Z]\w*\$/ Token Syntax ------------ Tokens, or atoms, are indivisible pieces of text making up a BASIC program (Note: Language::Basic only pays attention to case in string constants.) *Line Number*: /\d+/ Comment: REM /.*/ Note that a comment goes all the way to the end of a line. Colons in a comment do not start a new statement. Keyword: DATA | DIM | DEF | END | FOR | GOSUB | GOTO | IF | INPUT | LET | NEXT | ON | PRINT | READ | RETURN | *THEN* | ELSE | TO | *STEP* *Numeric Constant*: /(\d*)?\.?\d+/ *String Constant*: /".*?"/ *Relational Operator*: *<* | *<=* | *>* | *>=* | = | *<>* *Arithmetic Operator*: + | - *Multiplicative Operator*: * | / *Print Separator*: *,* | *;*  File: pm.info, Node: Language/Basic/Token, Next: Language/Basic/Variable, Prev: Language/Basic/Syntax, Up: Module List Module to handle lexing BASIC statements. ***************************************** NAME ==== Language::Basic::Token - Module to handle lexing BASIC statements. SYNOPSIS ======== See *Note Language/Basic: Language/Basic, for the overview of how the Language::Basic module works. This pod page is more technical. # lex a line of basic into a bunch of tokens. my $token_group = new Language::Basic::Token::Group; $token_group->lex('PRINT "YES","NO" : A=A+1'); # Look at tokens my $tok = $token_group->lookahead && print $tok->text; # Eat expected tokens my $tok = $token_group->eat_if_string(","); my $tok = $token_group->eat_if_class("Keyword"); DESCRIPTION =========== BASIC tokens are pretty simple. They include Keywords, Identifiers (Variable or Function names), String and Numeric Constants, and a few one- or two-character operators, like ':' and '<='. Tokens aren't very ambiguous, so for example, you don't need to know what type of Statement you're looking at in order to lex a line of BASIC. (The only remotely ambiguous thing is that '=' can be either a Relational Operator or an Assignment statement.) The subclasses of LB::Token represent the various sorts of tokens. The Token::Group class isn't really a subclass at all; it's a group of tokens. See `"Language::Basic::Token::Group"' in this node for more info. The "text" method returns the text that makes up the token. Note that text is stored in upper case (except for string constants, which are stored exactly as entered). class Language::Basic::Token::Group ----------------------------------- This important class handles a group of tokens. Text from the BASIC program is lexed and turned into LB::Tokens which are stored in a Token::Group. Any access to these Tokens (including creating them) is through the Token::Group methods. Other classes' parse methods will usually eat their way through the tokens in the Token::Group until it's empty. new This method just creates a new LBT::Group. lex This method breaks BASIC text arg1 into LB::Tokens and puts them in Token::Group arg0. lookahead This method returns the next token in the Token::Group without removing it from the group. That means lookahead can be called many times and keep getting the same token (as long as eat is never called). It returns undef if there are no more Tokens left. eat This method eats the next Token from the Token::Group and returns it. It returns undef if there are no more Tokens left. eat_if_string This method eats the next token from Group arg0 if it matches string arg1 If it ate a token, it returns it. Otherwise (or if there are no tokens left) it returns undef. Note that the string to match should be upper case, since all \w tokens are stored as uppercase. eat_if_class This method eats the next token from Group arg0 if the token is of class "Language::Basic::Token::" . arg1. (I.e., it's called with "Keyword" to get a Language::Basic::Token::Keyword Token.) If it ate a token, it returns it. Otherwise (or if there are no tokens left) it returns undef. slurp Eats tokens from Group arg1 and puts them in Group arg0 until it gets to a Token whose text matches string arg2 or it reaches the end of arg1. (The matching Token is left in arg1.) stuff_left Returns true if there's stuff left in the Statement we're parsing (i.e. if there are still tokens left in the Token::Group and the next token isn't a colon) print For debugging purposes. Returns the Tokens in Group arg0 nicely formatted. Other Language::Basic::Token subclasses --------------------------------------- The other subclasses are actually kinds of Tokens, unlike Token::Group. There are no "new" methods for these classes. Creation of Tokens is done by Token::Group::lex. In fact, these classes don't have any public methods. They're mostly there to use "isa" on. Keyword A BASIC keyword (reserved word) Identifier An Identifier matches /[A-Z][A-Z0-9]*\$?/. It's a variable or function name. String_Constant Stuff inside double quotes. Numeric_Constant A float (or integer, currently) Left_Paren A "(" Right_Paren A ")" Separator Comma or semicolon (separators in arglists, PRINT statements) Arithmetic_Operator Plus or minus Multiplicative_Operator Multiply or divide operators ('*' and '/') Relational_Operator Greater than, less than, equals, and their combinations. Note that equals sign is also used to assign values in BASIC. Logical_Operator AND, OR, NOT Comment REM statement (includes the whole rest of the line, even if there are colons in it) Statement_End End of a statement (i.e., a colon)  File: pm.info, Node: Language/Basic/Variable, Next: Language/Functional, Prev: Language/Basic/Token, Up: Module List Module to handle parsing and implementing BASIC variables. ********************************************************** NAME ==== Language::Basic::Variable - Module to handle parsing and implementing BASIC variables. SYNOPSIS ======== See *Note Language/Basic: Language/Basic, for the overview of how the Language::Basic module works. This pod page is more technical. There are two sorts of variables: Arrays and Scalars. Each of those classes has a subclass for Numeric or String variables. DESCRIPTION =========== An Array needs to have full LBV::Scalar objects in it, rather than just having an array of values. The reason is that, for example, you might use ARR(3) as the variable in a FOR loop. Also, the "set" and "value" methods apply to a LBV::Scalar (since you can't set an array to a value (in BASIC :)) so in order to be handle A(3)=3, A(3) needs to be an LBV::Scalar. The lookup method looks up a variable in the Array or Scalar lookup table (depending on whether there were parentheses after the variable name). BASIC allows undeclared variables, so if the variable name hasn't been seen before, a new variable is created. Language::Basic::Variable::Scalar class --------------------------------------- This class handles a variable or one cell in an array. Methods include "value", which gets the variable's value, and "set", which sets it. Language::Basic::Variable::Array class -------------------------------------- This class handles a BASIC array. Each cell in the array is a LBV::Scalar object. Methods include "dimension", which dimensions the array to a given size (or a default size) and get_cell, which returns the LBV::Scalar object in a given array location. Note that BASIC arrays start from 0!  File: pm.info, Node: Language/Functional, Next: Language/Mumps, Prev: Language/Basic/Variable, Up: Module List a module which makes Perl slightly more functional ************************************************** NAME ==== Language::Functional - a module which makes Perl slightly more functional SYNOPSIS ======== use Language::Functional ':all'; print 'The first ten primes are: ', show(take(10, filter { prime(shift) } integers)), "\n"; DESCRIPTION =========== Perl already contains some functional-like functions, such as map and grep. The purpose of this module is to add other functional-like functions to Perl, such as foldl and foldr, as well as the use of infinite lists. Think as to how you would express the first ten prime numbers in a simple way in your favourite programming language? So the example in the synopsis is a killer app, if you will (until I think up a better one ;-). The idea is mostly based on Haskell, from which most of the functions are taken. There are a couple of major omissions: currying and types. Lists (and tuples) are simply Perl list references, none of this 'cons' business, and strings are simple strings, not lists of characters. The idea is to make Perl slightly more functional, rather than completely replace it. Hence, this slots in very well with whatever else your program may be doing, and is very Perl-ish. Other modules are expected to try a much more functional approach. FUNCTIONS ========= The following functions are available. (Note: these should not be called as methods). In each description, I shall give the Haskell definition (if I think it would help) as well as a useful example. show Show returns a string representation of an object. It does not like infinite lists. inc k Increases the value passed by 1. $x = inc 2; # 3 In Haskell: inc :: a -> a inc k = 1 + k double k Doubles the passed value. $x = double 3; # 6 In Haskell: double :: a -> a double k = k * 2 square k Returns the square of the passed value. eg: $x = square 3; # 9 In Haskell: square :: a -> a square k = k * k gcd x y Returns the greatest common denominator of two numbers. eg: $x = gcd(144, 1024); # 16 In Haskell: gcd :: Integral a => a -> a -> a gcd 0 0 = error "gcd 0 0 is undefined" gcd x y = gcd' (abs x) (abs y) where gcd' x 0 = x gcd' x y = gcd' y (x `rem` y) lcm x y Returns the lowest common multiple of two numbers. eg: $x = lcm(144, 1024); # 9216 In Haskell: lcm :: (Integral a) => a -> a -> a lcm _ 0 = 0 lcm 0 _ = 0 lcm x y = abs ((x `quot` gcd x y) * y) id x The identity function - simply returns the argument. eg: $x = id([1..6]); # [1, 2, 3, 4, 5, 6]. In Haskell: id :: a -> a id x = x const k _ Returns the first argument of 2 arguments. eg: $x = const(4, 5); # 4 In Haskell: const :: a -> b -> a const k _ = k flip f Given a function, flips the two arguments it is passed. Note that this returns a CODEREF, as currying does not yet happen. eg: flip(sub { $_[0] ** $_[1] })->(2, 3) = 9. In Haskell (ie this is what it should really do): flip :: (a -> b -> c) -> b -> a -> c flip f x y = f y x Until p f x Keep on applying f to x until p(x) is true, and then return x at that point. eg: $x = Until { shift() % 10 == 0 } \&inc, 1; # 10 In Haskell: until :: (a -> Bool) -> (a -> a) -> a -> a until p f x = if p x then x else until p f (f x) fst x:xs Returns the first element in a tuple. eg: $x = fst([1, 2]); # 1 In Haskell: fst :: (a,b) -> a fst (x,_) = x snd x:y:xs Returns the second element in a tuple. eg: $x = snd([1, 2]); # 2 In Haskell: snd :: (a,b) -> a snd (_,y) = y head xs Returns the head (first element) of a list. eg: $x = head([1..6]); # 1 In Haskell: head :: [a] -> a head (x:_) = x Last xs Returns the last element of a list. Note the capital L, to make it distinct from the Perl 'last' command. eg: $x = Last([1..6]); # 6 In Haskell: last :: [a] -> a last [x] = x last (_:xs) = last xs tail xs Returns a list minus the first element (head). eg: $x = tail([1..6]); # [2, 3, 4, 5, 6] In Haskell: tail :: [a] -> [a] tail (_:xs) = xs init xs Returns a list minus its last element. eg: $x = init([1..6]); # [1, 2, 3, 4, 5] In Haskell: init :: [a] -> [a] init [x] = [] init (x:xs) = x : init xs null xs Returns whether or not the list is empty. eg: $x = null([1, 2]); # False In Haskell: null :: [a] -> Bool null [] = True null (_:_) = False Map f xs Evaluates f for each element of the list xs and returns the list composed of the results of each such evaluation. It is very similar to the Perl command 'map', hence the capital M, but also copes with infinite lists. eg: $x = Map { double(shift) } [1..6]; # [2, 4, 6, 8, 10, 12] In Haskell: map :: (a -> b) -> [a] -> [b] map f xs = [ f x | x <- xs ] filter p xs Returns the list of the elements in xs for which p(xs) returns true. It is similar to the Perl command 'grep', but it also copes with infinite lists. eg: $x = filter(\&even, [1..6]); # [2, 4, 6] In Haskell: filter :: (a -> Bool) -> [a] -> [a] filter p xs = [ x | x <- xs, p x ] concat Concatenates lists together into one list. eg: concat([[1..3], [4..6]]); # [1, 2, 3, 4, 5, 6] In Haskell: concat :: [[a]] -> [a] concat = foldr (++) [] TODO: Make sure this works with infinite lists! Length Returns the length of a list - only do this with finite lists! eg: $x = Length([1..6]); # 6 In Haskell: length :: [a] -> Int length = foldl' (\n _ -> n + 1) 0 TODO Make sure this works! foldl f z xs Applies function f to the pairs (z, xs[0]), (f(z, xs[0], xs[1]), (f(f(z, xs[0], xs[1])), xs[2]) and so on. ie it folds from the left and returns the last value. Note that foldl should not be done to infinite lists. eg: the following returns the sum of 1..6: $x = foldl { shift() + shift() } 0, [1..6]; # 21 In Haskell: foldl :: (a -> b -> a) -> a -> [b] -> a foldl f z [] = z foldl f z (x:xs) = foldl f (f z x) xs foldl1 f xs This is a variant of foldl where the first value of xs is taken as z. Applies function f to the pairs (xs[0], xs[1]), (f(xs[0], xs[1], xs[2]), (f(f(xs[0], xs[1], xs[2])), xs[3]) and so on. ie it folds from the left and returns the last value. Note that foldl should not be done to infinite lists. eg: the following returns the sum of 1..6: $x = foldl1 { shift() + shift() } [1..6]; # 21 In Haskell: foldl1 :: (a -> a -> a) -> [a] -> a foldl1 f (x:xs) = foldl f x xs scanl f q xs Returns a list of all the intermedia values that foldl would compute. ie returns the list z, f(z, xs[0]), f(f(z, xs[0]), xs[1]), f(f(f(z, xs[0]), xs[1]), xs[2]) and so on. eg: $x = scanl { shift() + shift() }, 0, [1..6]; # [0, 1, 3, 6, 10, 15, 21] In Haskell: scanl :: (a -> b -> a) -> a -> [b] -> [a] scanl f q xs = q : (case xs of [] -> [] x:xs -> scanl f (f q x) xs) scanl1 f xs This is a variant of scanl where the first value of xs is taken as q. Returns a list of all the intermedia values that foldl would compute. ie returns the list f(xs[0], xs[1]), f(f(xs[0], xs[1]), xs[2]), f(f(f(xs[0], xs[1]), xs[2]), xs[3]) and so on. eg: $x = scanl1 { shift() + shift() } [1..6]; # [1, 3, 6, 10, 15, 21] In Haskell: scanl1 :: (a -> a -> a) -> [a] -> [a] scanl1 f (x:xs) = scanl f x xs foldr f z xs This is similar to foldl but is folding from the right instead of the left. Note that foldr should not be done to infinite lists. eg: the following returns the sum of 1..6 $x = foldr { shift() + shift() } 0, [1..6] ; # 21 In Haskell: foldr :: (a -> b -> b) -> b -> [a] -> b foldr f z [] = z foldr f z (x:xs) = f x (foldr f z xs) foldr1 f xs This is similar to foldr1 but is folding from the right instead of the left. Note that foldr1 should not be done on infinite lists. eg: $x = foldr1 { shift() + shift() } [1..6]; # 21 In Haskell: foldr1 :: (a -> a -> a) -> [a] -> a foldr1 f [x] = x foldr1 f (x:xs) = f x (foldr1 f xs) scanr f z xs This is similar to scanl but is scanning and folding from the right instead of the left. Note that scanr should not be done on infinite lists. eg: $x = scanr { shift() + shift() } 0, [1..6]; # [0, 6, 11, 15, 18, 20, 21] In Haskell: scanr :: (a -> b -> b) -> b -> [a] -> [b] scanr f q0 [] = [q0] scanr f q0 (x:xs) = f x q : qs where qs@(q:_) = scanr f q0 xs scanr1 f xs This is similar to scanl1 but is scanning and folding from the right instead of the left. Note that scanr1 should not be done on infinite lists. eg: $x = scanr1 { shift() + shift() } [1..6]; # [6, 11, 15, 18, 20, 21] In Haskell: scanr1 :: (a -> a -> a) -> [a] -> [a] scanr1 f [x] = [x] scanr1 f (x:xs) = f x q : qs where qs@(q:_) = scanr1 f xs iterate f x This returns the infinite list (x, f(x), f(f(x)), f(f(f(x)))...) and so on. eg: $x = take(8, iterate { shift() * 2 } 1); # [1, 2, 4, 8, 16, 32, 64, 128] In Haskell: iterate :: (a -> a) -> a -> [a] iterate f x = x : iterate f (f x) repeat x This returns the infinite list where all elements are x. eg: $x = take(4, repeat(42)); # [42, 42, 42, 42]. In Haskell: repeat :: a -> [a] repeat x = xs where xs = x:xs replicate n x Returns a list containing n times the element x. eg: $x = replicate(5, 1); # [1, 1, 1, 1, 1] In Haskell: replicate :: Int -> a -> [a] replicate n x = take n (repeat x) take n xs Returns a list containing the first n elements from the list xs. eg: $x = take(2, [1..6]); # [1, 2] In Haskell: take :: Int -> [a] -> [a] take 0 _ = [] take _ [] = [] take n (x:xs) | n>0 = x : take (n-1) xs take _ _ = error "Prelude.take: negative argument" drop n xs Returns a list containing xs with the first n elements missing. eg: $x = drop(2, [1..6]); # [3, 4, 5, 6] In Haskell: drop :: Int -> [a] -> [a] drop 0 xs = xs drop _ [] = [] drop n (_:xs) | n>0 = drop (n-1) xs drop _ _ = error "Prelude.drop: negative argument" splitAt n xs Splits the list xs into two lists at element n. eg: $x = splitAt(2, [1..6]);# [[1, 2], [3, 4, 5, 6]] In Haskell: splitAt :: Int -> [a] -> ([a], [a]) splitAt 0 xs = ([],xs) splitAt _ [] = ([],[]) splitAt n (x:xs) | n>0 = (x:xs',xs'') where (xs',xs'') = splitAt (n-1) xs splitAt _ _ = error "Prelude.splitAt: negative argument" takeWhile p xs Takes elements from xs while p(that element) is true. Returns the list. eg: $x = takeWhile { shift() <= 4 } [1..6]; # [1, 2, 3, 4] In Haskell: takeWhile :: (a -> Bool) -> [a] -> [a] takeWhile p [] = [] takeWhile p (x:xs) | p x = x : takeWhile p xs | otherwise = [] dropWhile p xs Drops elements from the head of xs while p(that element) is true. Returns the list. eg: $x = dropWhile { shift() <= 4 } [1..6]; # [5, 6] In Haskell: dropWhile :: (a -> Bool) -> [a] -> [a] dropWhile p [] = [] dropWhile p xs@(x:xs') | p x = dropWhile p xs' | otherwise = xs span p xs Splits xs into two lists, the first containing the first few elements for which p(that element) is true. eg: $x = span { shift() <= 4 }, [1..6]; # [[1, 2, 3, 4], [5, 6]] In Haskell: span :: (a -> Bool) -> [a] -> ([a],[a]) span p [] = ([],[]) span p xs@(x:xs') | p x = (x:ys, zs) | otherwise = ([],xs) where (ys,zs) = span p xs' break p xs Splits xs into two lists, the first containing the first few elements for which p(that element) is false. eg: $x = break { shift() >= 4 }, [1..6]; # [[1, 2, 3], [4, 5, 6]] In Haskell: break :: (a -> Bool) -> [a] -> ([a],[a]) break p = span (not . p) lines s Breaks the string s into multiple strings, split at line boundaries. eg: $x = lines("A\nB\nC"); # ['A', 'B', 'C'] In Haskell: lines :: String -> [String] lines "" = [] lines s = let (l,s') = break ('\n'==) s in l : case s' of [] -> [] (_:s'') -> lines s'' words s Breaks the string s into multiple strings, split at whitespace boundaries. eg: $x = words("hey how random"); # ['hey', 'how', 'random'] In Haskell: words :: String -> [String] words s = case dropWhile isSpace s of "" -> [] s' -> w : words s'' where (w,s'') = break isSpace s' unlines xs Does the opposite of unlines, that is: joins multiple strings into one, joined by newlines. eg: $x = unlines(['A', 'B', 'C']); # "A\nB\nC"; In Haskell: unlines :: [String] -> String unlines = concatMap (\l -> l ++ "\n") (note that strings in Perl are not lists of characters, so this approach will not actually work...) unwords ws Does the opposite of unwords, that is: joins multiple strings into one, joined by a space. eg: $x = unwords(["hey","how","random"]); # 'hey how random' In Haskell: unwords :: [String] -> String unwords [] = [] unwords ws = foldr1 (\w s -> w ++ ' ':s) ws Reverse xs Returns a list containing the elements of xs in reverse order. Note the capital R, so as not to clash with the Perl command 'reverse'. You should not try to Reverse an infinite list. eg: $x = Reverse([1..6]); # [6, 5, 4, 3, 2, 1] In Haskell: reverse :: [a] -> [a] reverse = foldl (flip (:)) [] And xs Returns true if all the elements in xs are true. Returns false otherwise. Note the capital A, so as not to clash with the Perl command 'and'. You should not try to And an infinite list (unless you expect it to fail, as it will short-circuit). eg: $x = And([1, 1, 1]); # 1 In Haskell: and :: [Bool] -> Bool and = foldr (&&) True Or xs Returns true if one of the elements in xs is true. Returns false otherwise. Note the capital O, so as not to clash with the Perl command 'or'. You may try to Or an infinite list as it will short-circuit (unless you expect it to fail, that is). eg: $x = Or([0, 0, 1]); # 1 In Haskell: or :: [Bool] -> Bool or = foldr (||) False any p xs Returns true if one of p(each element of xs) are true. Returns false otherwise. You should not try to And an infinite list (unless you expect it to fail, as it will short-circuit). eg: $x = any { even(shift) } [1, 2, 3]; # 1 In Haskell: any :: (a -> Bool) -> [a] -> Bool any p = or . map p all p xs Returns true if all of the p(each element of xs) is true. Returns false otherwise. You may try to Or an infinite list as it will short-circuit (unless you expect it to fail, that is). eg: $x = all { odd(shift) } [1, 1, 3]; # 1 In Haskell: all :: (a -> Bool) -> [a] -> Bool all p = and . map p elem x xs Returns true is x is present in xs. You probably should not do this with infinite lists. Note that this assumes x and xs are numbers. eg: $x = elem(2, [1, 2, 3]); # 1 In Haskell: elem :: Eq a => a -> [a] -> Bool elem = any . (==) notElem x xs Returns true if x is not present in x. You should not do this with infinite lists. Note that this assumes that x and xs are numbers. eg: $x = notElem(2, [1, 1, 3]); # 1 In Haskell: notElem :: Eq a => a -> [a] -> Bool notElem = all . (/=) lookup key xys This returns the value of the key in xys, where xys is a list of key, value pairs. It returns undef if the key was not found. You should not do this with infinite lists. Note that this assumes that the keys are strings. eg: $x = lookup(3, [1..6]); # 4 In Haskell: lookup :: Eq a => a -> [(a,b)] -> Maybe b lookup k [] = Nothing lookup k ((x,y):xys) | k==x = Just y | otherwise = lookup k xys TODO: Make sure this works with infinite lists minimum xs Returns the minimum value in xs. You should not do this with a infinite list. eg: $x = minimum([1..6]); # 1 In Haskell: minimum :: Ord a => [a] -> a minimum = foldl1 min maximum xs Returns the maximum value in xs. You should not do this with an infinite list. eg: maximum([1..6]) = 6. In Haskell: maximum :: Ord a => [a] -> a maximum = foldl1 max sum xs Returns the sum of the elements of xs. You should not do this with an infinite list. eg: sum([1..6]) = 21. In Haskell: sum :: Num a => [a] -> a sum = foldl' (+) 0 product xs Returns the products of the elements of xs. You should not do this with an infinite list. eg: product([1..6]) = 720. In Haskell: product :: Num a => [a] -> a product = foldl' (*) 1 zip as bs Zips together two lists into one list. Should not be done with infinite lists. eg: zip([1..6], [7..12]) = [1, 7, 2, 8, 3, 9, 4, 10, 5, 11, 6, 12]. In Haskell: zip :: [a] -> [b] -> [(a,b)] zip = zipWith (\a b -> (a,b)) zipWith :: (a->b->c) -> [a]->[b]->[c] zipWith z (a:as) (b:bs) = z a b : zipWith z as bs zipWith _ _ _ = [] zip3 as bs cs Zips together three lists into one. Should not be done with infinite lists. eg: zip3([1..2], [3..4], [5..6]) = [1, 3, 5, 2, 4, 6]. In Haskell: zip3 :: [a] -> [b] -> [c] -> [(a,b,c)] zip3 = zipWith3 (\a b c -> (a,b,c)) zipWith3 :: (a->b->c->d) -> [a]->[b]->[c]->[d] zipWith3 z (a:as) (b:bs) (c:cs) = z a b c : zipWith3 z as bs cs zipWith3 _ _ _ _ = [] unzip abs Unzips one list into two. Should not be done with infinite lists. eg: unzip([1,7,2,8,3,9,4,10,5,11,6,12]) = ([1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12]). unzip :: [(a,b)] -> ([a],[b]) unzip = foldr (\(a,b) ~(as,bs) -> (a:as, b:bs)) ([], []) unzip abcs Unzips one list into three. Should not be done with infinite lists. eg: unzip3([1,3,5,2,4,6]) = ([1, 2], [3, 4], [5, 6]). In Haskell: unzip3 :: [(a,b,c)] -> ([a],[b],[c]) unzip3 = foldr (\(a,b,c) ~(as,bs,cs) -> (a:as,b:bs,c:cs)) ([],[],[]) integers A useful function that returns an infinite list containing all the integers. eg: integers = (1, 2, 3, 4, 5, ...). factors x A useful function that returns the factors of x. eg: factors(100) = [1, 2, 4, 5, 10, 20, 25, 50, 100]. In Haskell: factors x = [n | n <- [1..x], x `mod` n == 0] prime x A useful function that returns, rather unefficiently, if x is a prime number or not. It is rather useful while used as a filter, eg: take(10, filter("prime", integers)) = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]. In Haskell: primes = [n | n <- [2..], length (factors n) == 2] AUTHOR ====== Leon Brocard <`acme@astray.com'> COPYRIGHT ========= Copyright (C) 1999, Leon Brocard This module is free software; you can redistribute it or modify it under the same terms as Perl itself.  File: pm.info, Node: Language/Mumps, Next: Language/XS, Prev: Language/Functional, Up: Module List SYNOPSIS ======== use Language::Mumps; $pcode = Language::Mumps::compile(qq{\tw "Hello world!",!\n\th}); eval $pcode; Language::Mumps::evaluate(qq{\ts x=1 w x}); Language::Mumps::interprete("example.mps"); Mumps:translate("example.mps", "example.pl"); *prompt %* `perl example.pl' DESCRIPTION =========== This module compiles Mumps code to Perl code. The API is simillar to MumpsVM. ENVIRONMENT =========== Edit ~/.pmumps or /etc/pmumps to set up persistent arrays. FILES ===== `$BINDIR/pmumps' Interpreter `~/.pmumps' User configuration `/etc/pmumps.cf' Site configuration AUTHOR ====== Ariel Brosh, *schop@cpan.org* SEE ALSO ======== `pmumps' in this node, *Note DB_File: DB_File,.  File: pm.info, Node: Language/XS, Next: Lib/Browser, Prev: Language/Mumps, Up: Module List Write XS code on the fly and load it dynamically. ************************************************* NAME ==== Language::XS - Write XS code on the fly and load it dynamically. SYNOPSIS ======== use Language::XS; DESCRIPTION =========== This module allows C & XS-code creation "on-the-fly", i.e. while your script is running. Here is a very simple example: # create a Language::XS-object my $xs = new Language::XS cachedir => undef; # add plain C to the header $xs->hdr("#include "); # add a c function (not using xs syntax) $xs->cfun('printf ("I was called with %d arguments\n", items);'); # now compile and find the code-reference my $coderef = $xs->find; # Now call it $coderef->(1, "Zwei", 1/3); METHODS ======= new attr => value, ... ---------------------- Creates a new Language::XS object. Known attributes are: id a unique id that woill be shared among all modules cachedir the common directory where shared objects should be cached. set to undef when you want to disable sharing (must be an absolute path) Default values will be supplied when necessary. Two common idioms are: $xs = new Language::XS; # caching enabled $xs = new Language::XS cachedir => undef; # caching disabled cached ------ Returns true when as shared object with the given id already exists. This obviously only makes sense when you gave the module a unique id. hdr sourcecode, [id] -------------------- Add `sourcecode' to the header portion. Similar to the header portion of an XS module, you can insert any valid C-code here. Most often you'd add some include directives, though. id can be used to identify this portion (for error messages). cfun functionbody, [id], [prototype] ------------------------------------ Adds a XS function whose body is given in `functionbody'. Unlike XS, you have to do argument processing (i.e. fiddling with `ST(0)') yourself. id specifies the function name (for `find()' or error messages), and can be omitted (which results in a default name). prototype is an optional string that specifies the perl protoype. Remember that only the parser will evaluate prototypes. xsfun xs-source --------------- Similar to `cfun', but is able to parse normal XS syntax (most of it, that is). Pity that I haven't yet implemented this function, since that would require serious recoding of xsubpp. uselib lib... ------------- Link against all the libraries given as arguments. The libraries should be specified as strings of the form `-llibrary'. Additional search paths can be given using `-L/path/to/libs'. See *Note ExtUtils/Liblist: ExtUtils/Liblist,. incpath path... --------------- Add additional include paths. These paths are prepended to the other include paths. gen --- Create the shared object file. This method is called automatically by load and even by find. This function returns a truth status and fills the messages attribute (see messages) with any compiler/linker warnings or errors. messages -------- Returns the compiler messages (created & updated by gen). load ---- Tries to load the shared object, generating it if necessary. Returns a truth status. find [id] --------- Find the function (either xs or c) with id id and return a code-ref to it. If id is omitted, the default function (see `cfun') is returned instead. If no shared object is loaded, calls load. BUGS/PROBLEMS ============= Requires a C compiler (or even worse: the same C compiler perl was compiled with). Does (most probably) not work on many os's, especially non-unix ones. You cannot yet use normal XS syntax. Line number handling could be better. AUTHOR ====== Marc Lehmann . SEE ALSO ======== perl(1).  File: pm.info, Node: Lib/Browser, Next: Lib/Module, Prev: Language/XS, Up: Module List Perl library browser. ********************* NAME ==== Tk::Browser.pm - Perl library browser. SYNOPSIS ======== # Call from a shell prompt: # browser # Open a library file by name # browser # Open a package(s) matching # (Unix specific); # browser # Browse the entire library. # Call from a Perl Script: use Tk::Browser; use Lib::Module; # Construct Browser object: $b = new Browser; # Browse entire library: $b -> open(); # Browse a package by name: $b -> open(package => IO::File); # Browse a package by module path name: $b -> open(pathname =>"/usr/local/lib/perl5/5.6.0/open.pm"); DESCRIPTION =========== Tk::Browser.pm creates a library browser for Perl modules. A browser has three sub-windows, a module listing at the upper left, a symbol listing at the upper right, and a text display in the bottom half of the browser main window. The Tk::Browser.pm module contains mainly the window and user interface code. The Lib:: modules, included in the distribution archive, do the actual scanning of the library files and keep track of symbol reference information. Clicking with the left mouse button in the upper left-hand pane selects a package module. If no module was specified when the browser was opened with the Tk::Browser::open method, the the Lib::Module package scans first instance of each .pm and .pl file in the Perl library's @INC array of directories. Duplicate library modules and symlinked directories are skipped. Default Perl configurations include '.' in the @INC path, so that modules in the current directory and its subdirectories are also scanned. The window in the upper right-hand corner of the browser lists all of the symbols and their values of the currently selected package's symbol table hash (stash), a lexical scan of the source file, and, optionally, records the results of a cross-reference scan, depending on the settings of the Symbol menu options. A text window in the lower half of the frame optionally displays the module source code, POD documentation, or version and file information, depending on the setting of the View menu options. All of the menu bar commands are described in section, MENU FUNCTIONS, below. Clicking the right mouse button in a subwindow displays a pop-up menu for that pane. Popup menu functions are also described below. By default, the browser lists all Perl source modules, when no modules are specified to the open() method. The module class hierarchy then starts with UNIVERSAL, the abstract superclass of all Perl modules, the default Perl class. Selecting the main:: Symbol Table display from the View menu displays all of the symbols in the default stash, including those of the the Browser itself. In this stash also are the path names of library modules that are imported at run time. All imported modules, not only source modules with the *.pm and *.pl extension can be listed and browsed separately using the Modules ==> List Imports menu option. Opening a browser with the open() method's 'package' option browses the first package which has a matching name, after locating it in the Perl library's @INC directories. The 'pathname' argument specifies the path name of a single Perl module to browse. The Perl script 'browser', listed below, is included in the archive. It will open a Browser from a shell prompt. If a the pathname of a module is supplied as the argument it will open that module. If the argument is a package name, if will search the library and open that package: #!/usr/bin/perl # browser -- Launcher for Browser.pm # Substitute path of the perl binary on your system # in the line above. # When installing, change permissions to executable: # 'chmod +x browser'. use Tk; use Tk::Browser; use Lib::Module; use Env qw(_); my $b; $b = new Tk::Browser; if( -e $ARGV[0] ) { # assume it's a file name; $b -> open(pathname => $ARGV[0]); } elsif( $ARGV[0] ) { # assume the arg's a package name and # we have to scan for it. $b -> open(package => $ARGV[0]); } else { # No argument: open everything. $b -> open; } MainLoop; # End of browser listing MENU FUNCTIONS ============== File Menu --------- Open Selected Module - Open a new browser for the module selected in the module list window. Save Info... - Open a FileBrowser and prompt for a file name. Save the information in each of the browser windows to the text file. Exit - Close the browser and exit the program. Edit Menu --------- Cut - Move selected text from the editor pane to the X clipboard. Copy - Copy selected text from the editor pane to the X clipboard. Paste - Insert text from the X clipboard at the text editor pane's insertion point. View Menu --------- Source - View module source code of selected module. POD Documentation - Format and view the selected module's POD documentation, if any. Module Info - List the selected module's package name, module filename, version, and superclasses. main:: Stash - List symbols in the current main:: Stash. (That is the stash of the browser.) Package Stashes - Filter current symbol list to show only secondary stashes and their symbols. Library Menu ------------ Read Again - Re-scan the Perl library directories and files. View Imported - List and optionally open files listed in the main:: stash that were imported by Perl. Packages Menu ------------- Stash - View symbols that are in the module's symbol table hash. Lexical - View symbols parsed from the module's source code. Cross References - For non-local stash symbols, check for cross references in other modules that have been loaded by the interpreter. Warning: Cross referencing can take a considerable amount of time. Help Menu --------- About - Display the version number and authorship of the Browser library. Help - View the Browser's POD documentation. Popup Menus ----------- Find - Search for text in that pane where the menu is popped up by pressing the right mouse button. Open Module - In the module list window, query for the module name on which to open a new browser. COPYRIGHT ========= The software in this package is distributed under the terms of the Perl Artistic License. Please refer to the file "Artistic" in the distribution archive file. REVISION ======== $Id: Browser.pm,v 0.80 2000/09/22 19:45:53 kiesling Exp $ SEE ALSO ======== The manual pages for: Lib::Module(3), Tk(3), perl(1), perlmod(1), perlmodlib(1), perlreftut(1), and perlref(1)