Discussion:
The "Display" of Pascal?
(too old to reply)
gareth evans
2021-03-27 13:36:31 UTC
Permalink
Is there any inescapable reason in Pascal to define
a procedure within a procedure, for it seems to me that
the "Display" in the stack frame to give access to the
variables of an enclosing procedure must result in very
slow execution to read or write to those variables?

It's never been a problem for me in RTL/2, PLM86,
PLM51, CORAL, C, C++, Visual Basic, Tcl, and a raft
of others to pass variables in the calling convention
when required.
Scott Lurndal
2021-03-27 16:35:17 UTC
Permalink
Post by gareth evans
Is there any inescapable reason in Pascal to define
a procedure within a procedure, for it seems to me that
the "Display" in the stack frame to give access to the
variables of an enclosing procedure must result in very
slow execution to read or write to those variables?
Not for most architectures. The compiler knows the offset from the
frame pointer to the local variables, so there is no penalty to
access the enclosing procedures variables, same instruction just
a different offset from the frame pointer register.
gareth evans
2021-03-27 17:09:31 UTC
Permalink
Post by Scott Lurndal
Post by gareth evans
Is there any inescapable reason in Pascal to define
a procedure within a procedure, for it seems to me that
the "Display" in the stack frame to give access to the
variables of an enclosing procedure must result in very
slow execution to read or write to those variables?
Not for most architectures. The compiler knows the offset from the
frame pointer to the local variables, so there is no penalty to
access the enclosing procedures variables, same instruction just
a different offset from the frame pointer register.
Sorry, but I disagree because the enclosed procedure can be called
a number of times by the outer procedure and the number of temporary
variables on the stack of the outer procedure may change and thus will
alter the
distance from the enclosed procedure's stack frame to the outer
procedure's stach frame, which, of course, is the reason for the
Display on the stack of the enclosed procedure pointing to
the stack frame of the outer procedure.

Sorry, that's a bit long-winded
Thomas Koenig
2021-03-28 18:53:52 UTC
Permalink
Post by Scott Lurndal
Post by gareth evans
Is there any inescapable reason in Pascal to define
a procedure within a procedure, for it seems to me that
the "Display" in the stack frame to give access to the
variables of an enclosing procedure must result in very
slow execution to read or write to those variables?
Not for most architectures. The compiler knows the offset from the
frame pointer to the local variables,
If there a frame pointer is actually needed. Often, you can save
one register by not having one.
a***@math.uni.wroc.pl
2021-03-27 20:24:51 UTC
Permalink
Post by gareth evans
Is there any inescapable reason in Pascal to define
a procedure within a procedure, for it seems to me that
the "Display" in the stack frame to give access to the
variables of an enclosing procedure must result in very
slow execution to read or write to those variables?
In standard Pascal nested procefures/functions are the
only way to get nested scope, so a lot of folks
used them. Beside code style, you can use them to
get effects impossible without nested procedures.
Basically you use such nested procedure as
procedure parameter, and it has access to extra
data, not accesiible via arguments or global
variables.

Concerning speed: classic display means double
indirections, so cost of access is twice as for
local variables. However, creation of classic
display adds cost to every procedure call,
even if you do not have accesses to variables
in enclosing scopes. Modern approach takes
advantage of fact that usually there is small
number of accesses to surroundig scopes. So
intead of full display there is just link to
enclosing scope and you need to follow links.
That is more expensive, but if procedure
have several accesses to enclosing scopes
then compiler can generate code to create
display on entry to procedure, which is only
moderatly more expensive than code used to
create classic displays, but has advantage
that is done only for procedures that need it.

Also, if nested procedures are only used to
have better code structure, then compiler may
notice that they are not needed and effectively
flatten scope.

Bottom line: it may matter in performance critcal
code, but for most code overhead is negligible.
--
Waldek Hebisch
Joe Pfeiffer
2021-03-27 20:45:31 UTC
Permalink
Post by gareth evans
Is there any inescapable reason in Pascal to define
a procedure within a procedure, for it seems to me that
the "Display" in the stack frame to give access to the
variables of an enclosing procedure must result in very
slow execution to read or write to those variables?
It's never been a problem for me in RTL/2, PLM86,
PLM51, CORAL, C, C++, Visual Basic, Tcl, and a raft
of others to pass variables in the calling convention
when required.
It's always struck me as something that seemed like a good idea at the
time, but once it had been implemented it turned out to almost never be
used.
Peter Flass
2021-03-28 22:54:39 UTC
Permalink
Post by gareth evans
Is there any inescapable reason in Pascal to define
a procedure within a procedure, for it seems to me that
the "Display" in the stack frame to give access to the
variables of an enclosing procedure must result in very
slow execution to read or write to those variables?
It's never been a problem for me in RTL/2, PLM86,
PLM51, CORAL, C, C++, Visual Basic, Tcl, and a raft
of others to pass variables in the calling convention
when required.
Sometimes I’ve gotten tangled up in stuff that has to be passed. I use
nested procedures in PL/I when they make things simpler. It’s only one
extra instruction to access those variables, probably as simple as what PIC
does
--
Pete
robertth...@googlemail.com
2021-04-06 09:11:28 UTC
Permalink
Post by gareth evans
Is there any inescapable reason in Pascal to define
The joy of it is that you can make the inner procedure recursive and it also has access to the outer procedure's variables as sort of "sub globals". However I have to confess that in nearly 50 years of coding I've used it about twice.
Peter Flass
2021-04-06 17:22:12 UTC
Permalink
Post by ***@googlemail.com
Post by gareth evans
Is there any inescapable reason in Pascal to define
The joy of it is that you can make the inner procedure recursive and it
also has access to the outer procedure's variables as sort of "sub
globals". However I have to confess that in nearly 50 years of coding
I've used it about twice.
Exactly so. I use it a lot in PL/I for exactly this reason. It can avoid
passing a lot of parameters to the subroutine. I came to C from PL/I and
was unhappy with its “all or nothing” globals.
--
Pete
J. Clarke
2021-04-06 18:45:08 UTC
Permalink
Post by Peter Flass
Post by ***@googlemail.com
Post by gareth evans
Is there any inescapable reason in Pascal to define
The joy of it is that you can make the inner procedure recursive and it
also has access to the outer procedure's variables as sort of "sub
globals". However I have to confess that in nearly 50 years of coding
I've used it about twice.
Exactly so. I use it a lot in PL/I for exactly this reason. It can avoid
passing a lot of parameters to the subroutine. I came to C from PL/I and
was unhappy with its “all or nothing” globals.
If I understand what you're describing correctly, APL has the same
feature, you can define variables that are local to a function and
accessible by everything it calls.
Ahem A Rivet's Shot
2021-04-06 20:05:34 UTC
Permalink
On Tue, 06 Apr 2021 14:45:08 -0400
Post by J. Clarke
Post by Peter Flass
Post by ***@googlemail.com
Post by gareth evans
Is there any inescapable reason in Pascal to define
The joy of it is that you can make the inner procedure recursive and it
also has access to the outer procedure's variables as sort of "sub
globals". However I have to confess that in nearly 50 years of coding
I've used it about twice.
Exactly so. I use it a lot in PL/I for exactly this reason. It can avoid
passing a lot of parameters to the subroutine. I came to C from PL/I and
was unhappy with its “all or nothing” globals.
If I understand what you're describing correctly, APL has the same
feature, you can define variables that are local to a function and
accessible by everything it calls.
In Pascal (IIRC) the called functions have to be defined within the
scope of the calling function in order to have closures, I'm not sure
about PL/I I managed to miss out on that one. Closures are a fairly common
(and rarely used IME) language feature but syntax and restrictions vary
widely from language to language.
--
Steve O'Hara-Smith | Directable Mirror Arrays
C:\>WIN | A better way to focus the sun
The computer obeys and wins. | licences available see
You lose and Bill collects. | http://www.sohara.org/
Peter Flass
2021-04-06 22:10:22 UTC
Permalink
Post by Ahem A Rivet's Shot
On Tue, 06 Apr 2021 14:45:08 -0400
Post by J. Clarke
Post by Peter Flass
Post by ***@googlemail.com
Post by gareth evans
Is there any inescapable reason in Pascal to define
The joy of it is that you can make the inner procedure recursive and it
also has access to the outer procedure's variables as sort of "sub
globals". However I have to confess that in nearly 50 years of coding
I've used it about twice.
Exactly so. I use it a lot in PL/I for exactly this reason. It can avoid
passing a lot of parameters to the subroutine. I came to C from PL/I and
was unhappy with its “all or nothing” globals.
If I understand what you're describing correctly, APL has the same
feature, you can define variables that are local to a function and
accessible by everything it calls.
In Pascal (IIRC) the called functions have to be defined within the
scope of the calling function in order to have closures, I'm not sure
about PL/I I managed to miss out on that one. Closures are a fairly common
(and rarely used IME) language feature but syntax and restrictions vary
widely from language to language.
Didn’t know what a closure is. Looked it up, and still don’t know. The only
part of the definition I got is where they said it is confusing. Nested
scope is apparently not the same thing.
--
Pete
Ahem A Rivet's Shot
2021-04-07 08:05:48 UTC
Permalink
On Tue, 6 Apr 2021 15:10:22 -0700
Post by Peter Flass
Didn’t know what a closure is. Looked it up, and still don’t know. The
only part of the definition I got is where they said it is confusing.
Nested scope is apparently not the same thing.
Unless my understanding is broken, a closure is where a function has
direct access to a variable from the calling scope. The syntax and
restrictions vary a lot from language to language, as does the detailed
description, which is what makes it confusing.

It is not the same as nested scope, but sometimes closures are
restricted to functions in a nested scope.
--
Steve O'Hara-Smith | Directable Mirror Arrays
C:\>WIN | A better way to focus the sun
The computer obeys and wins. | licences available see
You lose and Bill collects. | http://www.sohara.org/
Joe Pfeiffer
2021-04-07 15:02:38 UTC
Permalink
Post by Ahem A Rivet's Shot
On Tue, 6 Apr 2021 15:10:22 -0700
Post by Peter Flass
Didn’t know what a closure is. Looked it up, and still don’t know. The
only part of the definition I got is where they said it is confusing.
Nested scope is apparently not the same thing.
Unless my understanding is broken, a closure is where a function has
direct access to a variable from the calling scope. The syntax and
restrictions vary a lot from language to language, as does the detailed
description, which is what makes it confusing.
Again, my understanding could also be broken, but I think you need
functions as objects to have a closure. You need to be able to create a
"function object" that you then execute at some later time, and when you
do so it has access to some part of the program state as it existed back
when the function object was created.
Post by Ahem A Rivet's Shot
It is not the same as nested scope, but sometimes closures are
restricted to functions in a nested scope.
Scott Lurndal
2021-04-07 15:28:17 UTC
Permalink
Post by Joe Pfeiffer
Post by Ahem A Rivet's Shot
On Tue, 6 Apr 2021 15:10:22 -0700
Didn’t know what a closure is. Looked it up, and still don’t know. The
only part of the definition I got is where they said it is confusing.
Nested scope is apparently not the same thing.
Unless my understanding is broken, a closure is where a function has
direct access to a variable from the calling scope. The syntax and
restrictions vary a lot from language to language, as does the detailed
description, which is what makes it confusing.
Again, my understanding could also be broken, but I think you need
functions as objects to have a closure. You need to be able to create a
"function object" that you then execute at some later time, and when you
do so it has access to some part of the program state as it existed back
when the function object was created.
I think your understanding matches mine. C++ lambda expressions come
to mind.

https://en.cppreference.com/w/cpp/language/lambda
Peter Flass
2021-04-07 19:55:52 UTC
Permalink
Post by Ahem A Rivet's Shot
On Tue, 6 Apr 2021 15:10:22 -0700
Post by Peter Flass
Didn’t know what a closure is. Looked it up, and still don’t know. The
only part of the definition I got is where they said it is confusing.
Nested scope is apparently not the same thing.
Unless my understanding is broken, a closure is where a function has
direct access to a variable from the calling scope. The syntax and
restrictions vary a lot from language to language, as does the detailed
description, which is what makes it confusing.
It is not the same as nested scope, but sometimes closures are
restricted to functions in a nested scope.
Sounds like I need to do more research.
--
Pete
Stoat
2021-04-08 01:50:06 UTC
Permalink
Post by Ahem A Rivet's Shot
On Tue, 6 Apr 2021 15:10:22 -0700
Post by Peter Flass
Didn’t know what a closure is. Looked it up, and still don’t know. The
only part of the definition I got is where they said it is confusing.
Nested scope is apparently not the same thing.
Unless my understanding is broken, a closure is where a function has
direct access to a variable from the calling scope. The syntax and
restrictions vary a lot from language to language, as does the detailed
description, which is what makes it confusing.
It is not the same as nested scope, but sometimes closures are
restricted to functions in a nested scope.
A closure is a piece of code and an environment (a binding of names to
values) in which it is to be executed.
It's designed to prevent the binding of a variable being dependent of
the run-time call path, as was the case in early versions of Lisp.

--brian
--
Wellington
New Zealand
Peter Flass
2021-04-10 23:24:27 UTC
Permalink
Post by Stoat
Post by Ahem A Rivet's Shot
On Tue, 6 Apr 2021 15:10:22 -0700
Post by Peter Flass
Didn’t know what a closure is. Looked it up, and still don’t know. The
only part of the definition I got is where they said it is confusing.
Nested scope is apparently not the same thing.
Unless my understanding is broken, a closure is where a function has
direct access to a variable from the calling scope. The syntax and
restrictions vary a lot from language to language, as does the detailed
description, which is what makes it confusing.
It is not the same as nested scope, but sometimes closures are
restricted to functions in a nested scope.
A closure is a piece of code and an environment (a binding of names to
values) in which it is to be executed.
It's designed to prevent the binding of a variable being dependent of
the run-time call path, as was the case in early versions of Lisp.
So it’s a thunk?
--
Pete
John Levine
2021-04-11 02:22:40 UTC
Permalink
Post by Stoat
A closure is a piece of code and an environment (a binding of names to
values) in which it is to be executed.
It's designed to prevent the binding of a variable being dependent of
the run-time call path, as was the case in early versions of Lisp.
So it’s a thunk?
Sort of. Assuming you mean Algol 60 style thunks, they do the same thing, capture
a dynamic nesting state, but thunks are anonymous and implicit, while closures can
depending on the language, be created explicitly, have names and be passed around as objects.
--
Regards,
John Levine, ***@taugh.com, Primary Perpetrator of "The Internet for Dummies",
Please consider the environment before reading this e-mail. https://jl.ly
Peter Flass
2021-04-11 02:48:30 UTC
Permalink
Post by John Levine
Post by Peter Flass
Post by Stoat
A closure is a piece of code and an environment (a binding of names to
values) in which it is to be executed.
It's designed to prevent the binding of a variable being dependent of
the run-time call path, as was the case in early versions of Lisp.
So it’s a thunk?
Sort of. Assuming you mean Algol 60 style thunks, they do the same thing, capture
a dynamic nesting state, but thunks are anonymous and implicit, while closures can
depending on the language, be created explicitly, have names and be
passed around as objects.
Sounds like I need to do more reading, but this sounds like PL/I ENTRY
variables.
--
Pete
John Levine
2021-04-11 19:14:08 UTC
Permalink
Post by Peter Flass
Post by John Levine
Post by Stoat
A closure is a piece of code and an environment (a binding of names to
values) in which it is to be executed.
It's designed to prevent the binding of a variable being dependent of
the run-time call path, as was the case in early versions of Lisp.
So it’s a thunk?
Sort of. Assuming you mean Algol 60 style thunks, they do the same thing, capture
a dynamic nesting state, but thunks are anonymous and implicit, while closures can
depending on the language, be created explicitly, have names and be
passed around as objects.
Sounds like I need to do more reading, but this sounds like PL/I ENTRY
variables.
Again, sort of. In Pascal and PL/I, dynamic variables are allocated on a stack,
and variables outside of the current block are found by looking down the stack.
Real closures let you remember the state of a procedure beyond the return from the calling
routine, so it needs heap allocation and garbage collection. Thunks are in between, they
keep the call state but their scope is limited so stack allocation still works.
--
Regards,
John Levine, ***@taugh.com, Primary Perpetrator of "The Internet for Dummies",
Please consider the environment before reading this e-mail. https://jl.ly
Fred Weigel
2021-04-07 12:20:02 UTC
Permalink
Post by Peter Flass
Post by Ahem A Rivet's Shot
On Tue, 06 Apr 2021 14:45:08 -0400
Post by J. Clarke
Post by ***@googlemail.com
Post by gareth evans
Is there any inescapable reason in Pascal to define
The joy of it is that you can make the inner procedure recursive and it
also has access to the outer procedure's variables as sort of "sub
globals". However I have to confess that in nearly 50 years of coding
I've used it about twice.
Exactly so. I use it a lot in PL/I for exactly this reason. It can avoid
passing a lot of parameters to the subroutine. I came to C from PL/I and
was unhappy with its “all or nothing” globals.
If I understand what you're describing correctly, APL has the same
feature, you can define variables that are local to a function and
accessible by everything it calls.
In Pascal (IIRC) the called functions have to be defined within the
scope of the calling function in order to have closures, I'm not sure
about PL/I I managed to miss out on that one. Closures are a fairly common
(and rarely used IME) language feature but syntax and restrictions vary
widely from language to language.
Didn’t know what a closure is. Looked it up, and still don’t know. The only
part of the definition I got is where they said it is confusing. Nested
scope is apparently not the same thing.
--
Pete
Pete

Closures are very interesting. No, PASCAL doesn't have them. Makes sense
in systems that have functions as first class things. Here is a very
simple example.

v <-5
f(x) <- return x + v

f(x) returns a function (notice the return -- and, I am making up the syntax) .
g <- f(1)

Now, g(x) is a function:

g(1) gives 6 (1 + 5) -- because x was passed, and v was "closed over".

Making another function:

v <- 6
h <- f(1)

g(1) STILL gives 6, h(1) gives 7 -- v changed, and a different function was returned.
now g() and h() are immune to further changes to v. A way to think abut this is that
an object was created -- it has private variables f() COULD change v inside of itself,
and THAT v would not influence g(). The object has an execution property and value
properties.

Javascript has closures, Scheme does. Pascal doesn't -- doesn't need them because
there is no way to handle functions like this (you can pass them, and call them, but
not generate them or return them...

FredW
Peter Flass
2021-04-07 19:55:53 UTC
Permalink
Post by Fred Weigel
Post by Peter Flass
Post by Ahem A Rivet's Shot
On Tue, 06 Apr 2021 14:45:08 -0400
Post by J. Clarke
Post by ***@googlemail.com
Post by gareth evans
Is there any inescapable reason in Pascal to define
The joy of it is that you can make the inner procedure recursive and it
also has access to the outer procedure's variables as sort of "sub
globals". However I have to confess that in nearly 50 years of coding
I've used it about twice.
Exactly so. I use it a lot in PL/I for exactly this reason. It can avoid
passing a lot of parameters to the subroutine. I came to C from PL/I and
was unhappy with its “all or nothing” globals.
If I understand what you're describing correctly, APL has the same
feature, you can define variables that are local to a function and
accessible by everything it calls.
In Pascal (IIRC) the called functions have to be defined within the
scope of the calling function in order to have closures, I'm not sure
about PL/I I managed to miss out on that one. Closures are a fairly common
(and rarely used IME) language feature but syntax and restrictions vary
widely from language to language.
Didn’t know what a closure is. Looked it up, and still don’t know. The only
part of the definition I got is where they said it is confusing. Nested
scope is apparently not the same thing.
--
Pete
Pete
Closures are very interesting. No, PASCAL doesn't have them. Makes sense
in systems that have functions as first class things. Here is a very
simple example.
v <-5
f(x) <- return x + v
f(x) returns a function (notice the return -- and, I am making up the syntax) .
g <- f(1)
g(1) gives 6 (1 + 5) -- because x was passed, and v was "closed over".
v <- 6
h <- f(1)
g(1) STILL gives 6, h(1) gives 7 -- v changed, and a different function was returned.
now g() and h() are immune to further changes to v. A way to think abut this is that
an object was created -- it has private variables f() COULD change v inside of itself,
and THAT v would not influence g(). The object has an execution property and value
properties.
Javascript has closures, Scheme does. Pascal doesn't -- doesn't need them because
there is no way to handle functions like this (you can pass them, and call them, but
not generate them or return them...
FredW
OK, makes sense
--
Pete
Ahem A Rivet's Shot
2021-04-07 22:45:41 UTC
Permalink
On Wed, 7 Apr 2021 05:20:02 -0700 (PDT)
Post by Fred Weigel
Closures are very interesting. No, PASCAL doesn't have them. Makes sense
in systems that have functions as first class things. Here is a very
simple example.
v <-5
f(x) <- return x + v
f(x) returns a function (notice the return -- and, I am making up the
syntax) . g <- f(1)
g becomes the function return 1 + v
I think not, as you have written it g() is a function that equates
to { return 1 + v } - by passing 1 as x you have created a function in which
x is fixed and v is supplied from the enclosing environment, but g takes no
parameters.
Post by Fred Weigel
g(1) gives 6 (1 + 5) -- because x was passed, and v was "closed over".
What is the 1 being passed to g() doing ? The 1 passed to f() in
order to generate g() set x in g() to 1 and v comes from the closure so
there is nowhere for a parameter to g() to go.

Otherwise what is the 1 you passed to f() doing ? You have it doing
nothing at all.

To quote from the Scala documentation:

-----------
A closure is a function, whose return value depends on the value of one or
more variables declared outside this function.
-----------

Closures do not require functions as first class objects in order
to exist, but they only really become useful when you can return the
function that references a variable to a scope that doesn't know the
variable exists.

In this example the closure is that logger() has access to prefix
from the enclosing scope of make_logger - it is called from inside and
outside that scope with the value of prefix changing between the calls -
again syntax is made up.

---------------------------------------------------
make_logger(passed_prefix) {
prefix = "Dummy"
logger(msg) {
print(prefix + ":" + msg)
}
logger("Inside make_logger") // Enclosed is enough for this usage
prefix = passed_prefix
return logger // But this needs functions as objects
}

logger = make_logger("My Silly Function")

logger("Outside make_logger") // So that prefix can have effect here
------------------------------------------

The first call to logger("Inside make_logger") will see prefix with the
value dummy, however by the time logger gets returned it will have the
value "My silly function".
--
Steve O'Hara-Smith | Directable Mirror Arrays
C:\>WIN | A better way to focus the sun
The computer obeys and wins. | licences available see
You lose and Bill collects. | http://www.sohara.org/
Fred Weigel
2021-04-09 01:20:20 UTC
Permalink
Post by Ahem A Rivet's Shot
On Wed, 7 Apr 2021 05:20:02 -0700 (PDT)
Post by Fred Weigel
Closures are very interesting. No, PASCAL doesn't have them. Makes sense
in systems that have functions as first class things. Here is a very
simple example.
v <-5
f(x) <- return x + v
f(x) returns a function (notice the return -- and, I am making up the
syntax) . g <- f(1)
g becomes the function return 1 + v
I think not, as you have written it g() is a function that equates
to { return 1 + v } - by passing 1 as x you have created a function in which
x is fixed and v is supplied from the enclosing environment, but g takes no
parameters.
Post by Fred Weigel
g(1) gives 6 (1 + 5) -- because x was passed, and v was "closed over".
What is the 1 being passed to g() doing ? The 1 passed to f() in
order to generate g() set x in g() to 1 and v comes from the closure so
there is nowhere for a parameter to g() to go.
Otherwise what is the 1 you passed to f() doing ? You have it doing
nothing at all.
-----------
A closure is a function, whose return value depends on the value of one or
more variables declared outside this function.
-----------
Closures do not require functions as first class objects in order
to exist, but they only really become useful when you can return the
function that references a variable to a scope that doesn't know the
variable exists.
In this example the closure is that logger() has access to prefix
from the enclosing scope of make_logger - it is called from inside and
outside that scope with the value of prefix changing between the calls -
again syntax is made up.
---------------------------------------------------
make_logger(passed_prefix) {
prefix = "Dummy"
logger(msg) {
print(prefix + ":" + msg)
}
logger("Inside make_logger") // Enclosed is enough for this usage
prefix = passed_prefix
return logger // But this needs functions as objects
}
logger = make_logger("My Silly Function")
logger("Outside make_logger") // So that prefix can have effect here
------------------------------------------
The first call to logger("Inside make_logger") will see prefix with the
value dummy, however by the time logger gets returned it will have the
value "My silly function".
--
Steve O'Hara-Smith | Directable Mirror Arrays
C:\>WIN | A better way to focus the sun
The computer obeys and wins. | licences available see
You lose and Bill collects. | http://www.sohara.org/
You are correct -- I meant g <- f
FredW
Bill Findlay
2021-04-08 00:24:54 UTC
Permalink
Post by Ahem A Rivet's Shot
On Tue, 06 Apr 2021 14:45:08 -0400
Post by J. Clarke
Post by ***@googlemail.com
Post by gareth evans
Is there any inescapable reason in Pascal to define
The joy of it is that you can make the inner procedure recursive and it
also has access to the outer procedure's variables as sort of "sub
globals". However I have to confess that in nearly 50 years of coding
I've used it about twice.
Exactly so. I use it a lot in PL/I for exactly this reason. It can avoid
passing a lot of parameters to the subroutine. I came to C from PL/I and
was unhappy with its "all or nothing" globals.
If I understand what you're describing correctly, APL has the same
feature, you can define variables that are local to a function and
accessible by everything it calls.
In Pascal (IIRC) the called functions have to be defined within the
scope of the calling function in order to have closures, I'm not sure
about PL/I I managed to miss out on that one. Closures are a fairly common
(and rarely used IME) language feature but syntax and restrictions vary
widely from language to language.
Didn´t know what a closure is. Looked it up, and still don´t know. The
only
part of the definition I got is where they said it is confusing. Nested
scope is apparently not the same thing.
--
Pete
Pete
Closures are very interesting. No, PASCAL doesn't have them. ...
It most certainly does, but as transient values, not first-class objects.
They are needed to pass procedural and functional parameters correctly.
--
Bill Findlay
Fred Weigel
2021-04-09 01:28:11 UTC
Permalink
Post by Bill Findlay
Post by Ahem A Rivet's Shot
On Tue, 06 Apr 2021 14:45:08 -0400
Post by J. Clarke
Post by ***@googlemail.com
Post by gareth evans
Is there any inescapable reason in Pascal to define
The joy of it is that you can make the inner procedure recursive and it
also has access to the outer procedure's variables as sort of "sub
globals". However I have to confess that in nearly 50 years of coding
I've used it about twice.
Exactly so. I use it a lot in PL/I for exactly this reason. It can avoid
passing a lot of parameters to the subroutine. I came to C from PL/I and
was unhappy with its "all or nothing" globals.
If I understand what you're describing correctly, APL has the same
feature, you can define variables that are local to a function and
accessible by everything it calls.
In Pascal (IIRC) the called functions have to be defined within the
scope of the calling function in order to have closures, I'm not sure
about PL/I I managed to miss out on that one. Closures are a fairly common
(and rarely used IME) language feature but syntax and restrictions vary
widely from language to language.
Didn´t know what a closure is. Looked it up, and still don´t know. The
only
part of the definition I got is where they said it is confusing. Nested
scope is apparently not the same thing.
--
Pete
Pete
Closures are very interesting. No, PASCAL doesn't have them. ...
It most certainly does, but as transient values, not first-class objects.
They are needed to pass procedural and functional parameters correctly.
--
Bill Findlay
Turbo Pascal doesn't. Pascal would. You are correct here.
If passing a function, the display needs to be captured.
Bill Findlay
2021-04-09 15:43:23 UTC
Permalink
Post by Fred Weigel
Post by Bill Findlay
Post by Ahem A Rivet's Shot
On Tue, 06 Apr 2021 14:45:08 -0400
Post by J. Clarke
Post by ***@googlemail.com
Post by gareth evans
Is there any inescapable reason in Pascal to define
The joy of it is that you can make the inner procedure recursive and
it
also has access to the outer procedure's variables as sort of "sub
globals". However I have to confess that in nearly 50 years of coding
I've used it about twice.
Exactly so. I use it a lot in PL/I for exactly this reason. It can
avoid
passing a lot of parameters to the subroutine. I came to C from PL/I
and
was unhappy with its "all or nothing" globals.
If I understand what you're describing correctly, APL has the same
feature, you can define variables that are local to a function and
accessible by everything it calls.
In Pascal (IIRC) the called functions have to be defined within the
scope of the calling function in order to have closures, I'm not sure
about PL/I I managed to miss out on that one. Closures are a fairly common
(and rarely used IME) language feature but syntax and restrictions vary
widely from language to language.
Didn´t know what a closure is. Looked it up, and still don´t know. The
only
part of the definition I got is where they said it is confusing. Nested
scope is apparently not the same thing.
--
Pete
Pete
Closures are very interesting. No, PASCAL doesn't have them. ...
It most certainly does, but as transient values, not first-class objects.
They are needed to pass procedural and functional parameters correctly.
--
Bill Findlay
Turbo Pascal doesn't. Pascal would. You are correct here.
If passing a function, the display needs to be captured.
There is no need for a display: a pointer to the lexically
enclosing frame is sufficient.
--
Bill Findlay
Fred Weigel
2021-04-09 19:27:59 UTC
Permalink
Post by Bill Findlay
Post by Fred Weigel
Post by Bill Findlay
Post by Ahem A Rivet's Shot
On Tue, 06 Apr 2021 14:45:08 -0400
Post by J. Clarke
Post by ***@googlemail.com
Post by gareth evans
Is there any inescapable reason in Pascal to define
The joy of it is that you can make the inner procedure recursive and
it
also has access to the outer procedure's variables as sort of "sub
globals". However I have to confess that in nearly 50 years of coding
I've used it about twice.
Exactly so. I use it a lot in PL/I for exactly this reason. It can
avoid
passing a lot of parameters to the subroutine. I came to C from PL/I
and
was unhappy with its "all or nothing" globals.
If I understand what you're describing correctly, APL has the same
feature, you can define variables that are local to a function and
accessible by everything it calls.
In Pascal (IIRC) the called functions have to be defined within the
scope of the calling function in order to have closures, I'm not sure
about PL/I I managed to miss out on that one. Closures are a fairly
common
(and rarely used IME) language feature but syntax and restrictions vary
widely from language to language.
Didn´t know what a closure is. Looked it up, and still don´t know. The
only
part of the definition I got is where they said it is confusing. Nested
scope is apparently not the same thing.
--
Pete
Pete
Closures are very interesting. No, PASCAL doesn't have them. ...
It most certainly does, but as transient values, not first-class objects.
They are needed to pass procedural and functional parameters correctly.
--
Bill Findlay
Turbo Pascal doesn't. Pascal would. You are correct here.
If passing a function, the display needs to be captured.
There is no need for a display: a pointer to the lexically
enclosing frame is sufficient.
--
Bill Findlay
What about something like the following (no, I haven't compiled it -- I don't
know if this is valid Pascal, but... the intent should be clear enough)...
The function func3() is called in function2(). function2() has no way of
knowing that func3() is going to need integer a. either a is closed over,
or func3 is going to have to be very smart! It is this loss of context that
makes this interesting.

(I haven't looked at a pascal compiler) I would implement this as
a stack context captured on the call function2(). Since *that* passes
func3() - it can ALSO pass a display. The display will be used to find
the variable "a" *when* fn is called.

Anyway, something like that. I don't see how fn would know HOW to
find "a" when it is called with (potentially) lots of frames in between.

Unless (and this is very possible) I am not understanding Pascal here.

Fred Weigel



type f = function(x: integer): integer;

{ function 2 is outside of myfunction, we are seeing if
there is a possibility that function passed f would need
a display or closure }
function function2(x: integer; y: integer; fn: f): integer;
begin
{ no, fn itself can be smart enough to access a when
it is called -- it will be horrible to find a! the value of a
needs to be copied into fn() }
function2 := x + fn(y)
end;

function myfunction(x: integer): integer;
var
a: integer;
b: integer;
function func3(x: integer): integer;
begin
func3 = a + x { uses param and variable in myfunction }
end;
begin
a := x + 2;
b := 4;
myfunction = function2(a, x, func3)
end;

begin
{ display 19 }
writeln(myfunction(5))
end.
Bill Findlay
2021-04-09 22:48:06 UTC
Permalink
On 9 Apr 2021, Fred Weigel wrote
(in article<10feeb1d-3bc6-49c4-bf1f-***@googlegroups.com>):
...
Post by Fred Weigel
What about something like the following (no, I haven't compiled it -- I don't
know if this is valid Pascal, but... the intent should be clear enough)...
The function func3() is called in function2(). function2() has no way of
knowing that func3() is going to need integer a.
And function2 has no need to know that.
Post by Fred Weigel
either a is closed over,
??
Post by Fred Weigel
or func3 is going to have to be very smart! It is this loss of context that
makes this interesting.
No smarts are required and there is no loss of context.
Post by Fred Weigel
type f = function(x: integer): integer;
function function2(x: integer; y: integer; fn: f): integer;
begin
{ no, fn itself can be smart enough to access a when
it is called -- it will be horrible to find a! the value of a
needs to be copied into fn() }
Nope.
Post by Fred Weigel
function2 := x + fn(y)
end;
function myfunction(x: integer): integer;
var
a: integer;
b: integer;
function func3(x: integer): integer;
begin
func3 = a + x { uses param and variable in myfunction }
end;
begin
a := x + 2;
b := 4;
myfunction = function2(a, x, func3)
end;
...
Post by Fred Weigel
(I haven't looked at a pascal compiler) I would implement this as
a stack context captured on the call function2(). Since *that* passes
func3() - it can ALSO pass a display. The display will be used to find
the variable "a" *when* fn is called.
Yes, except that it is not necessary to pass a whole display,
Post by Fred Weigel
function2(a, x, func3)
passes the address of func3 and that of myfunction's current stack frame.
The latter is usually called func3's static pointer, its dynamicpointer
being the address of the stack frame of the calling routine of func3,
i.e. the stack frame of function2 when it calls fn.
Further enclosing scopes of func3 are accessible to it by chasing down
its static pointer chain.

This has been the usual implementation of lexical scoping since the early
1970s,
when measurement showed that displays offered no performance advantage,
because the typical lexical nesting depth is small.

Hope that helps.
--
Bill Findlay
Joe Pfeiffer
2021-04-10 01:34:34 UTC
Permalink
Post by Bill Findlay
Post by Fred Weigel
Turbo Pascal doesn't. Pascal would. You are correct here.
If passing a function, the display needs to be captured.
There is no need for a display: a pointer to the lexically
enclosing frame is sufficient.
Back in the dark ages when I learned Pascal, it was described in terms
of the "static link", which was a pointer to the lexically enclosing
block. An actual display vector was something I learned about later, as
an optimization.
Peter Flass
2021-04-10 23:24:28 UTC
Permalink
Post by Joe Pfeiffer
Post by Bill Findlay
Post by Fred Weigel
Turbo Pascal doesn't. Pascal would. You are correct here.
If passing a function, the display needs to be captured.
There is no need for a display: a pointer to the lexically
enclosing frame is sufficient.
Back in the dark ages when I learned Pascal, it was described in terms
of the "static link", which was a pointer to the lexically enclosing
block. An actual display vector was something I learned about later, as
an optimization.
Same in PL/I. LABEL and ENTRY variables include a pointer to their
lexically enclosing stack frame.
--
Pete
Joe Pfeiffer
2021-04-10 01:36:40 UTC
Permalink
Post by Fred Weigel
Post by Bill Findlay
Closures are very interesting. No, PASCAL doesn't have them. ...
It most certainly does, but as transient values, not first-class objects.
They are needed to pass procedural and functional parameters correctly.
Turbo Pascal doesn't. Pascal would. You are correct here.
If passing a function, the display needs to be captured.
I haven't used Pascal since some time in the very early 1980s, but I
don't remember procedural parameters... Did they exist back then? Are
they really something standard Pascal had but Turbo didn't? I'd always
thought Turbo was pretty much a proper superset of standard...
Jean-Marc Bourguet
2021-04-10 21:03:21 UTC
Permalink
Post by Joe Pfeiffer
Post by Fred Weigel
Post by Bill Findlay
Closures are very interesting. No, PASCAL doesn't have them. ...
It most certainly does, but as transient values, not first-class objects.
They are needed to pass procedural and functional parameters correctly.
Turbo Pascal doesn't. Pascal would. You are correct here.
If passing a function, the display needs to be captured.
I haven't used Pascal since some time in the very early 1980s, but I
don't remember procedural parameters... Did they exist back then? Are
they really something standard Pascal had but Turbo didn't? I'd always
thought Turbo was pretty much a proper superset of standard...
Procedural parameters are present in the Revised Report dated 1972 I've
downloaded somewhere years ago.

My memory is somewhat different from yours about Turbo Pascal: at first it
didn't have some features of Wirth's report and then evolved in a
independant way from that.

Sadly, to be practical implementations had to have extensions over Wirth's
Pascal. I've used Turbo Pascal and Dec Pascal, for sure they were
incompabitilities between them (but that's so long ago that I would not be
able to give any hints about what they were, I have not done any Pascal
programming for more than 25 years) and I seems to remember that the IEEE
standard was yet another beast, coming too late to have any influence on
most implementations.

Yours,
--
Jean-Marc
Peter Flass
2021-04-10 23:24:29 UTC
Permalink
Post by Joe Pfeiffer
Post by Fred Weigel
Post by Bill Findlay
Closures are very interesting. No, PASCAL doesn't have them. ...
It most certainly does, but as transient values, not first-class objects.
They are needed to pass procedural and functional parameters correctly.
Turbo Pascal doesn't. Pascal would. You are correct here.
If passing a function, the display needs to be captured.
I haven't used Pascal since some time in the very early 1980s, but I
don't remember procedural parameters... Did they exist back then? Are
they really something standard Pascal had but Turbo didn't? I'd always
thought Turbo was pretty much a proper superset of standard...
PL/I had them in 1964. I don’t use them much, but in one case I call a
procedure to recursively descend a binary tree and pass an entry point to
be called for each terminal node.
--
Pete
Joe Pfeiffer
2021-04-06 22:10:58 UTC
Permalink
Post by Ahem A Rivet's Shot
On Tue, 06 Apr 2021 14:45:08 -0400
Post by J. Clarke
Post by Peter Flass
Post by ***@googlemail.com
Post by gareth evans
Is there any inescapable reason in Pascal to define
The joy of it is that you can make the inner procedure recursive and it
also has access to the outer procedure's variables as sort of "sub
globals". However I have to confess that in nearly 50 years of coding
I've used it about twice.
Exactly so. I use it a lot in PL/I for exactly this reason. It can avoid
passing a lot of parameters to the subroutine. I came to C from PL/I and
was unhappy with its “all or nothing” globals.
If I understand what you're describing correctly, APL has the same
feature, you can define variables that are local to a function and
accessible by everything it calls.
In Pascal (IIRC) the called functions have to be defined within the
scope of the calling function in order to have closures, I'm not sure
about PL/I I managed to miss out on that one. Closures are a fairly common
(and rarely used IME) language feature but syntax and restrictions vary
widely from language to language.
Pascal doesn't really have closures (as I understand the term). It's
simple nested name binding.

You can use C's static keyword to restrict a global to the file in which
it's defined. Not as good as real modules, but not quite
all-or-nothing.
chris
2021-04-08 21:30:21 UTC
Permalink
Post by Peter Flass
Post by ***@googlemail.com
Post by gareth evans
Is there any inescapable reason in Pascal to define
The joy of it is that you can make the inner procedure recursive and it
also has access to the outer procedure's variables as sort of "sub
globals". However I have to confess that in nearly 50 years of coding
I've used it about twice.
Exactly so. I use it a lot in PL/I for exactly this reason. It can avoid
passing a lot of parameters to the subroutine. I came to C from PL/I and
was unhappy with its “all or nothing” globals.
Don't do globals here. In C, the correct way to share variables between
a set of functions, is to first define a struct containing same. Then,
pass a pointer to that structure between functions. It's faster,
since a pointer fits into a register. It provides data hiding and
virtual local scope. Haven't used globals for decades, other than
perhaps a few items at very top level,..
Charlie Gibbs
2021-04-08 23:30:20 UTC
Permalink
Post by chris
Post by Peter Flass
Post by ***@googlemail.com
Post by gareth evans
Is there any inescapable reason in Pascal to define
The joy of it is that you can make the inner procedure recursive and it
also has access to the outer procedure's variables as sort of "sub
globals". However I have to confess that in nearly 50 years of coding
I've used it about twice.
Exactly so. I use it a lot in PL/I for exactly this reason. It can avoid
passing a lot of parameters to the subroutine. I came to C from PL/I and
was unhappy with its “all or nothing” globals.
Don't do globals here. In C, the correct way to share variables between
a set of functions, is to first define a struct containing same. Then,
pass a pointer to that structure between functions. It's faster,
since a pointer fits into a register. It provides data hiding and
virtual local scope. Haven't used globals for decades, other than
perhaps a few items at very top level,..
Oh boy, a globals war! Haven't seen one of those for a while.
Just to throw fuel on the fire, I use globals for allocated
resources - file pointers, memory, etc. - since they exist
no matter where you are, and must be freed before you quit.
My programs exit by calling a function quit_cleanup(char *errmsg);
it frees all memory, closes all files, etc. and then, if errmsg
is not NULL, displays an error message before exiting with a
nonzero error code.

I do agree with the idea of passing a pointer to a struct of
variables, although I tend to make some variables (e.g. program
options) global because they're, well, global.

Let the games begin!
--
/~\ Charlie Gibbs | They don't understand Microsoft
\ / <***@kltpzyxm.invalid> | has stolen their car and parked
X I'm really at ac.dekanfrus | a taxi in their driveway.
/ \ if you read it the right way. | -- Mayayana
chris
2021-04-09 11:20:25 UTC
Permalink
Post by Charlie Gibbs
Post by chris
Post by Peter Flass
Post by ***@googlemail.com
Post by gareth evans
Is there any inescapable reason in Pascal to define
The joy of it is that you can make the inner procedure recursive and it
also has access to the outer procedure's variables as sort of "sub
globals". However I have to confess that in nearly 50 years of coding
I've used it about twice.
Exactly so. I use it a lot in PL/I for exactly this reason. It can avoid
passing a lot of parameters to the subroutine. I came to C from PL/I and
was unhappy with its “all or nothing” globals.
Don't do globals here. In C, the correct way to share variables between
a set of functions, is to first define a struct containing same. Then,
pass a pointer to that structure between functions. It's faster,
since a pointer fits into a register. It provides data hiding and
virtual local scope. Haven't used globals for decades, other than
perhaps a few items at very top level,..
Oh boy, a globals war! Haven't seen one of those for a while.
Just to throw fuel on the fire, I use globals for allocated
resources - file pointers, memory, etc. - since they exist
no matter where you are, and must be freed before you quit.
My programs exit by calling a function quit_cleanup(char *errmsg);
it frees all memory, closes all files, etc. and then, if errmsg
is not NULL, displays an error message before exiting with a
nonzero error code.
I do agree with the idea of passing a pointer to a struct of
variables, although I tend to make some variables (e.g. program
options) global because they're, well, global.
Let the games begin!
Not a war I hope :-). For system constants etc, often use a file
of the name project_defs.h, or sysdefs.h, which can be included as
needed. That can also enclose typedef and enum templates usable
by various parts of the system.

If the idea is to make code easier to debug and reuse, encapsulation
is a key part of that. Tend to write all code with a view to reuse,
or even as small libraries and the idea of globals, accessible from
anywhere, is an anathema to that. Not too difficult to get a C with
classes subset from such ideas, without all the baggage of C++...

Chris
Scott Lurndal
2021-04-09 14:24:30 UTC
Permalink
Post by Charlie Gibbs
Post by chris
Post by Peter Flass
Post by ***@googlemail.com
Post by gareth evans
Is there any inescapable reason in Pascal to define
The joy of it is that you can make the inner procedure recursive and it
also has access to the outer procedure's variables as sort of "sub
globals". However I have to confess that in nearly 50 years of coding
I've used it about twice.
Exactly so. I use it a lot in PL/I for exactly this reason. It can avoid
passing a lot of parameters to the subroutine. I came to C from PL/I and
was unhappy with its “all or nothing” globals.
Don't do globals here. In C, the correct way to share variables between
a set of functions, is to first define a struct containing same. Then,
pass a pointer to that structure between functions. It's faster,
since a pointer fits into a register. It provides data hiding and
virtual local scope. Haven't used globals for decades, other than
perhaps a few items at very top level,..
Oh boy, a globals war! Haven't seen one of those for a while.
Just to throw fuel on the fire, I use globals for allocated
resources - file pointers, memory, etc. - since they exist
no matter where you are, and must be freed before you quit.
My programs exit by calling a function quit_cleanup(char *errmsg);
it frees all memory, closes all files, etc. and then, if errmsg
is not NULL, displays an error message before exiting with a
nonzero error code.
I do agree with the idea of passing a pointer to a struct of
variables, although I tend to make some variables (e.g. program
options) global because they're, well, global.
Let the games begin!
as soon as you have more than one thread in an application,
writable (non const) globals should be completely avoided
or access to them must be synchronized correctly, or replaced
with thread-local variables.
Ahem A Rivet's Shot
2021-04-09 14:38:31 UTC
Permalink
On Fri, 09 Apr 2021 14:24:30 GMT
Post by Scott Lurndal
as soon as you have more than one thread in an application,
writable (non const) globals should be completely avoided
or access to them must be synchronized correctly, or replaced
with thread-local variables.
I'm not at all sure that swapping buffer overruns for thread races
has been a net benefit in code maintainability - but at least the thread
races are harder to exploit.
--
Steve O'Hara-Smith | Directable Mirror Arrays
C:\>WIN | A better way to focus the sun
The computer obeys and wins. | licences available see
You lose and Bill collects. | http://www.sohara.org/
Timothy McCaffrey
2021-04-07 21:50:16 UTC
Permalink
Post by gareth evans
Is there any inescapable reason in Pascal to define
a procedure within a procedure, for it seems to me that
the "Display" in the stack frame to give access to the
variables of an enclosing procedure must result in very
slow execution to read or write to those variables?
It's never been a problem for me in RTL/2, PLM86,
PLM51, CORAL, C, C++, Visual Basic, Tcl, and a raft
of others to pass variables in the calling convention
when required.
Depends on the architecture.

Burroughs/Unisys Large systems/A series had an array of pointers that were indexed at the current
lexical level (Global data was LL 2, IIRC, the program was LL1 and OS? was LL0, or something like that).
A nested procedure had a LL one greater than the enclosing procedure.

On the 80186/286, Intel added the Enter/Leave instructions which handled the drudgery of copying the
the outer frame pointers every time a nested procedure was entered and exited. (Note that these are
not supported in AMD64). Yes, you had to load the outer frame pointer first before you could use it,
but nothing said that you couldn't keep it around in a register and re-use it (thus avoiding "double indirect"
references) except, of course, the general lack of registers.

- Tim
Loading...