[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Lua impressions from a scheme/f# programmer [was: Linking Lua in F#]
- From: David Manura <dm.lua@...>
- Date: Mon, 18 Jul 2011 21:08:41 -0400
Here's a few quick responses on some of these points:
On Mon, Jul 18, 2011 at 6:46 PM, J. A. "Biep" Durieux <rrrs@biep.org> wrote:
> - Operator precedence: function call has the highest: a+b "c" = a+(b("c")), even if a+b yields a function.
First, a+b "c" is syntactic sugar for a+b("c") [1]. Second, I think
the reason for omission of function calls in the precedence table [2]
is that function calls are not considered operators in the grammar
[3].
[1] http://www.lua.org/manual/5.1/manual.html#2.5.6
[2] http://www.lua.org/manual/5.1/manual.html#2.5.8
[3] http://www.lua.org/manual/5.1/manual.html#8
> - Limitations - I realise these are probably changeable by recompilation,
>but what are the standard, min and max values?
> - Recursion stack size? Is that the number of recursive calls, or do calls with many args take more space?
> - Max string, table, function, userdata size? Max size of table constructor?
> - Max number of function args, return values, unpackable values?
> - Max number of parallel threads? Open files? Max usable size of file?
Some such things are controlled by options in luaconf.h. They are
generally implementation defined (e.g. could differ in LuaJIT) and
omitted from the specification (i.e. Lua Reference Manual).
> - Relative cost of operations, to allow intelligent choice. Amortised cost, for garbage collection counts.
> - Between a closure and a table store+read for storage of information.
> - Between recomputation and memoizing to access information.
> - Between a numeric index table read and a hash index table read?
> - Insertion/deletion vs. other operations.
> - After computing a value, is it worthwhile saving a stack insertion and do pointer bookkeeping instead?
> - Does the cost of table.insert and table.remove depend on the size of the table?
> - table.sort: is sorting an (almost-)sorted table expensive? More or less expensive than the average case?
> - Likewise for space.
> - What is the overhead of having N small tables instead of one big one (e.g. for a matrix)?
> - What is the overhead of a function? Of a closure?
> - a = {x=p, y=q} is supposed to be equivalent to a={}; a.x=p; a.y=q
> - but it isn't, nor to a={}; a.x, a.y = p, q
> - To see that, consider a = {[f()]=g(), y=1} and a={}; a[f()]=g(); a.y=1 .
> - Now f and/or g may set a metatable with __setindex on a.
> - In the first case f and g cannot access the a being defined - they act on a previous value of a, if any.
> - In the second case, f and g act on the newly defined a.
Some of this is again implementation defined. I've understood the
"shifting" mentioned in table.insert and table.remove to imply O(N)
though. See also http://lua-users.org/wiki/OptimisationTips .
> - The function "next" and the one produced by "pairs" perform "rawget". They don't use __index (unfortunately).
This problem was described in [4]. A solution was implemented in 5.2beta [5].
[4] http://lua-users.org/wiki/GeneralizedPairsAndIpairs
[5] http://www.lua.org/work/doc/manual.html#pdf-pairs
>- Libaries.
> - Reification, which turns functions, the stack, etc. into a table with pointers to the innards.
> - Functions such as debug.traceback could be based on reify (and written in Lua, and user-changeable).
> - The complete workspace can also be reified. This state can be reinstalled later on.
> - Writing out this reified workspace creates a state dump, a save.
> - (Loading a save and) reinstalling a reified workspace means restoring the program state.
> - This is useful for games, but for other long-running programs too.
> - This way, saving is automatically preceded by an aggressive garbage collection
> - This minimises the save file, compacts the memory on reload.
> - The debug library comes close to providing the stuff needed to make a restartable dump. Missing is the following.
> - "debug.setinfo(..)" - there is no way to restore the state.
> - A more fine-grained function code pointer. "debug.getinfo('l')" is too course, obviously.
Maybe similar to some of the solutions in [6], such as Pluto an lper.
[6] http://lua-users.org/wiki/TableSerialization
> - Fold, which does intelligent folding of operators over many arguments (can be written in Lua).
> - For numerical operations, it tries to avoid overflow and loss of precision by judiciously ordering its args.
> - x=_MAXINT-1; map(+, {x, x, -x, -1}) --> _MAXINT-2 -- Illegal code, but you see what I mean..
> - For concatenation, it minimizes the amount of garbage produced (i.e. it would use table.concat).
> - For user defined function, it "degenerates" into a standard fold.
>- Language change proposals.
> - Please let functions such as table.insert return the table - this allows for concise functional programming.
> - The current situation is the cause of countless annoying little programming errors.
> - "return table.inser(t,v)" is legal - that's what makes it worse.
Others have brought that up [7]. See also [7.2]
[7] http://lua-users.org/lists/lua-l/2011-04/msg00345.html
[7.2] http://lua-users.org/wiki/MethodChainingWrapper
> - Please let the sort function be stable.
> - It allows one to sort e.g. by minor and major key.
> - If it is impossible to make sort stable without extra cost, at least allow a flag which enforces stability.
Apparently unchanged in 5.2beta [8]
[8] http://www.lua.org/work/doc/manual.html#pdf-table.sort
> - Allow "[x] = y", which assigns in the current environment table.
> - This makes Lua more uniform, for in table constructors, "a=b" is already a shorthand for "['a'] = b".
> - It makes Lua more expressive, more powerful.
> - "local [3]=x" is a neat, concise way of setting an array value in the current environment.
> - "[3]=x" ought to set the nearest enclosing [3] that has been defined.
> - A metatable can ensure that in a certain environment all numerical indexes are defined.
Syntax ambiguous:
f()
[x] = y
f() [x] = y
> - Remove statements from the language; let everything be expressions.
> - The language becomes simpler, both in grammar and conceptually.
> - The anomaly of function calls as statements is removed.
> - "return" in tail position becomes the identity operation, and may slowly be deprecated.
> - the comma would become a first-class value concatenator (stack pusher).
> - "return" in other positions becomes a break (see below).
> - Typing print(..) around all expressions in the interpreter becomes unnecessary.
> - That alone would already be worth it!
> - Old programs continue to work.
> - More expressivity is possible
> - Most obviously "return if x then a else b end".
> - A for loop might return the final value(s) of its (local) loop variable(s).
> - index = for i = 1, #a do if a[i]<0 then break end end -- will find the index of the first negative value in a.
> - "index, val = for i, v in ipairs(a) do" will find both the index and the value.
> - Alternatively, "break" might take an explist the way "return" does.
> - That is more flexible and works for the same way for all loops, for, while or until.
> - It would provide another kind of throw and catch - one not for errors, but for continuations.
> - "Statements" may still return zero values.
> - loadstring and its ilk become more useful - no need to guess whether "return " needs to be prefixed.
[9] http://lua-users.org/wiki/ExpressionsAsStatements
[10] http://lua-users.org/wiki/StatementsInExpressions
People have brought it up, and i recall various detractors too.
> - More metatable functionality.
> - Allow __type in metatables, which then is returned by the type function (I know, trivial to write oneself..).
[11] http://lua-users.org/wiki/TypeIntrospection
> - In line with __index which can contain a pointer to another table, __add might contain a number, etc.
I once thought __len (in 5.2alpha/beta) maybe should be allowed to
contain a number.
> - In general: the value in the metatable, if not a function, will be used instead of the table itself.
> - So if I want equivalence classes on tables or userdata, all I need to do is set some value to __eq.
> - (Assigning them the same metatable with a non-function value for __eq would alread do it.)
> - If I want to order my userdata, I store the rank in __lt.
> - This makes the various metatable events more uniform (and some code may be shared in accessing them).
> - It allows me to annotate numbers, strings and threads: the table behaves like the value, but accepts fields.
> - Default metatables would be great: a table used for every value without explicit metatable.
Others have mentioned this, but this also implies that {x=2} would
contain "sort" as a key. On difficulty here is that Lua doesn't
distinguish between method calls, indexing, and attributes on objects.
See also calls for differentiating ":" and "[]" syntax (e.g.
__methindex metamethod [11.2]).
[11.2] http://lua-users.org/lists/lua-l/2009-11/msg00715.html
> - And that includes environments in closures.
> - This would provide most "system hooks" in a Lua-worthy way.
> - The __index and __newindex in the default table metatable hook into variable access and assignment.
> - The __call in the default function metatable hooks into function calls and returns.
> - Of course, "rawcall" would be needed, in line with "rawget" and friends.
> - It would allow things such as proxies: values used before their definition.
> - Very useful for static OO initialisation: "John = man{wife=Mary}; Mary = woman{husband=John}".
> - "__index" would be programmed to return a proxy object, which would keep track of where it was assigned.
> - Assignment to a location that already held a proxy would replace all the proxy locations with the actual value.
> - After initialisation, a "run()" command might cleanup by removing the proxy-generating code.
> - Currently this can almost be made to work: it fails for proxies captured in closures and fresh tables.
> - Add "__init": "__init(table, how)" is executed when a table is created.
> - (Only useful in default metatables or with "table.clone".).
> - The second argument states how the table was created: by closure, through "{..}", through "table.create(how)"..
> - Give more freedom to events.
.
> - Particularly __len doesn't have much leeway: all strings and tables return their primitive length.
Supported in 5.2beta for tables [12] but not for strings.
[12] http://www.lua.org/work/doc/manual.html#2.4
> - One cannot even have it point to another table of which it is to return the length.
> - Having __index and __newindex have a say when the key exist already would be very nice too.
Has been requested before, sometimes named __setindex [13].
[13] http://lua-users.org/lists/lua-l/2009-06/msg00201.html
> - I realise this might lead to loss of speed, and is therefore not allowed. Is that correct?
> - Replace dispatch strings by tables, i.e. functions by libraries.
> - Reasons:
> - It makes the language more uniform. Currently there are two kinds of indexing/dispatching.
> - No more need for code inspecting the argument string.
> - The programmer can add, remove or change individual functions in a seamless way.
> - (They can now, too, but it is harder.)
> - Examples:
> - The function "collectgarbage". Let's have cg.count(), etc.
> - Hook setting would be nicer with "debug.sethook.call(..)", etc. (But a __call event would be even better!)
> - One may set the same or different hook functions for the various hooks.
> - One may remove some hook functions while leaving others active.
> - Likewise in the file metatable, but here a method "parse" would be better.
> - file:parse(string) reads in file trying to match with string, which is a string pattern.
> - By the way, string patterns could be more like format patterns - uniformity again.
> - Currently there are THREE pattern languages: for string formatting, string matching and file reading!
> - Make package.paths into a table, an array of paths.
> - That way ";" loses its special meaning - which is always a good thing.
> - One could even free "?" by having an optional entry "pattern='?'" setting the wildcard character.
> - It becomes easier to insert or remove paths, or to reorder them.
> - It is way more Lua-like.
> - It is faster, for no string-parsing is needed to get the indivual patterns.