lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Mar 8, 2012, at 3:18 AM, steve donovan wrote:

> On Thu, Mar 8, 2012 at 12:58 AM, Jay Carlson <nop@nop.com> wrote:
>>    for i,v in pairs(fragments) do
>>        xml.parse(v, {
>>            function end_tag(t)
>>                print("closing tag", t, "at index", i)
>>            end
>>        })
>>    end
>> 
>> when there's a table+closure's worth of garbage created per iteration.
> 
> I suppose a clever compiler could hoist the {...} out of the loop

Read-only tables clearly can be hoisted all the way up to the chunk level. Mark mentioning read-only tables and me finding them hiding in the $L:"" argument position mapping made me start wondering about this.

A function readonly(t) could be peephole optimized not to copy t if encountered as readonly({table_constructor}) since there are no other references to {table_constructor}. If the table has no side effects or free variables at all, its readonly version can be moved to the chunk level. This is a kind of optimization plausible to do inside the existing compiler.

Barring side effects, the issue of hoisting it is finding the scope in which the free variables are invariant. Unfortunately...well, no, it's not unfortunate, I specifically set it up this way: in the example above end_tag references the loop variable i, which means it can be hoisted...to the start of the scope of the loop iteration. 

(In Smalltalk, the typical use of blocks allows them to be stack allocated; if that can be guaranteed then the compiler could be able to transform end_tag(t) to end_tag2(t, &i) which could have no free variables because &i is a numeric reference to the position of the local in the caller's activation record. But now we're really getting off in the weeds.)

> However, I'm not sure of the wisdom of not allowing new notations
> because they make inefficiency easier.

Yeah. If I wanted to work in a language where I had to worry about every little allocation I'd go back to C.

> On the subject of surprising commas, look at this map literal in Go:
> 
> var m = map[string]int {
>   "one": 1,
>  "two": 2,
>  "three":3,
> }
> 
> Here you actually _need_ the trailing comma, because the semi-colon
> insertion algorithm gets confused, pretty much like the JS situation.

Python tuples were clearly jammed into the language:

>>> print (), (1), (1,), (1,2)
() 1 (1,) (1, 2)

> Apparently all new Go programmers have to learn this the hard way...

...although I'm not entirely comfortable with our tuple-like multiple return splicing for the same reason. But I like that as a design principle:

  "Do not include features, especially edge cases, where *everybody* will find them out the hard way."

Not sure that gives any guidance on { function c() end 1 } though. For the most part, I am a rejectionist: I evaluate syntax shorthands by how many mistakes formerly rejected will now be either locally legal (making diagnosis of errors puzzling) or just flat out legal (making all function application omit parens, instead of just function application on string and table literals).

Jay