Instead of editing nested textual expressions, edit the whole expression.
[l3full.git] / l3doc / l3lang.txt
blob1fdb129a73da866a2b10662d9eee57b3ed5762ac
1 = l3lang(n) =
2 Michael Hohn <mhhohn@users.sf.net>
4 == NAME ==
5 l3lang - the l3 data handling and programming language
7 == SYNOPSIS ==
9 The l3 language is an interpreted, lexically scoped language
10 designed to automate much of the parameter and data handling of
11 the type often encountered in experimental (scientific)
12 computing. To accomplish this, l3 programs and all their data are
13 persistent, and can be inspected at any time; further, the
14 language maps one-to-one onto its graphical interface to make data
15 traversal and inspection practical.
16 See l3gui(1) for the interface description.
18 The l3 language is implemented as an interpreter written in Python;
19 all Python modules can be directly imported and used from l3.  Thus,
20 algorithms without interesting intermediate data can be written in
21 Python and called from l3 to provide a data interface for
22 applications, and existing Python code can be used directly. 
24 The l3 syntax follows Python's when possible, with only a few
25 syntactic extensions for parameter, module, and documentation
26 handling.  As result, most l3 scripts are valid Python scripts and
27 can be moved to Python if desired.
29 Only a subset of Python is repeated in l3; in particular,
30 there are no classes.  
32 The semantics of l3 are closer to a purely functional language.
33 Everything in l3 is an expression, including computed values.  l3 is
34 designed as a single-assignment language to permit reliable data
35 tracking; overwriting of existing names is *strongly* discouraged (but
36 allowed for compatibility with existing Python scripts).
38 l3 introduces several new language features to support direct access
39 to expressions and their values from a random-access interface (see
40 l3gui(1)); they are 
42 - Every expression is turned into an object by assignment of a
43   permanent, unique id.  Both the expression and the value(s) computed
44   by the expression can be accessed via this id (using the gui,
45   through the script's text).
47 - The data flow graph of l3 scripts is a stacked dag, and can be
48   generated from a script.  In this view, named data are emphasized,
49   and data interdependencies shown.  Loops cause no ``explosion'' of
50   the data flow graph.
52 - l3 scripts are lexically scoped, allowing for arbitrarily nested
53   (static) namespaces and avoiding name collisions.  Also, every
54   function call introduces a new (dynamic) scope, so multiple calls
55   to the same function do not produce naming conflicts, even when file
56   names are used.
58 - All scripts and their computed data are persistent.  l3 is most
59   useful when most data is should be kept.  By keeping _all_ data, file
60   I/O need not be part of a script, keeping it simpler and cleaner.
61   Exporting data to other programs _after_ script execution is simple
62   and can be done interactively or by adding I/O commands where
63   desired.
65 - Evaluation of scripts is incremental (need-based).  An expression is
66   only executed if it is out-of-date or newly inserted.  This allows
67   l3 scripts to _evolve_; they can be added to without re-running
68   existing code, and references to all previouly computed data are
69   available. 
71 - Values and scripts are the same.
72   An l3 value is a valid l3 script.  Therefore, computed values from prior
73   scripts can be directly inserted into new scripts. 
76 // == SYNTAX ==
77 // grammar.
79 == ENVIRONMENTS ==
80 Names are bound in environments.  Environments are lexically nested
81 and dynamically formed on function entry.  Scoping is lexical.
84 == SEMANTICS ==
85 The L3 semantics deal with the special cases of persistence and
86 need-based evaluation to make the language convenient to *use*, at the
87 cost of complicating the language.
89 When a new L3 program is executed the special cases do not affect
90 evaluation, so a simple description of those semantics are given
91 first, in 
92 <<sem-general, GENERAL RULES, autoref>>.
94 Persistence and need-based evaluation introduce retention and
95 retrieval of computed values, and a mechanism based on timestamps to
96 decide whether to interpret to get a new value or retrieve a
97 previously computed value.  The additional rules introduced by
98 evaluation are covered in
99 <<sem-timestamp, Timestamps and IDs, autoref>>.
101 Other special cases are listed after.
103 [[sem-general]]
104 .General rules
106 Numbers and strings evaluate to their internal representation and
107 return that.  Nested expressions evaluate children, then self, and
108 return this value.  Lists evaluate from first to last element, and a
109 list is returned.  Programs evaluate from first to last entry, and the
110 last computed value is returned.
112 Assignments are made in the enclosing environment, typically the
113 enclosing Program, Map, or Function.
115 Name (Symbol) lookup is lexical, starting in the current environment
116 and searching enclosing defining environments until a binding is
117 found, if any.
119 A Map (dictionary) is a Program inside a nested environment; the
120 Program is evaluated with bindings made in this environment, and the
121 environment itself is returned.
123 [[sem-timestamp]]
124 .Timestamps and IDs
126 Every expression has an associated numeric id and time stamp.  The id
127 is assigned once and never changes; every expression is uniquely
128 identified via its id.  There are three logical ages an
129 expression may have: SETUP, EXTERN, and INTEGER.  Corresponding to
130 these are the actual stamps "SETUP", "EXTERN" and any positive
131 integer.  The ordering of these is SETUP < EXTERN < INTEGER.
133 During evaluation, timestamps increase monotonically; they are
134 independent of system time.  An expression with time SETUP is
135 evaluated and its time updated to the current time (a positive integer).
137 An expression with time EXTERN is evaluated and no time stamp change
138 is made.
140 A terminal expression with an integer time stamp is not evaluated at
141 all; its prior value is retrieved and returned.  The timestamp remains
142 unchanged. 
144 A nested expression `E` with an intger time stamp first evaluates its
145 children.  If any child's value is newer than `E`, it is evaluated
146 again using the new values, and `E`'s timestamp updated.
148 An expression of EXTERN age is assumed constant, and its time stamp
149 never changes. 
152 .Special forms
154 Unlike other expressions in L3, `inline` is always evaluated, so its
155 contents must be constant.  For example
158 .External values
160 Most application-specific values are not recognized by L3 at all.
161 They are treated as simple values by l3 and represented as text, using
162 their Python `str()` form (which in turn is provided by the library
163 implementing the value).
167 == PYTHON COMPATIBILITY ==
169 The following Python(1) constructs are not available in l3.  The
170 workarounds are straightforward and are valid in Python and l3.
172 .Ungrouped tuple assignment 
173 Instead of 
174 ----------------------
175     psi, sx, sy, scale = compose_()
176 ----------------------
177 use 
178 ----------------------
179    (psi, sx, sy, scale) = compose_()
180 ----------------------
183 .list assignments
184 Instead of 
185 ---------------------------------
186     [psin, sxn, syn, mn] = combine_params2( ...)
187 ---------------------------------
189 ---------------------------------
190     (psin, sxn, syn, mn) = combine_params2( ...)
191 ---------------------------------
193 .dictionary syntax
194 The `{ key : val }` syntax is not available.  
195 Instead of 
196 ---------------------------------
197     {"negative":0, "mask":mask}
198 ---------------------------------
199 use 
200 ---------------------------------
201     dict(negative = 0, mask = mask)
202 ---------------------------------
204 .No inline blocks
205 The shortcuts `if 1: do_this` and `def f(a,b): return a+b`
206 are not available.  Use the long forms
207 ---------------------------------
208     if 1:
209         do_this
210 ---------------------------------
212 ---------------------------------
213     def f(a,b):
214         return a+b
215 ---------------------------------
216 instead.        
218 .Values returned to l3 must pickle properly.  
219 There are several Python constructs that cannot be pickled and must
220 not be used in l3 code.
222 Most generators will not pickle.  In particular avoid `xrange` and use
223 `range` instead. 
225 Avoid using `from foo import \*` in inline code.  Importing this way
226 is often a problem for pickling.  For example, using
227 ---------------------------------
228     from numpy import *
229 ---------------------------------
230 causes the error 
231 ---------------------------------
232     pickle.PicklingError: Can't pickle <type 'frame'>: it's not
233     found as __builtin__.frame
234 ---------------------------------
235 and the session state will no longer save.
238 == SEE ALSO ==
239 l3(1), l3gui(1)
241 == AUTHOR ==
242 Michael Hohn, mhhohn@users.sf.net
244 == COPYING ==
245 Copyright (C) 2004-8 Lawrence Berkeley National Laboratory.
246 l3 is released under the BSD license.  See license.txt for details.