* static vs. dynamic scoping
@ 2010-11-09 22:02 Eric Blake
2010-11-13 23:22 ` Harald van Dijk
0 siblings, 1 reply; 9+ messages in thread
From: Eric Blake @ 2010-11-09 22:02 UTC (permalink / raw)
To: dash
[-- Attachment #1: Type: text/plain, Size: 2425 bytes --]
On the Austin Group mailing list, David Korn (of ksh93 fame)
complained[1] that bash's 'local' uses dynamic scoping, but that ksh's
'typeset' uses static scoping, and argued that static scoping is saner
since it matches the behavior of declarative languages like C and Java
(dynamic scoping mainly matters in functional languages like lisp):
[1]
https://www.opengroup.org/sophocles/show_mail.tpl?CALLER=show_archive.tpl&source=L&listname=austin-group-l&id=14951
I'm trying to standardize the notion of local variables for the next
revision of POSIX, but before I can do so, I need some feedback on two
general aspects:
1. Implementation aspect:
How hard would it be to add static scoping to dash?
Is it something that should be added in addition to dynamic scoping,
via the use of an option to select the non-default mode (for example,
'local -d' to force dynamic, 'local -s' to force static, and 'local' to
go with default scoping)?
Or should dash switch entirely to static scoping (my gut feel is that
static scoping may be more efficient to implement, which fits in line
with dash's desire to be as lean as possible)?
2. User aspect:
Is anyone aware of a script that intentionally uses the full power of
dynamic scoping available through 'local' which would break if scoping
switched to static?
Here's a sample shell script that illustrates the difference between the
two scoping methods (note that ksh only provides nested scoping via its
typeset builtin, and only when using the function reserved word).
$ ksh -c 'function f1 { typeset a=local; f2; echo $a; };
function f2 { echo $a; a=changed; };
a=global; f1; echo $a'
global
local
changed
$ dash -c 'f1 () { typeset a=local; f2; echo $a; };
f2 () { echo $a; a=changed; };
a=global; f1; echo $a'
local
changed
global
In static scoping, function f2 does not shadow a declaration of a, so
references to $a within f2 refer to the global variable. The local
variable a of f1 can only be accessed within f1; the behavior of f2 is
the same no matter how it was reached.
In dynamic scoping, function f2 looks up its call stack for the closest
enclosing scope of a variable named a, and finds the local one declared
in f1. Therefore, the behavior of f2 depends on how f2 is called.
--
Eric Blake eblake@redhat.com +1-801-349-2682
Libvirt virtualization library http://libvirt.org
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 619 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: static vs. dynamic scoping
2010-11-09 22:02 static vs. dynamic scoping Eric Blake
@ 2010-11-13 23:22 ` Harald van Dijk
2010-11-13 23:54 ` ольга крыжановская
0 siblings, 1 reply; 9+ messages in thread
From: Harald van Dijk @ 2010-11-13 23:22 UTC (permalink / raw)
To: dash; +Cc: Eric Blake
On 09/11/10 23:02, Eric Blake wrote:
> 2. User aspect:
> Is anyone aware of a script that intentionally uses the full power of
> dynamic scoping available through 'local' which would break if scoping
> switched to static?
FWIW, some scripts use "local IFS" to reset IFS to a sane value, and
have the shell take care of restoring it afterwards. This works with
ksh's typeset, but because of the static scoping only so long as no
other shell functions get called, or those other shell functions also
take the effort to handle IFS correctly. In the scripts I have been able
to find, other shell functions do get called, but they themselves set
IFS too. Still, it may be worth keeping in mind, if only to serve as one
of the few examples of when dynamic scoping would have been slightly
more useful.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: static vs. dynamic scoping
2010-11-13 23:22 ` Harald van Dijk
@ 2010-11-13 23:54 ` ольга крыжановская
2010-11-14 0:10 ` Harald van Dijk
0 siblings, 1 reply; 9+ messages in thread
From: ольга крыжановская @ 2010-11-13 23:54 UTC (permalink / raw)
To: Harald van Dijk; +Cc: dash, Eric Blake
How is dynamic scoping in this case 'more useful'? Imagine function a
written by author A and function b written by author B, both loaded
into an application and each of them working independently, bound
together by an api spec.
Now function a uses typeset IFS="X" to set the field separator to "X"
via a local variable IFS. If function b now uses "read foo1 foo2 foo3"
to read a line of a database the concept of dynamic scoping *BITES*.
Suddenly function b no longer works as author B intended it. Lots of
surprise, lots of raised eyebrows by an unwanted interaction.
Static scoping is in this case much *SAFER* because IFS is reset in
function b to the (global) default.
The issue isn't new but the issues with dynamic scoping are one major
factor why there are so few shell function libraries: It is just hard
to write such a library without running afoul dynamic scoping.
Olga
On Sun, Nov 14, 2010 at 12:22 AM, Harald van Dijk <harald@gigawatt.nl> wrote:
> On 09/11/10 23:02, Eric Blake wrote:
>>
>> 2. User aspect:
>> Is anyone aware of a script that intentionally uses the full power of
>> dynamic scoping available through 'local' which would break if scoping
>> switched to static?
>
> FWIW, some scripts use "local IFS" to reset IFS to a sane value, and have
> the shell take care of restoring it afterwards. This works with ksh's
> typeset, but because of the static scoping only so long as no other shell
> functions get called, or those other shell functions also take the effort to
> handle IFS correctly. In the scripts I have been able to find, other shell
> functions do get called, but they themselves set IFS too. Still, it may be
> worth keeping in mind, if only to serve as one of the few examples of when
> dynamic scoping would have been slightly more useful.
> --
> To unsubscribe from this list: send the line "unsubscribe dash" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
--
, _ _ ,
{ \/`o;====- Olga Kryzhanovska -====;o`\/ }
.----'-/`-/ olga.kryzhanovska@gmail.com \-`\-'----.
`'-..-| / http://twitter.com/fleyta \ |-..-'`
/\/\ Solaris/BSD//C/C++ programmer /\/\
`--` `--`
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: static vs. dynamic scoping
2010-11-13 23:54 ` ольга крыжановская
@ 2010-11-14 0:10 ` Harald van Dijk
0 siblings, 0 replies; 9+ messages in thread
From: Harald van Dijk @ 2010-11-14 0:10 UTC (permalink / raw)
To: dash
Cc: ольга крыжановская,
Eric Blake
On 14/11/10 00:54, ольга крыжановская wrote:
> Now function a uses typeset IFS="X" to set the field separator to "X"
> via a local variable IFS. If function b now uses "read foo1 foo2 foo3"
> to read a line of a database the concept of dynamic scoping *BITES*.
The way I had seen "local IFS" used is to sanitise IFS -- to reset IFS
to the default value, when IFS was set to, for example, : before the
function was called, and the function wants to split on whitespace. In
that case, you don't want b to get IFS=:. Both forms are used, and in
your form, I agree, static scoping is more useful.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: static vs. dynamic scoping
@ 2010-11-10 14:15 ольга крыжановская
2010-11-10 21:01 ` Jilles Tjoelker
0 siblings, 1 reply; 9+ messages in thread
From: ольга крыжановская @ 2010-11-10 14:15 UTC (permalink / raw)
To: dash
Eric Blake wrote:
> Or should dash switch entirely to static scoping (my gut feel is that
> static scoping may be more efficient to implement, which fits in line
> with dash's desire to be as lean as possible)?
static scoping is much more efficient. Think about accessing a global
variable in a deep function call stack, e.g. 20 functions deep. With
dynamic scoping you have to look up the list of local variables for
each function *first* before looking at the global variables. In my
example this means 20 look ups. Each further function adds another
look up.
For static scoping you just look at the local variables of the
*current* function and then look up the global ones. This is faster
and much more efficient.
Olga
--
, _ _ ,
{ \/`o;====- Olga Kryzhanovska -====;o`\/ }
.----'-/`-/ olga.kryzhanovska@gmail.com \-`\-'----.
`'-..-| / http://twitter.com/fleyta \ |-..-'`
/\/\ Solaris/BSD//C/C++ programmer /\/\
`--` `--`
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: static vs. dynamic scoping
2010-11-10 14:15 ольга крыжановская
@ 2010-11-10 21:01 ` Jilles Tjoelker
0 siblings, 0 replies; 9+ messages in thread
From: Jilles Tjoelker @ 2010-11-10 21:01 UTC (permalink / raw)
To: ольга крыжановская
Cc: dash
On Wed, Nov 10, 2010 at 03:15:59PM +0100, ольга крыжановская wrote:
> Eric Blake wrote:
> > Or should dash switch entirely to static scoping (my gut feel is that
> > static scoping may be more efficient to implement, which fits in line
> > with dash's desire to be as lean as possible)?
> static scoping is much more efficient. Think about accessing a global
> variable in a deep function call stack, e.g. 20 functions deep. With
> dynamic scoping you have to look up the list of local variables for
> each function *first* before looking at the global variables. In my
> example this means 20 look ups. Each further function adds another
> look up.
> For static scoping you just look at the local variables of the
> *current* function and then look up the global ones. This is faster
> and much more efficient.
That's not how dash implements it, though. The local builtin saves the
value and attributes of the variable and they are restored upon return.
There is just one table of variables to search (two in older versions
and other ash versions, the additional one storing variable assignments
for regular builtins like IFS= read x; these were converted to the local
mechanism recently).
The real efficiency benefit of static scoping comes when disallowing
access to locals when the name is not known at compile time: at run
time, the names of the locals are not necessary.
--
Jilles Tjoelker
^ permalink raw reply [flat|nested] 9+ messages in thread
[parent not found: <4CD9C280.60007@redhat.com>]
end of thread, other threads:[~2010-11-15 21:45 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-11-09 22:02 static vs. dynamic scoping Eric Blake
2010-11-13 23:22 ` Harald van Dijk
2010-11-13 23:54 ` ольга крыжановская
2010-11-14 0:10 ` Harald van Dijk
-- strict thread matches above, loose matches on Subject: below --
2010-11-10 14:15 ольга крыжановская
2010-11-10 21:01 ` Jilles Tjoelker
[not found] <4CD9C280.60007@redhat.com>
[not found] ` <4CDA6301.1010703@gmail.com>
2010-11-10 15:13 ` Eric Blake
2010-11-15 21:11 ` Cedric Blancher
2010-11-15 21:45 ` Eric Blake
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox