A Frame-space syntax ? - Re: global, globals(), _global ?

robert no-spam at no-spam-no-spam.com
Fri Mar 17 12:30:59 CET 2006


Alex Martelli wrote:

> robert <no-spam at no-spam-no-spam.com> wrote:
>    ...
> 
>>>Not sure I entirely understand what you're proposing, but locals access
>>>must remain compile-time-optimized for crucial practical reasons, so
>>>"writing to locals()" just will not work right.
>>
>>Why will a definite write to _certain_ top local dict consume any extra
>>time?
> 
> 
> Writing to a dict intrinsically takes longer than writing to a fixed
> offset into a vector.  locals(), as a dict, is in fact built as a shim
> on top of the fixed vector where a function's locals are kept. We're
> talking of a difference in timing of over a factor of two, over a
> microsecond per local-variable access on my laptop -- the average
> function does so much locals-accessing that I would expect it to slow
> down proportionally, by a factor of two or so, if locals were actually
> kept in a dictionary rather than in a vector.
> 
> Try it out by running the same code as a module's main body versus
> running it as a function -- see how much the latter approach speeds
> things up. Indeed, "put the code inside a function" is the first
> optimization tip to give to any newbie, exactly because a module's
> top-level code actually does read/write a dict for each variable access,
> while a function's body code does not.

looking at typical code, I'd guess 50% of the variable reads and 75% of 
writes are local.

testing a number crunch computation with locals only, I got down from

1.42501854286 seconds  to 1.04999126984 seconds  (=> 75% )

Thus I guess, typical functions would loose 15%..20% of their speed, 
Methods 10%, by using dicts only. (Dict-creation costs?) byte-code size 
would increase maybe 30%.


>>The target can still be directed fix at compile time. See below.
> 
> 
> None of the examples you give below exemplifies "writing to
> locals() could be defined as writing to the top-frame-locals" as you had
> proposed in the snippet I was responding to.
> 
>>>Ugly enough that Guido has never wanted to entertain such possibilities
>>
>>Maybe a syntax could be applied which is already known for float 
>>litterals and which seems to be intuitive and compatible to me:
>>
>>a=1
>>.a=1             # same
> 
> 
> Just about exactly this syntax was recently discussed on python-dev and
> Guido (and many others) shot it down in no time. Please do take the tiny
> trouble to research the python-dev archives, as I already suggested,
> before proposing something that's so recently been roundly rejected.
> 
> 
>>As far as I see this would not slow down the interpreter at run time 
>>(except maybe for the new "..b=" intermediate local write's)
> 
> Each local access that goes to a dict instead of a fixed vector will
> intrinsically and inevitably slow down by 2-3 times. And the fact that
> sometimes accessing a local c is the same as accessing .c, and sometimes
> it isn't, is something I'm *EXTREMELY* happy to not have to teach,
> explain, and justify.

The compiler whould know which variables go where.
The mechanism and a restrictive discrimination worse than the suggestion 
here is maybe already in current Python:

 >>> def f():
... 	exec "a=2"
... 	print a
... 	
 >>> f()
2
 >>>

-------

 >>> def f():
... 	exec "a=2"
... 	print a
... 	def g(): print a
Traceback (SyntaxError: unqualified exec is not allowed in function 'f' 
it contains a nested function with free variables (<interactive input>, 
line 2)
 >>>
 >>>

-------

That is: self-similarity breaks more and more when it is not accepted.

The frame-syntax and free dict suggestion is maybe more in line with 
original dict-centric Python.

( A potential dual a / .a  access is nothing else than 0.1 == .1  )

The speedy vector (if necessary; the 30% memory are maybe more 
important) could still be preserved for the majority of code. Free dict 
optional/even in addition. The compiler knows perfectly beforehand, when 
a free dict has to be added in rare cases.

Even a nested "..b" access from inner frame can go to and even trigger 
the vector binding in the outer. thus a one-dot-is-'same' ".b" syntax is 
not even necessary as I see now (only the compiler will become little 
more complex).  ".b" could alternatively immediately go down the 
hierarchy. And with 'exec' and danger the vector could be replaced with 
dict silently by the compiler also for access from inner frames.

Even the pseudo locals()-dict (better would be an object or .) could 
direct write's to local vector/dict (as it knows the name-to-index 
translation because it can read anyway).

The fact is:
* Python has that big problem with unnecessary barriers for nested frame 
access - especially painfull with callback functions where you want to 
put back data into the calling frame. That is a unnecessary disgrace 
compared to Ruby "blocks". With frame-space syntax Python nesteds could 
be even more clear&practical than blocks
* That need for a modern atomic ad-hoc route to globals.
* 'exec' breaks with SyntaxError
* self-inspection for the otherwise wonderful dict-language breaks 
unnecessarily

That could be most probably all healed in one rush with grace so and 
without any downwards compatibility issues and speed costs (except for 
the compiler part). The dict graile could be kept and guarantee.

( I don't know if all that has already been discussed to the end 'in no 
time', but I'd search longer for the right search terms to start 
searching :-) )

Robert



More information about the Python-list mailing list