Many questions should be answered with tooling here, but in the particular case I mentioned, IMHO it is not about tooling. Until now, code that does `Smalltalk at: something` wants to look up something dynamically or it can't be sure that this class is actually loaded. As there was only one place to do such lookups, no differentiation about visibility or the source of a binding was necessary.
Instances of `Smalltalk at: something` should either be replaced by an environment aware equivalent that makes clear if a name should be looked up *only* in the receiving environment (in its declarations), or if a name should be resolved, looking also in imported environments (in the bindings). As it is inconvenient to find all these pieces of code and change them all, `Smalltalk (globals)` could be the "active" environment (currently via dynamic scoping with `on: CurrentEnvironment do: ...`), not the original global environment. But then Environment>>at: must behave sensibly. I would expect that I can always do `Smalltalk at: #Object` to retrieve `Object` in any environment (under the assumption that every environment would import the "Kernel" or original environment). This is currently not the case, because Environment>>at: looks only into an environment's (own) declarations, not the imported bindings.
2016-09-29 17:30 GMT+02:00 Nicolas Cellier nicolas.cellier.aka.nice@gmail.com:
2016-09-29 15:15 GMT+02:00 Jakob Reschke jakob.reschke@student.hpi.de:
Hi,
Environment>>associationAt: is part of the Smalltalk globals Dictionary compatibility interface, right? As a quick and dirty fix, I changed instances of Smalltalk at: xyz in Monticello code to CurrentEnvironment signal at: xyz, but #at: also only reads in the declarations, so myEnvironment at: #MCWriter or myEnvironment at: #Object returns nil by default. It would make more sense to perform a full lookup via #valueOf:ifAbsent: in #at: and its cousins, wouldn't it?
Best, Jakob
I imagine that the question is about tools. For now Smalltalk importSelf, so bindings and declarations do agree. If an Environment does not importSelf, then some variables will be invisibles (unbounds). Do we still want to see them in some tool, or not? What's going on if we play with Alias? Do we want to see the Alias in some browser? If not, then we'd better stick with declarations. There is no easy solution. A single facade for two dictionaries cannot fit all, so we need several different messages. But it's much about what we want to do with those environments.
2016-09-29 7:33 GMT+02:00 H. Hirzel hannes.hirzel@gmail.com:
On 9/28/16, Nicolas Cellier nicolas.cellier.aka.nice@gmail.com wrote:
Since we are at reviewing Environment, here is a small detail that bothers me. I already asked some months ago, but silence was the only response, so ping.
Implementation of Environment is sometimes not obvious:
- Environment>>associationAt: uses declarations inst.var..
- Environment>>associationOrUndeclaredAt: uses bindings inst.var.
How can it be so different, the selector does not speak, does it?
OK, there is a flag: #review in one of them, but that does not make code clearer, it's just a smell of over-complexity or ill-naming.
Whatever the reason (self explaining code?) Colin does not comment class/methods, that's a fact.
Alternatively a description of the general ideas and the mechanism would help.
After all Environments is just a clever combination of a few dictionaries to look up class names? Isn't it? ;-)
However the fact that people did not move on much finalising the implementation of environments since 2012 shows that it is hard to reverse-engineer the intentions from the (incomplete) code.
Chris made the effort of commenting Environment but then came this declarations/bindings split, and the comment did rapidly rot. We have here an un-healthy statu quo crying for change.
So if we want to at least comment the class with the meaning/role/responsibility of inst vars, here is my understanding:
environment bind: #Foo to: 0. just add to the declarations. (You see how names are not obvious: bind does not bind the new binding to bindings).
Environments
bind: aSymbol to: anObject | binding newBinding | newBinding := aSymbol => anObject.
binding := declarations associationAt: aSymbol ifAbsent: [nil]. binding ifNotNil: [binding class == newBinding class ifTrue: [binding value: anObject] ifFalse: [binding becomeForward: newBinding]. ^anObject]. binding := undeclared associationAt: aSymbol ifAbsent: [nil]. binding ifNil: [binding := newBinding] ifNotNil: [undeclared removeKey: aSymbol. binding class == newBinding class ifTrue: [binding value: anObject] ifFalse: [binding becomeForward:
newBinding]].
declarations add: binding. self binding: binding addedTo: self. ^anObject
Could you elaborate a bit please?
If the Environment importSelf, then the ClassBinding/Global also goes to bindings... (thru an observer pattern and the magic of naming policies)
The bindings is what is used by the compiler, so what if an environment does not importSelf? It means that the variable it declares are not bound, so it is not reachable (kind of invisible class/Global).
IOW, the bindings will contain all the imports, including self-imports. importSelf is generally what we want to do, unless weird cases of powerless environment for obfuscation or trustless sandboxing reason.
Now, associationAt: does not speak for itself. It's too hard to decide if we're speaking of own declarations or bindings... Analyzing the usage is difficult. bindingAt: would be less ambiguous, so IMO we cannot fix without semantic shift.
This would need as well elaboration as well a separate thread.
The semantic will be carried by the senders (the Tools), and the tools by usage we want to make of Environment. So we first have to define that: what feature do we want to support? With which tool? That probably require yet another thread...
Yes
--Hannes
2016-09-29 18:39 GMT+02:00 Jakob Reschke jakob.reschke@student.hpi.de:
Many questions should be answered with tooling here, but in the particular case I mentioned, IMHO it is not about tooling. Until now, code that does `Smalltalk at: something` wants to look up something dynamically or it can't be sure that this class is actually loaded. As there was only one place to do such lookups, no differentiation about visibility or the source of a binding was necessary.
Instances of `Smalltalk at: something` should either be replaced by an environment aware equivalent that makes clear if a name should be looked up *only* in the receiving environment (in its declarations), or if a name should be resolved, looking also in imported environments (in the bindings).
Agree
As it is inconvenient to find all these pieces of code and change them all, `Smalltalk (globals)` could be the "active" environment (currently via dynamic scoping with `on: CurrentEnvironment do: ...`), not the original global environment.
I don't like the idea of CurrentEnvironment at all. IMO global state stinks. It would mean that a lotta behavior would change by simply switching one shared variable... I see it more like a not so clever workaround to make tools still work in presence of environments with minimal changes.
But then Environment>>at: must behave sensibly. I would expect that I can always do `Smalltalk at: #Object` to retrieve `Object` in any environment (under the assumption that every environment would import the "Kernel" or original environment). This is currently not the case, because Environment>>at: looks only into an environment's (own) declarations, not the imported bindings.
I don't know. Maybe (Smalltalk at: #Foo) is questionable by itself. VW did introduce #{Foo} ifPresent: [:foo | ] or something like that for deferred bindings. I remind you that Smalltalk itself is a global variable created with a different instance for each environment.
Object is in the superclass chain, so we can still access with superclass superclass ... environment.
2016-09-29 17:30 GMT+02:00 Nicolas Cellier <nicolas.cellier.aka.nice@ gmail.com>:
2016-09-29 15:15 GMT+02:00 Jakob Reschke jakob.reschke@student.hpi.de:
Hi,
Environment>>associationAt: is part of the Smalltalk globals Dictionary compatibility interface, right? As a quick and dirty fix, I changed instances of Smalltalk at: xyz in Monticello code to CurrentEnvironment signal at: xyz, but #at: also only reads in the declarations, so myEnvironment at: #MCWriter or myEnvironment at: #Object returns nil by default. It would make more sense to perform a full lookup via #valueOf:ifAbsent: in #at: and its cousins, wouldn't it?
Best, Jakob
I imagine that the question is about tools. For now Smalltalk importSelf, so bindings and declarations do agree. If an Environment does not importSelf, then some variables will be invisibles (unbounds). Do we still want to see them in some tool, or not? What's going on if we play with Alias? Do we want to see the Alias in
some
browser? If not, then we'd better stick with declarations. There is no easy solution. A single facade for two dictionaries cannot
fit
all, so we need several different messages. But it's much about what we want to do with those environments.
2016-09-29 7:33 GMT+02:00 H. Hirzel hannes.hirzel@gmail.com:
On 9/28/16, Nicolas Cellier nicolas.cellier.aka.nice@gmail.com
wrote:
Since we are at reviewing Environment, here is a small detail that bothers me. I already asked some months ago, but silence was the only
response,
so ping.
Implementation of Environment is sometimes not obvious:
- Environment>>associationAt: uses declarations inst.var..
- Environment>>associationOrUndeclaredAt: uses bindings inst.var.
How can it be so different, the selector does not speak, does it?
OK, there is a flag: #review in one of them, but that does not make code clearer, it's just a smell of over-complexity or ill-naming.
Whatever the reason (self explaining code?) Colin does not comment class/methods, that's a fact.
Alternatively a description of the general ideas and the mechanism
would
help.
After all Environments is just a clever combination of a few dictionaries to look up class names? Isn't it? ;-)
However the fact that people did not move on much finalising the implementation of environments since 2012 shows that it is hard to reverse-engineer the intentions from the (incomplete) code.
Chris made the effort of commenting Environment but then came this declarations/bindings split, and the comment did rapidly rot. We have here an un-healthy statu quo crying for change.
So if we want to at least comment the class with the meaning/role/responsibility of inst vars, here is my understanding:
environment bind: #Foo to: 0. just add to the declarations. (You see how names are not obvious: bind does not bind the new
binding
to bindings).
Environments
bind: aSymbol to: anObject | binding newBinding | newBinding := aSymbol => anObject.
binding := declarations associationAt: aSymbol ifAbsent:
[nil].
binding ifNotNil: [binding class == newBinding class ifTrue: [binding value: anObject] ifFalse: [binding becomeForward: newBinding]. ^anObject]. binding := undeclared associationAt: aSymbol ifAbsent: [nil]. binding ifNil: [binding := newBinding] ifNotNil: [undeclared removeKey: aSymbol. binding class == newBinding class ifTrue: [binding value: anObject] ifFalse: [binding becomeForward:
newBinding]].
declarations add: binding. self binding: binding addedTo: self. ^anObject
Could you elaborate a bit please?
If the Environment importSelf, then the ClassBinding/Global also goes to bindings... (thru an observer pattern and the magic of naming
policies)
The bindings is what is used by the compiler, so what if an
environment
does not importSelf? It means that the variable it declares are not bound, so it is not reachable (kind of invisible class/Global).
IOW, the bindings will contain all the imports, including
self-imports.
importSelf is generally what we want to do, unless weird cases of powerless environment for obfuscation or trustless sandboxing reason.
Now, associationAt: does not speak for itself. It's too hard to
decide
if we're speaking of own declarations or bindings... Analyzing the usage is difficult. bindingAt: would be less ambiguous, so IMO we cannot fix without semantic shift.
This would need as well elaboration as well a separate thread.
The semantic will be carried by the senders (the Tools), and the
tools
by usage we want to make of Environment. So we first have to define
that:
what feature do we want to support? With which tool? That probably require yet another thread...
Yes
--Hannes
On 29 September 2016 at 10:10, Nicolas Cellier < nicolas.cellier.aka.nice@gmail.com> wrote:
2016-09-29 18:39 GMT+02:00 Jakob Reschke jakob.reschke@student.hpi.de:
Many questions should be answered with tooling here, but in the particular case I mentioned, IMHO it is not about tooling. Until now, code that does `Smalltalk at: something` wants to look up something dynamically or it can't be sure that this class is actually loaded. As there was only one place to do such lookups, no differentiation about visibility or the source of a binding was necessary.
Instances of `Smalltalk at: something` should either be replaced by an environment aware equivalent that makes clear if a name should be looked up *only* in the receiving environment (in its declarations), or if a name should be resolved, looking also in imported environments (in the bindings).
Agree
As it is inconvenient to find all these pieces of code and change them all, `Smalltalk (globals)` could be the "active" environment (currently via dynamic scoping with `on: CurrentEnvironment do: ...`), not the original global environment.
I don't like the idea of CurrentEnvironment at all. IMO global state stinks. It would mean that a lotta behavior would change by simply switching one shared variable... I see it more like a not so clever workaround to make tools still work in presence of environments with minimal changes.
Global state does indeed stink, which is why Environments is so nice, because "global" isn't global anymore.
But that's the whole point of CurrentEnvironment - it's a _delimited dynamic variable_, turning formerly actually global state into something context sensitive.
frank
But
then Environment>>at: must behave sensibly. I would expect that I can always do `Smalltalk at: #Object` to retrieve `Object` in any environment (under the assumption that every environment would import the "Kernel" or original environment). This is currently not the case, because Environment>>at: looks only into an environment's (own) declarations, not the imported bindings.
I don't know. Maybe (Smalltalk at: #Foo) is questionable by itself. VW did introduce #{Foo} ifPresent: [:foo | ] or something like that for deferred bindings. I remind you that Smalltalk itself is a global variable created with a different instance for each environment.
Object is in the superclass chain, so we can still access with superclass superclass ... environment.
2016-09-29 17:30 GMT+02:00 Nicolas Cellier <nicolas.cellier.aka.nice@gmai l.com>:
2016-09-29 15:15 GMT+02:00 Jakob Reschke jakob.reschke@student.hpi.de
:
Hi,
Environment>>associationAt: is part of the Smalltalk globals Dictionary compatibility interface, right? As a quick and dirty fix, I changed instances of Smalltalk at: xyz in Monticello code to CurrentEnvironment signal at: xyz, but #at: also only reads in the declarations, so myEnvironment at: #MCWriter or myEnvironment at: #Object returns nil by default. It would make more sense to perform a full lookup via #valueOf:ifAbsent: in #at: and its cousins, wouldn't it?
Best, Jakob
I imagine that the question is about tools. For now Smalltalk importSelf, so bindings and declarations do agree. If an Environment does not importSelf, then some variables will be invisibles (unbounds). Do we still want to see them in some tool, or
not?
What's going on if we play with Alias? Do we want to see the Alias in
some
browser? If not, then we'd better stick with declarations. There is no easy solution. A single facade for two dictionaries cannot
fit
all, so we need several different messages. But it's much about what we want to do with those environments.
2016-09-29 7:33 GMT+02:00 H. Hirzel hannes.hirzel@gmail.com:
On 9/28/16, Nicolas Cellier nicolas.cellier.aka.nice@gmail.com
wrote:
Since we are at reviewing Environment, here is a small detail that bothers me. I already asked some months ago, but silence was the only
response,
so ping.
Implementation of Environment is sometimes not obvious:
- Environment>>associationAt: uses declarations inst.var..
- Environment>>associationOrUndeclaredAt: uses bindings inst.var.
How can it be so different, the selector does not speak, does it?
OK, there is a flag: #review in one of them, but that does not make code clearer, it's just a smell of over-complexity or ill-naming.
Whatever the reason (self explaining code?) Colin does not comment class/methods, that's a fact.
Alternatively a description of the general ideas and the mechanism
would
help.
After all Environments is just a clever combination of a few dictionaries to look up class names? Isn't it? ;-)
However the fact that people did not move on much finalising the implementation of environments since 2012 shows that it is hard to reverse-engineer the intentions from the (incomplete) code.
Chris made the effort of commenting Environment but then came this declarations/bindings split, and the comment did rapidly rot. We have here an un-healthy statu quo crying for change.
So if we want to at least comment the class with the meaning/role/responsibility of inst vars, here is my understanding:
environment bind: #Foo to: 0. just add to the declarations. (You see how names are not obvious: bind does not bind the new
binding
to bindings).
Environments
bind: aSymbol to: anObject | binding newBinding | newBinding := aSymbol => anObject.
binding := declarations associationAt: aSymbol ifAbsent:
[nil].
binding ifNotNil: [binding class == newBinding class ifTrue: [binding value: anObject] ifFalse: [binding becomeForward: newBinding]. ^anObject]. binding := undeclared associationAt: aSymbol ifAbsent: [nil]. binding ifNil: [binding := newBinding] ifNotNil: [undeclared removeKey: aSymbol. binding class == newBinding class ifTrue: [binding value: anObject] ifFalse: [binding becomeForward:
newBinding]].
declarations add: binding. self binding: binding addedTo: self. ^anObject
Could you elaborate a bit please?
If the Environment importSelf, then the ClassBinding/Global also
goes
to bindings... (thru an observer pattern and the magic of naming
policies)
The bindings is what is used by the compiler, so what if an
environment
does not importSelf? It means that the variable it declares are not bound, so it is not reachable (kind of invisible class/Global).
IOW, the bindings will contain all the imports, including
self-imports.
importSelf is generally what we want to do, unless weird cases of powerless environment for obfuscation or trustless sandboxing reason.
Now, associationAt: does not speak for itself. It's too hard to
decide
if we're speaking of own declarations or bindings... Analyzing the
usage
is difficult. bindingAt: would be less ambiguous, so IMO we cannot fix without semantic shift.
This would need as well elaboration as well a separate thread.
The semantic will be carried by the senders (the Tools), and the
tools
by usage we want to make of Environment. So we first have to define
that:
what feature do we want to support? With which tool? That probably
require
yet another thread...
Yes
--Hannes
On 9/29/16, Frank Shearar frank.shearar@gmail.com wrote:
On 29 September 2016 at 10:10, Nicolas Cellier < nicolas.cellier.aka.nice@gmail.com> wrote:
2016-09-29 18:39 GMT+02:00 Jakob Reschke jakob.reschke@student.hpi.de:
Many questions should be answered with tooling here, but in the particular case I mentioned, IMHO it is not about tooling. Until now, code that does `Smalltalk at: something` wants to look up something dynamically or it can't be sure that this class is actually loaded. As there was only one place to do such lookups, no differentiation about visibility or the source of a binding was necessary.
Instances of `Smalltalk at: something` should either be replaced by an environment aware equivalent that makes clear if a name should be looked up *only* in the receiving environment (in its declarations), or if a name should be resolved, looking also in imported environments (in the bindings).
Agree
As it is inconvenient to find all these pieces of code and change them all, `Smalltalk (globals)` could be the "active" environment (currently via dynamic scoping with `on: CurrentEnvironment do: ...`), not the original global environment.
I don't like the idea of CurrentEnvironment at all. IMO global state stinks. It would mean that a lotta behavior would change by simply switching one shared variable... I see it more like a not so clever workaround to make tools still work in presence of environments with minimal changes.
Global state does indeed stink, which is why Environments is so nice, because "global" isn't global anymore.
But that's the whole point of CurrentEnvironment - it's a _delimited dynamic variable_, turning formerly actually global state into something context sensitive.
Environment current
is parallel to
Project current
I think this is OK.
@Frank, could you elaborate please what you mean with '_delimited dynamic variable_' ?
--Hannes
frank
But
then Environment>>at: must behave sensibly. I would expect that I can always do `Smalltalk at: #Object` to retrieve `Object` in any environment (under the assumption that every environment would import the "Kernel" or original environment). This is currently not the case, because Environment>>at: looks only into an environment's (own) declarations, not the imported bindings.
I don't know. Maybe (Smalltalk at: #Foo) is questionable by itself. VW did introduce #{Foo} ifPresent: [:foo | ] or something like that for deferred bindings. I remind you that Smalltalk itself is a global variable created with a different instance for each environment.
Object is in the superclass chain, so we can still access with superclass superclass ... environment.
2016-09-29 17:30 GMT+02:00 Nicolas Cellier <nicolas.cellier.aka.nice@gmai l.com>:
2016-09-29 15:15 GMT+02:00 Jakob Reschke jakob.reschke@student.hpi.de
:
Hi,
Environment>>associationAt: is part of the Smalltalk globals Dictionary compatibility interface, right? As a quick and dirty fix, I changed instances of Smalltalk at: xyz in Monticello code to CurrentEnvironment signal at: xyz, but #at: also only reads in the declarations, so myEnvironment at: #MCWriter or myEnvironment at: #Object returns nil by default. It would make more sense to perform a full lookup via #valueOf:ifAbsent: in #at: and its cousins, wouldn't it?
Best, Jakob
I imagine that the question is about tools. For now Smalltalk importSelf, so bindings and declarations do agree. If an Environment does not importSelf, then some variables will be invisibles (unbounds). Do we still want to see them in some tool, or
not?
What's going on if we play with Alias? Do we want to see the Alias in
some
browser? If not, then we'd better stick with declarations. There is no easy solution. A single facade for two dictionaries cannot
fit
all, so we need several different messages. But it's much about what we want to do with those environments.
2016-09-29 7:33 GMT+02:00 H. Hirzel hannes.hirzel@gmail.com:
On 9/28/16, Nicolas Cellier nicolas.cellier.aka.nice@gmail.com
wrote:
> Since we are at reviewing Environment, here is a small detail that > bothers > me. I already asked some months ago, but silence was the only
response,
> so > ping. > > Implementation of Environment is sometimes not obvious: > - Environment>>associationAt: uses declarations inst.var.. > - Environment>>associationOrUndeclaredAt: uses bindings inst.var. > How can it be so different, the selector does not speak, does it? > > OK, there is a flag: #review in one of them, but that does not > make > code > clearer, it's just a smell of over-complexity or ill-naming. > > Whatever the reason (self explaining code?) Colin does not comment > class/methods, that's a fact.
Alternatively a description of the general ideas and the mechanism
would
help.
After all Environments is just a clever combination of a few dictionaries to look up class names? Isn't it? ;-)
However the fact that people did not move on much finalising the implementation of environments since 2012 shows that it is hard to reverse-engineer the intentions from the (incomplete) code.
> Chris made the effort of commenting Environment but then came this > declarations/bindings split, and the comment did rapidly rot. > We have here an un-healthy statu quo crying for change. > > So if we want to at least comment the class with the > meaning/role/responsibility of inst vars, here is my > understanding: > > environment bind: #Foo to: 0. just add to the declarations. > (You see how names are not obvious: bind does not bind the new
binding
> to > bindings).
Environments
bind: aSymbol to: anObject | binding newBinding | newBinding := aSymbol => anObject.
binding := declarations associationAt: aSymbol ifAbsent:
[nil].
binding ifNotNil: [binding class == newBinding class ifTrue: [binding value: anObject] ifFalse: [binding becomeForward:
newBinding]. ^anObject].
binding := undeclared associationAt: aSymbol ifAbsent:
[nil]. binding ifNil: [binding := newBinding] ifNotNil: [undeclared removeKey: aSymbol. binding class == newBinding class ifTrue: [binding value: anObject] ifFalse: [binding becomeForward: newBinding]].
declarations add: binding. self binding: binding addedTo: self. ^anObject
Could you elaborate a bit please?
> If the Environment importSelf, then the ClassBinding/Global also
goes
> to > bindings... (thru an observer pattern and the magic of naming
policies)
> > The bindings is what is used by the compiler, so what if an
environment
> does not importSelf? It means that the variable it declares are > not > bound, > so it is not reachable (kind of invisible class/Global). > > IOW, the bindings will contain all the imports, including
self-imports.
> importSelf is generally what we want to do, unless weird cases of > powerless > environment for obfuscation or trustless sandboxing reason. > > Now, associationAt: does not speak for itself. It's too hard to
decide
> if > we're speaking of own declarations or bindings... Analyzing the
usage
> is > difficult. bindingAt: would be less ambiguous, so IMO we cannot > fix > without > semantic shift.
This would need as well elaboration as well a separate thread.
> The semantic will be carried by the senders (the Tools), and the
tools
> by > usage we want to make of Environment. So we first have to define
that:
> what > feature do we want to support? With which tool? That probably
require
> yet > another thread...
Yes
--Hannes
If I inspect
Environment current
I get an Enviroment instance with declarations, bindings, policies and observers as instance variables.
If I do a printit on
Environment current
I get Smalltalk. When I inspect that I get an instance of SmalltalkImage. With the only instance variable 'globals' which is an environment.
What is happening here? Relationship between Environment and SmalltalkImage instance?
On 9/29/16, H. Hirzel hannes.hirzel@gmail.com wrote:
On 9/29/16, Frank Shearar frank.shearar@gmail.com wrote:
On 29 September 2016 at 10:10, Nicolas Cellier < nicolas.cellier.aka.nice@gmail.com> wrote:
2016-09-29 18:39 GMT+02:00 Jakob Reschke jakob.reschke@student.hpi.de:
Many questions should be answered with tooling here, but in the particular case I mentioned, IMHO it is not about tooling. Until now, code that does `Smalltalk at: something` wants to look up something dynamically or it can't be sure that this class is actually loaded. As there was only one place to do such lookups, no differentiation about visibility or the source of a binding was necessary.
Instances of `Smalltalk at: something` should either be replaced by an environment aware equivalent that makes clear if a name should be looked up *only* in the receiving environment (in its declarations), or if a name should be resolved, looking also in imported environments (in the bindings).
Agree
As it is inconvenient to find all these pieces of code and change them all, `Smalltalk (globals)` could be the "active" environment (currently via dynamic scoping with `on: CurrentEnvironment do: ...`), not the original global environment.
I don't like the idea of CurrentEnvironment at all. IMO global state stinks. It would mean that a lotta behavior would change by simply switching one shared variable... I see it more like a not so clever workaround to make tools still work in presence of environments with minimal changes.
Global state does indeed stink, which is why Environments is so nice, because "global" isn't global anymore.
But that's the whole point of CurrentEnvironment - it's a _delimited dynamic variable_, turning formerly actually global state into something context sensitive.
Environment current
is parallel to
Project current
I think this is OK.
@Frank, could you elaborate please what you mean with '_delimited dynamic variable_' ?
--Hannes
frank
But
then Environment>>at: must behave sensibly. I would expect that I can always do `Smalltalk at: #Object` to retrieve `Object` in any environment (under the assumption that every environment would import the "Kernel" or original environment). This is currently not the case, because Environment>>at: looks only into an environment's (own) declarations, not the imported bindings.
I don't know. Maybe (Smalltalk at: #Foo) is questionable by itself. VW did introduce #{Foo} ifPresent: [:foo | ] or something like that for deferred bindings. I remind you that Smalltalk itself is a global variable created with a different instance for each environment.
Object is in the superclass chain, so we can still access with superclass superclass ... environment.
2016-09-29 17:30 GMT+02:00 Nicolas Cellier <nicolas.cellier.aka.nice@gmai l.com>:
2016-09-29 15:15 GMT+02:00 Jakob Reschke jakob.reschke@student.hpi.de
:
Hi,
Environment>>associationAt: is part of the Smalltalk globals Dictionary compatibility interface, right? As a quick and dirty fix, I changed instances of Smalltalk at: xyz in Monticello code to CurrentEnvironment signal at: xyz, but #at: also only reads in the declarations, so myEnvironment at: #MCWriter or myEnvironment at: #Object returns nil by default. It would make more sense to perform a full lookup via #valueOf:ifAbsent: in #at: and its cousins, wouldn't it?
Best, Jakob
I imagine that the question is about tools. For now Smalltalk importSelf, so bindings and declarations do agree. If an Environment does not importSelf, then some variables will be invisibles (unbounds). Do we still want to see them in some tool, or
not?
What's going on if we play with Alias? Do we want to see the Alias in
some
browser? If not, then we'd better stick with declarations. There is no easy solution. A single facade for two dictionaries cannot
fit
all, so we need several different messages. But it's much about what we want to do with those environments.
2016-09-29 7:33 GMT+02:00 H. Hirzel hannes.hirzel@gmail.com: > On 9/28/16, Nicolas Cellier nicolas.cellier.aka.nice@gmail.com
wrote:
>> Since we are at reviewing Environment, here is a small detail >> that >> bothers >> me. I already asked some months ago, but silence was the only
response,
>> so >> ping. >> >> Implementation of Environment is sometimes not obvious: >> - Environment>>associationAt: uses declarations inst.var.. >> - Environment>>associationOrUndeclaredAt: uses bindings inst.var. >> How can it be so different, the selector does not speak, does it? >> >> OK, there is a flag: #review in one of them, but that does not >> make >> code >> clearer, it's just a smell of over-complexity or ill-naming. >> >> Whatever the reason (self explaining code?) Colin does not >> comment >> class/methods, that's a fact. > > Alternatively a description of the general ideas and the mechanism
would
> help. > > After all Environments is just a clever combination of a few > dictionaries to look up class names? Isn't it? ;-) > > However the fact that people did not move on much finalising the > implementation of environments since 2012 shows that it is hard > to > reverse-engineer the intentions from the (incomplete) code. > > > > > >> Chris made the effort of commenting Environment but then came >> this >> declarations/bindings split, and the comment did rapidly rot. >> We have here an un-healthy statu quo crying for change. >> >> So if we want to at least comment the class with the >> meaning/role/responsibility of inst vars, here is my >> understanding: >> >> environment bind: #Foo to: 0. just add to the declarations. >> (You see how names are not obvious: bind does not bind the new
binding
>> to >> bindings). > > Environments > > bind: aSymbol to: anObject > | binding newBinding | > newBinding := aSymbol => anObject. > > binding := declarations associationAt: aSymbol ifAbsent:
[nil].
> binding ifNotNil: > [binding class == newBinding class > ifTrue: [binding value: anObject] > ifFalse: [binding becomeForward: > newBinding]. > ^anObject]. > > binding := undeclared associationAt: aSymbol ifAbsent: > [nil]. > binding > ifNil: [binding := newBinding] > ifNotNil: > [undeclared removeKey: aSymbol. > binding class == newBinding class > ifTrue: [binding value: anObject] > ifFalse: [binding becomeForward: > newBinding]]. > > declarations add: binding. > self binding: binding addedTo: self. > ^anObject > > > Could you elaborate a bit please? > > > > >> If the Environment importSelf, then the ClassBinding/Global also
goes
>> to >> bindings... (thru an observer pattern and the magic of naming
policies)
>> >> The bindings is what is used by the compiler, so what if an
environment
>> does not importSelf? It means that the variable it declares are >> not >> bound, >> so it is not reachable (kind of invisible class/Global). >> >> IOW, the bindings will contain all the imports, including
self-imports.
>> importSelf is generally what we want to do, unless weird cases of >> powerless >> environment for obfuscation or trustless sandboxing reason. >> >> Now, associationAt: does not speak for itself. It's too hard to
decide
>> if >> we're speaking of own declarations or bindings... Analyzing the
usage
>> is >> difficult. bindingAt: would be less ambiguous, so IMO we cannot >> fix >> without >> semantic shift. > > This would need as well elaboration as well a separate thread. > > >> The semantic will be carried by the senders (the Tools), and the
tools
>> by >> usage we want to make of Environment. So we first have to define
that:
>> what >> feature do we want to support? With which tool? That probably
require
>> yet >> another thread... > > Yes > > --Hannes >
On 29 September 2016 at 10:42, H. Hirzel hannes.hirzel@gmail.com wrote:
On 9/29/16, Frank Shearar frank.shearar@gmail.com wrote:
On 29 September 2016 at 10:10, Nicolas Cellier < nicolas.cellier.aka.nice@gmail.com> wrote:
2016-09-29 18:39 GMT+02:00 Jakob Reschke jakob.reschke@student.hpi.de
:
Many questions should be answered with tooling here, but in the particular case I mentioned, IMHO it is not about tooling. Until now, code that does `Smalltalk at: something` wants to look up something dynamically or it can't be sure that this class is actually loaded. As there was only one place to do such lookups, no differentiation about visibility or the source of a binding was necessary.
Instances of `Smalltalk at: something` should either be replaced by an environment aware equivalent that makes clear if a name should be looked up *only* in the receiving environment (in its declarations), or if a name should be resolved, looking also in imported environments (in the bindings).
Agree
As it is inconvenient to find all these pieces of code and change them all, `Smalltalk (globals)` could be the "active" environment (currently via dynamic scoping with `on: CurrentEnvironment do: ...`), not the original global environment.
I don't like the idea of CurrentEnvironment at all. IMO global state stinks. It would mean that a lotta behavior would change by simply switching one shared variable... I see it more like a not so clever workaround to make tools still work
in
presence of environments with minimal changes.
Global state does indeed stink, which is why Environments is so nice, because "global" isn't global anymore.
But that's the whole point of CurrentEnvironment - it's a _delimited dynamic variable_, turning formerly actually global state into something context sensitive.
Environment current
is parallel to
Project current
I think this is OK.
@Frank, could you elaborate please what you mean with '_delimited dynamic variable_' ?
Well, I like to be precise with my terminology. The tl;dr is that a delimited dynamic variable is just like what other people call a dynamic variable, except it plays nicely with stack slicing. The throw-a-Notification-get-an-answer idiom is exactly equivalent to delimited dynamic variables
http://lists.squeakfoundation.org/pipermail/squeak-dev/2014-February/176777.... has a bit of a conversation around the topic, and has pointers to in-depth articles on delimited dynamic binding, and I've done my small part in trying to dig into the topic here: http://www.lshift.net/blog/2012/06/27/resumable-exceptions-can-macro-express... .
Anyway, the fundamental point I was trying to make is that using a Notification (CurrentEnvironment) is exactly avoiding global state, but it seems I missed the point that you and Nicolas were making, around various things having a #environment property.
frank
--Hannes
frank
But
then Environment>>at: must behave sensibly. I would expect that I can always do `Smalltalk at: #Object` to retrieve `Object` in any environment (under the assumption that every environment would import the "Kernel" or original environment). This is currently not the case, because Environment>>at: looks only into an environment's (own) declarations, not the imported bindings.
I don't know. Maybe (Smalltalk at: #Foo) is questionable by itself. VW did introduce #{Foo} ifPresent: [:foo | ] or something like that for deferred bindings. I remind you that Smalltalk itself is a global variable created with a different instance for each environment.
Object is in the superclass chain, so we can still access with
superclass
superclass ... environment.
2016-09-29 17:30 GMT+02:00 Nicolas Cellier <nicolas.cellier.aka.nice@gmai l.com>:
2016-09-29 15:15 GMT+02:00 Jakob Reschke jakob.reschke@student.hpi.de
:
Hi,
Environment>>associationAt: is part of the Smalltalk globals Dictionary compatibility interface, right? As a quick and dirty fix, I changed instances of Smalltalk at: xyz in Monticello code to CurrentEnvironment signal at: xyz, but #at: also only reads in the declarations, so myEnvironment at: #MCWriter or myEnvironment at: #Object returns nil by default. It would make more sense to perform
a
full lookup via #valueOf:ifAbsent: in #at: and its cousins, wouldn't it?
Best, Jakob
I imagine that the question is about tools. For now Smalltalk importSelf, so bindings and declarations do agree. If an Environment does not importSelf, then some variables will be invisibles (unbounds). Do we still want to see them in some tool, or
not?
What's going on if we play with Alias? Do we want to see the Alias in
some
browser? If not, then we'd better stick with declarations. There is no easy solution. A single facade for two dictionaries
cannot
fit
all, so we need several different messages. But it's much about what we want to do with those environments.
2016-09-29 7:33 GMT+02:00 H. Hirzel hannes.hirzel@gmail.com: > On 9/28/16, Nicolas Cellier nicolas.cellier.aka.nice@gmail.com
wrote:
>> Since we are at reviewing Environment, here is a small detail
that
>> bothers >> me. I already asked some months ago, but silence was the only
response,
>> so >> ping. >> >> Implementation of Environment is sometimes not obvious: >> - Environment>>associationAt: uses declarations inst.var.. >> - Environment>>associationOrUndeclaredAt: uses bindings
inst.var.
>> How can it be so different, the selector does not speak, does it? >> >> OK, there is a flag: #review in one of them, but that does not >> make >> code >> clearer, it's just a smell of over-complexity or ill-naming. >> >> Whatever the reason (self explaining code?) Colin does not
comment
>> class/methods, that's a fact. > > Alternatively a description of the general ideas and the mechanism
would
> help. > > After all Environments is just a clever combination of a few > dictionaries to look up class names? Isn't it? ;-) > > However the fact that people did not move on much finalising the > implementation of environments since 2012 shows that it is hard
to
> reverse-engineer the intentions from the (incomplete) code. > > > > > >> Chris made the effort of commenting Environment but then came
this
>> declarations/bindings split, and the comment did rapidly rot. >> We have here an un-healthy statu quo crying for change. >> >> So if we want to at least comment the class with the >> meaning/role/responsibility of inst vars, here is my >> understanding: >> >> environment bind: #Foo to: 0. just add to the declarations. >> (You see how names are not obvious: bind does not bind the new
binding
>> to >> bindings). > > Environments > > bind: aSymbol to: anObject > | binding newBinding | > newBinding := aSymbol => anObject. > > binding := declarations associationAt: aSymbol ifAbsent:
[nil].
> binding ifNotNil: > [binding class == newBinding class > ifTrue: [binding value: anObject] > ifFalse: [binding becomeForward: > newBinding]. > ^anObject]. > > binding := undeclared associationAt: aSymbol ifAbsent: > [nil]. > binding > ifNil: [binding := newBinding] > ifNotNil: > [undeclared removeKey: aSymbol. > binding class == newBinding class > ifTrue: [binding value: anObject] > ifFalse: [binding becomeForward: > newBinding]]. > > declarations add: binding. > self binding: binding addedTo: self. > ^anObject > > > Could you elaborate a bit please? > > > > >> If the Environment importSelf, then the ClassBinding/Global also
goes
>> to >> bindings... (thru an observer pattern and the magic of naming
policies)
>> >> The bindings is what is used by the compiler, so what if an
environment
>> does not importSelf? It means that the variable it declares are >> not >> bound, >> so it is not reachable (kind of invisible class/Global). >> >> IOW, the bindings will contain all the imports, including
self-imports.
>> importSelf is generally what we want to do, unless weird cases of >> powerless >> environment for obfuscation or trustless sandboxing reason. >> >> Now, associationAt: does not speak for itself. It's too hard to
decide
>> if >> we're speaking of own declarations or bindings... Analyzing the
usage
>> is >> difficult. bindingAt: would be less ambiguous, so IMO we cannot >> fix >> without >> semantic shift. > > This would need as well elaboration as well a separate thread. > > >> The semantic will be carried by the senders (the Tools), and the
tools
>> by >> usage we want to make of Environment. So we first have to define
that:
>> what >> feature do we want to support? With which tool? That probably
require
>> yet >> another thread... > > Yes > > --Hannes >
On 29.09.2016, at 20:57, Frank Shearar frank.shearar@gmail.com wrote:
Environment current
is parallel to
Project current
I think this is OK.
@Frank, could you elaborate please what you mean with '_delimited dynamic variable_' ?
Well, I like to be precise with my terminology. The tl;dr is that a delimited dynamic variable is just like what other people call a dynamic variable, except it plays nicely with stack slicing. The throw-a-Notification-get-an-answer idiom is exactly equivalent to delimited dynamic variables
http://lists.squeakfoundation.org/pipermail/squeak-dev/2014-February/176777.... has a bit of a conversation around the topic, and has pointers to in-depth articles on delimited dynamic binding, and I've done my small part in trying to dig into the topic here: http://www.lshift.net/blog/2012/06/27/resumable-exceptions-can-macro-express....
Anyway, the fundamental point I was trying to make is that using a Notification (CurrentEnvironment) is exactly avoiding global state, but it seems I missed the point that you and Nicolas were making, around various things having a #environment property.
A note: The first time I had seen a dynamic variable was in seaside where it is/was used for accessing the 'request context' (Being a web framework, this thingy described the HTTP request received by the framework).
To access that, you call
self requestContext zork
in you seaside class, which boils down to
requestContext
^ CurrentRequestContext value
And CurrentRequestContext being a Dynamic Variable implemented as Notification.
However, since then, we have merged in the DynamicVariable as ProcessSpecificVariable contributed by Martin von Löwis. This provides a more efficient way to 'resolve' the DV to a value, because the Notification-based DV needs to peel the stack and re-built it (particularly hurting Cog) whereas the ProcessSpecificVariable-based DV 'just' needs some Dict-lookups in the current Process.
========
I quite like accessing the current Environment via a dynamic variable, as it exactly provides the control-flow scope that is necessary for this kind of thing.
We should however adopt a proper DV here, increasing efficiency and readability. No more 'CurrentEnvironment signal ifNil: […]'
but rather Object>>environment
^ CurrentEnvironment value
and
DynamicVariable subclass: #CurrentEnvironment instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: '...' and CurrentEnvironment class>>default
^ Smalltalk globals
and then, for example
EnvironmentLoader>>evaluate: chunk
^ CurrentEnvironment use: environment during: [Compiler evaluate: chunk environment: environment]
(not tested, tho)
Best regards -Tobias
PS: I sometimes call DVs semi-globals. not really global, not really non-global…
On 29 September 2016 at 12:19, Tobias Pape Das.Linux@gmx.de wrote:
On 29.09.2016, at 20:57, Frank Shearar frank.shearar@gmail.com wrote:
Environment current
is parallel to
Project current
I think this is OK.
@Frank, could you elaborate please what you mean with '_delimited dynamic variable_' ?
Well, I like to be precise with my terminology. The tl;dr is that a
delimited dynamic variable is just like what other people call a dynamic variable, except it plays nicely with stack slicing. The throw-a-Notification-get-an-answer idiom is exactly equivalent to delimited dynamic variables
http://lists.squeakfoundation.org/pipermail/squeak-dev/2014-
February/176777.html has a bit of a conversation around the topic, and has pointers to in-depth articles on delimited dynamic binding, and I've done my small part in trying to dig into the topic here: http://www.lshift.net/blog/2012/06/27/resumable- exceptions-can-macro-express-delimited-dynamic-variables/.
Anyway, the fundamental point I was trying to make is that using a
Notification (CurrentEnvironment) is exactly avoiding global state, but it seems I missed the point that you and Nicolas were making, around various things having a #environment property.
A note: The first time I had seen a dynamic variable was in seaside where it is/was used for accessing the 'request context' (Being a web framework, this thingy described the HTTP request received by the framework).
To access that, you call
self requestContext zork
in you seaside class, which boils down to
requestContext ^ CurrentRequestContext value
And CurrentRequestContext being a Dynamic Variable implemented as Notification.
However, since then, we have merged in the DynamicVariable as ProcessSpecificVariable contributed by Martin von Löwis. This provides a more efficient way to 'resolve' the DV to a value, because the Notification-based DV needs to peel the stack and re-built it (particularly hurting Cog) whereas the ProcessSpecificVariable-based DV 'just' needs some Dict-lookups in the current Process.
This is why I like being specific in terminology. Yes, the thing called DynamicVariable in Squeak trunk is a dynamic variable, and not a delimited dynamic variable, which is exactly why you cannot combine using DynamicVariable and stack manipulations. Debugging happens to do said stack manipulations.
Yes, the Notification idiom is much less efficient (in its current implementation (*)) than DynamicVariable, but DynamicVariable fundamentally cannot work correctly with stack manipulations. Oleg Kiselyov covers the issue in depth in the various articles linked to from http://okmij.org/ftp/Computation/dynamic-binding.html#DDBinding.
(*) I would imagine that VM support would allow for efficient delimited dynamic variables, because Henry Baker wrote a whole pile of papers back in the late 70s on the subject (see http://www.pipeline.com/~hbaker1/home.html, for instance "Shallow Binding Makes Functional Arrays Fast".
frank
========
I quite like accessing the current Environment via a dynamic variable, as it exactly provides the control-flow scope that is necessary for this kind of thing.
We should however adopt a proper DV here, increasing efficiency and readability. No more 'CurrentEnvironment signal ifNil: […]'
but rather
Object>>environment ^ CurrentEnvironment value
and
DynamicVariable subclass: #CurrentEnvironment instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: '...'
and CurrentEnvironment class>>default
^ Smalltalk globals
and then, for example
EnvironmentLoader>>evaluate: chunk ^ CurrentEnvironment use: environment during: [Compiler evaluate: chunk environment: environment]
(not tested, tho)
Best regards -Tobias
PS: I sometimes call DVs semi-globals. not really global, not really non-global…
On 30.09.2016, at 02:02, Frank Shearar frank.shearar@gmail.com wrote:
On 29 September 2016 at 12:19, Tobias Pape Das.Linux@gmx.de wrote:
On 29.09.2016, at 20:57, Frank Shearar frank.shearar@gmail.com wrote:
Environment current
is parallel to
Project current
I think this is OK.
@Frank, could you elaborate please what you mean with '_delimited dynamic variable_' ?
Well, I like to be precise with my terminology. The tl;dr is that a delimited dynamic variable is just like what other people call a dynamic variable, except it plays nicely with stack slicing. The throw-a-Notification-get-an-answer idiom is exactly equivalent to delimited dynamic variables
http://lists.squeakfoundation.org/pipermail/squeak-dev/2014-February/176777.... has a bit of a conversation around the topic, and has pointers to in-depth articles on delimited dynamic binding, and I've done my small part in trying to dig into the topic here: http://www.lshift.net/blog/2012/06/27/resumable-exceptions-can-macro-express....
Anyway, the fundamental point I was trying to make is that using a Notification (CurrentEnvironment) is exactly avoiding global state, but it seems I missed the point that you and Nicolas were making, around various things having a #environment property.
A note: The first time I had seen a dynamic variable was in seaside where it is/was used for accessing the 'request context' (Being a web framework, this thingy described the HTTP request received by the framework).
To access that, you call
self requestContext zork
in you seaside class, which boils down to
requestContext ^ CurrentRequestContext value
And CurrentRequestContext being a Dynamic Variable implemented as Notification.
However, since then, we have merged in the DynamicVariable as ProcessSpecificVariable contributed by Martin von Löwis. This provides a more efficient way to 'resolve' the DV to a value, because the Notification-based DV needs to peel the stack and re-built it (particularly hurting Cog) whereas the ProcessSpecificVariable-based DV 'just' needs some Dict-lookups in the current Process.
This is why I like being specific in terminology. Yes, the thing called DynamicVariable in Squeak trunk is a dynamic variable, and not a delimited dynamic variable, which is exactly why you cannot combine using DynamicVariable and stack manipulations. Debugging happens to do said stack manipulations.
Ok, I think I understand, but doesn't the [ ] ensure: [] in DynamicVariable class>>value:during: take care of the delimition?
Yes, the Notification idiom is much less efficient (in its current implementation (*)) than DynamicVariable, but DynamicVariable fundamentally cannot work correctly with stack manipulations. Oleg Kiselyov covers the issue in depth in the various articles linked to from http://okmij.org/ftp/Computation/dynamic-binding.html#DDBinding.
(*) I would imagine that VM support would allow for efficient delimited dynamic variables, because Henry Baker wrote a whole pile of papers back in the late 70s on the subject (see http://www.pipeline.com/~hbaker1/home.html, for instance "Shallow Binding Makes Functional Arrays Fast".
frank
========
I quite like accessing the current Environment via a dynamic variable, as it exactly provides the control-flow scope that is necessary for this kind of thing.
We should however adopt a proper DV here, increasing efficiency and readability. No more 'CurrentEnvironment signal ifNil: […]'
but rather
Object>>environment ^ CurrentEnvironment value
and
DynamicVariable subclass: #CurrentEnvironment instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: '...'
and CurrentEnvironment class>>default
^ Smalltalk globals
and then, for example
EnvironmentLoader>>evaluate: chunk ^ CurrentEnvironment use: environment during: [Compiler evaluate: chunk environment: environment]
(not tested, tho)
Best regards -Tobias
PS: I sometimes call DVs semi-globals. not really global, not really non-global…
I don't like the idea of CurrentEnvironment at all. IMO global state stinks. It would mean that a lotta behavior would change by simply switching one shared variable... I see it more like a not so clever workaround to make tools still work in presence of environments with minimal changes.
Global state does indeed stink, which is why Environments is so nice, because "global" isn't global anymore.
This deserves some qualification. Its true that writable globals stink, you never know what state its going to be in, and updating it introduces contention, etc. However, Class names don't suddenly point to a different class object within the context of a running application, and no one ever replaces Smalltalk with a new instance. These globals are just "there" -- read-only bindings which don't suffer the stinky issues associated with writable globals.
I'm glad Nicolas started the other thread asking "what's it for?" To me, that's the most important question -- is there something actually truly useful gained in exchange for complicating the language and tools? Is it only about everyone being able to have elegant, prefix-less class names all loaded into one image? Most of the use-cases mentioned in this and the other threads were just "cool ways to handle a one-off problem."
For the real world, we have been wanting smaller, more modular images. The conditions of having less code and responsibility in those smaller images bodes them less likely to benefit from Environments. Multiple small images passing messages over the network lets those Smalltalk applications run on multiple processor cores, compared to one monolithic image with all the code loaded and disambiguated via a hierarchy of Environment imports/exports and running on just one process core.
In 15 years, I think I've had just one name collision between classes of different packages (neither of which used prefixes). I think I simply renamed one of them. Dynamic system. With Environments, I would still have had to write some code to do various imports/exports/renames, etc.. and so it doesn't actually save me any development effort. I guess it boils down to letting me keep pretty, but ambiguous, names in the code. But, I actually prefer prefixes...
Not trying to be a party pooper, but complexity is commonplace, simplicity is rare. If we still have a simple system, we should value that aspect and try to keep it that way. At least _optionally_...
Best, Chris
In 15 years, I think I've had just one name collision between classes of different packages (neither of which used prefixes). I think I simply renamed one of them. Dynamic system. With Environments, I would still have had to write some code to do various imports/exports/renames, etc.. and so it doesn't actually save me any development effort. I guess it boils down to letting me keep pretty, but ambiguous, names in the code. But, I actually prefer prefixes...
Not trying to be a party pooper, but complexity is commonplace, simplicity is rare. If we still have a simple system, we should value that aspect and try to keep it that way. At least _optionally_...
+1
Stef
On 30 September 2016 at 14:36, Chris Muller asqueaker@gmail.com wrote:
I don't like the idea of CurrentEnvironment at all. IMO global state stinks. It would mean that a lotta behavior would change by simply switching one shared variable... I see it more like a not so clever workaround to make tools still work
in
presence of environments with minimal changes.
Global state does indeed stink, which is why Environments is so nice, because "global" isn't global anymore.
This deserves some qualification. Its true that writable globals stink, you never know what state its going to be in, and updating it introduces contention, etc. However, Class names don't suddenly point to a different class object within the context of a running application, and no one ever replaces Smalltalk with a new instance. These globals are just "there" -- read-only bindings which don't suffer the stinky issues associated with writable globals.
I'm glad Nicolas started the other thread asking "what's it for?" To me, that's the most important question -- is there something actually truly useful gained in exchange for complicating the language and tools? Is it only about everyone being able to have elegant, prefix-less class names all loaded into one image? Most of the use-cases mentioned in this and the other threads were just "cool ways to handle a one-off problem."
For the real world, we have been wanting smaller, more modular images. The conditions of having less code and responsibility in those smaller images bodes them less likely to benefit from Environments. Multiple small images passing messages over the network lets those Smalltalk applications run on multiple processor cores, compared to one monolithic image with all the code loaded and disambiguated via a hierarchy of Environment imports/exports and running on just one process core.
In 15 years, I think I've had just one name collision between classes of different packages (neither of which used prefixes). I think I simply renamed one of them. Dynamic system. With Environments, I would still have had to write some code to do various imports/exports/renames, etc.. and so it doesn't actually save me any development effort. I guess it boils down to letting me keep pretty, but ambiguous, names in the code. But, I actually prefer prefixes...
Not trying to be a party pooper, but complexity is commonplace, simplicity is rare. If we still have a simple system, we should value that aspect and try to keep it that way. At least _optionally_...
Best, Chris
Well, there's simple, and there's simplistic, and these are not the same thing. Environments abstracts, and makes uniform, the binding of names to variables (which includes classes and globals). Instead of the single, and therefore specialised, and therefore apt to make klunky, mapping of names to things, the implementing of Environments focuses attention on a often neglected part of programming.
But I've had these discussions before, and I don't have the energy to pursue them, therefore I don't really have a voice in the matter.
I am, however, sick to death of things being invented in Smalltalk, only to die in its birthplace, while the rest of the world sees value, and wholeheartedly takes up the concept. I'm not saying you're doing this now, Chris, but I have often, often heard people in the Squeak community say "oh, it was Too Complicated, it Wasn't Simple, Not Worth It" while Ruby, Perl, Clojure, Fortress, Scala all say "yep, great idea, thanks!".
frank
Frank,
you write
'Environments abstracts, and makes uniform, the binding of names to variables (which includes classes and globals).
the implementing of Environments focuses attention on a often neglected part of programming.'
This is what we are looking for. An explanation of the _concept_ behind environments. This concept is not obvious for most people here on the list......
On 10/1/16, Frank Shearar frank.shearar@gmail.com wrote:
On 30 September 2016 at 14:36, Chris Muller asqueaker@gmail.com wrote:
I don't like the idea of CurrentEnvironment at all. IMO global state stinks. It would mean that a lotta behavior would change by simply switching one shared variable... I see it more like a not so clever workaround to make tools still work
in
presence of environments with minimal changes.
Global state does indeed stink, which is why Environments is so nice, because "global" isn't global anymore.
This deserves some qualification. Its true that writable globals stink, you never know what state its going to be in, and updating it introduces contention, etc. However, Class names don't suddenly point to a different class object within the context of a running application, and no one ever replaces Smalltalk with a new instance. These globals are just "there" -- read-only bindings which don't suffer the stinky issues associated with writable globals.
I'm glad Nicolas started the other thread asking "what's it for?" To me, that's the most important question -- is there something actually truly useful gained in exchange for complicating the language and tools? Is it only about everyone being able to have elegant, prefix-less class names all loaded into one image? Most of the use-cases mentioned in this and the other threads were just "cool ways to handle a one-off problem."
For the real world, we have been wanting smaller, more modular images. The conditions of having less code and responsibility in those smaller images bodes them less likely to benefit from Environments. Multiple small images passing messages over the network lets those Smalltalk applications run on multiple processor cores, compared to one monolithic image with all the code loaded and disambiguated via a hierarchy of Environment imports/exports and running on just one process core.
In 15 years, I think I've had just one name collision between classes of different packages (neither of which used prefixes). I think I simply renamed one of them. Dynamic system. With Environments, I would still have had to write some code to do various imports/exports/renames, etc.. and so it doesn't actually save me any development effort. I guess it boils down to letting me keep pretty, but ambiguous, names in the code. But, I actually prefer prefixes...
Not trying to be a party pooper, but complexity is commonplace, simplicity is rare. If we still have a simple system, we should value that aspect and try to keep it that way. At least _optionally_...
Best, Chris
Well, there's simple, and there's simplistic, and these are not the same thing. Environments abstracts, and makes uniform, the binding of names to variables (which includes classes and globals). Instead of the single, and therefore specialised, and therefore apt to make klunky, mapping of names to things, the implementing of Environments focuses attention on a often neglected part of programming.
But I've had these discussions before, and I don't have the energy to pursue them, therefore I don't really have a voice in the matter.
I am, however, sick to death of things being invented in Smalltalk, only to die in its birthplace, while the rest of the world sees value, and wholeheartedly takes up the concept. I'm not saying you're doing this now, Chris, but I have often, often heard people in the Squeak community say "oh, it was Too Complicated, it Wasn't Simple, Not Worth It" while Ruby, Perl, Clojure, Fortress, Scala all say "yep, great idea, thanks!".
frank
This is what we are looking for. An explanation of the _concept_ behind environments. This concept is not obvious for most people here on the list......
Right. I have been asking for documentation, and got silence for an answer. How serious is that ? We need to RTFM.
Stef
On 01-10-2016, at 4:42 PM, Stéphane Rollandin lecteur@zogotounga.net wrote:
This is what we are looking for. An explanation of the _concept_ behind environments. This concept is not obvious for most people here on the list......
Right. I have been asking for documentation, and got silence for an answer. How serious is that ? We need to RTFM.
There must of course be a decent manual (or collection of writings that constitute a manual) because *nobody* would do something stupid like adding a bunch of code that doesn’t have an obvious reason for being or an explanation of how to use it, or examples. It just couldn’t happen.
tim -- tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim Four wheels move the body. Two wheels move the soul
There must of course be a decent manual (or collection of writings that constitute a manual) because *nobody* would do something stupid like adding a bunch of code that doesn’t have an obvious reason for being or an explanation of how to use it, or examples. It just couldn’t happen.
Ok, I know this is Squeak's tradition.
The fact is I'm genuinely interested in Environments, as I used to be interested in Traits but never did anything with it because of the missing support.
What a waste.
Stef
We should go Cuis simpler Smalltalk. We NEED a Kernel and a Core Squeak without experiments. And people should be able to load Traits or Environments or SeeWhatCoolIsThese if they choose to do so. And the rest of us live without pain.
By the way Alejandro Reimondo have his old Fenix image builder as subclass of Environments of Dan Ingalls and Guille Polito and Pharo guys have his Kernel building tool as kind of Environments .
Edgar
On Oct 3, 2016, at 02:49, Stéphane Rollandin lecteur@zogotounga.net wrote:
There must of course be a decent manual (or collection of writings that constitute a manual) because *nobody* would do something stupid like adding a bunch of code that doesn’t have an obvious reason for being or an explanation of how to use it, or examples. It just couldn’t happen.
Ok, I know this is Squeak's tradition.
The fact is I'm genuinely interested in Environments, as I used to be interested in Traits but never did anything with it because of the missing support.
What a waste.
Stef
On Mon, 3 Oct 2016, Edgar De Cleene wrote:
We should go Cuis simpler Smalltalk.
Sure. Just port Squeak on top of Cuis without losing functionality and performance.
Levente
We NEED a Kernel and a Core Squeak without experiments. And people should be able to load Traits or Environments or SeeWhatCoolIsThese if they choose to do so. And the rest of us live without pain.
By the way Alejandro Reimondo have his old Fenix image builder as subclass of Environments of Dan Ingalls and Guille Polito and Pharo guys have his Kernel building tool as kind of Environments .
Edgar
On Oct 3, 2016, at 02:49, Stéphane Rollandin lecteur@zogotounga.net wrote:
There must of course be a decent manual (or collection of writings that constitute a manual) because *nobody* would do something stupid like adding a bunch of code that doesn’t have an obvious reason for being or an explanation of how to use it, or examples. It just couldn’t happen.
Ok, I know this is Squeak's tradition.
The fact is I'm genuinely interested in Environments, as I used to be interested in Traits but never did anything with it because of the missing support.
What a waste.
Stef
Hi--
Edgar writes:
We NEED a Kernel and a Core Squeak without experiments. And people should be able to load Traits or Environments or SeeWhatCoolIsThese if they choose to do so. And the rest of us live without pain.
By the way Alejandro Reimondo have his old Fenix image builder as subclass of Environments of Dan Ingalls and Guille Polito and Pharo guys have his Kernel building tool as kind of Environments.
I have adapted the Naiad module system[1] to the latest Squeak, and plan to release it this month. Naiad enables loading and unloading modules, so you can maintain a minimal system without experiments.
-C
[1] http://thiscontext.com/naiad
-- Craig Latta Black Page Digital Amsterdam | San Francisco craig@blackpagedigital.com +31 6 2757 7177 (SMS ok) + 1 415 287 3547 (no SMS)
Glad see you still work on this
On 10/4/16, 6:14 AM, "Craig Latta" craig@blackpagedigital.com wrote:
I have adapted the Naiad module system[1] to the latest Squeak, and
plan to release it this month. Naiad enables loading and unloading modules, so you can maintain a minimal system without experiments.
-C
On 02-10-2016, at 10:49 PM, Stéphane Rollandin lecteur@zogotounga.net wrote:
There must of course be a decent manual (or collection of writings that constitute a manual) because *nobody* would do something stupid like adding a bunch of code that doesn’t have an obvious reason for being or an explanation of how to use it, or examples. It just couldn’t happen.
Ok, I know this is Squeak's tradition.
The fact is I'm genuinely interested in Environments, as I used to be interested in Traits but never did anything with it because of the missing support.
What a waste.
Exactly my problem. This was a lot of work and involved a lot of deep futzing and must have had some serious discussion about the design, intent, implementation and usage before anyone agreed to bring it into the main system - surely? Without tool support, examples, descriptions and so on it will end up the same way as Traits and so many other neat ideas.
It doesn’t matter a damn how good an idea is - if it can’t be described so other people can make sense of it and use it (hmm, we could call it ‘documentation’) then it doesn’t exist in any meaningful sense.
tim -- tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim Strange OpCodes: SD: Self Destruct
On 9/29/16, Nicolas Cellier nicolas.cellier.aka.nice@gmail.com wrote:
2016-09-29 18:39 GMT+02:00 Jakob Reschke jakob.reschke@student.hpi.de:
Many questions should be answered with tooling here, but in the particular case I mentioned, IMHO it is not about tooling. Until now, code that does `Smalltalk at: something` wants to look up something dynamically or it can't be sure that this class is actually loaded. As there was only one place to do such lookups, no differentiation about visibility or the source of a binding was necessary.
Instances of `Smalltalk at: something` should either be replaced by an environment aware equivalent that makes clear if a name should be looked up *only* in the receiving environment (in its declarations), or if a name should be resolved, looking also in imported environments (in the bindings).
Agree
As it is inconvenient to find all these pieces of code and change them all, `Smalltalk (globals)` could be the "active" environment (currently via dynamic scoping with `on: CurrentEnvironment do: ...`), not the original global environment.
I don't like the idea of CurrentEnvironment at all. IMO global state stinks.
Sure but we also have
ActiveWorld ActiveHand World ScriptingSystem Smalltalk ActiveEvent Sensor Transcript Display TextConstants ImageImports SystemOrganization
to list just a few.
Every Project (with subclasses MVCProject and MorphicProject) has an instance variable 'environment'. This variable is not used as of now (no access, no stores)
Project current environment (does not work -- yet?)
looks like a natural thing to have. Depending on the project type a project specific environment might be set up when entering the project.
It would mean that a lotta behavior would change by simply switching one shared variable... I see it more like a not so clever workaround to make tools still work in presence of environments with minimal changes.
But then Environment>>at: must behave sensibly. I would expect that I can always do `Smalltalk at: #Object` to retrieve `Object` in any environment (under the assumption that every environment would import the "Kernel" or original environment). This is currently not the case, because Environment>>at: looks only into an environment's (own) declarations, not the imported bindings.
I don't know. Maybe (Smalltalk at: #Foo) is questionable by itself. VW did introduce #{Foo} ifPresent: [:foo | ] or something like that for deferred bindings. I remind you that Smalltalk itself is a global variable created with a different instance for each environment.
Object is in the superclass chain, so we can still access with superclass superclass ... environment.
2016-09-29 17:30 GMT+02:00 Nicolas Cellier <nicolas.cellier.aka.nice@ gmail.com>:
2016-09-29 15:15 GMT+02:00 Jakob Reschke jakob.reschke@student.hpi.de:
Hi,
Environment>>associationAt: is part of the Smalltalk globals Dictionary compatibility interface, right? As a quick and dirty fix, I changed instances of Smalltalk at: xyz in Monticello code to CurrentEnvironment signal at: xyz, but #at: also only reads in the declarations, so myEnvironment at: #MCWriter or myEnvironment at: #Object returns nil by default. It would make more sense to perform a full lookup via #valueOf:ifAbsent: in #at: and its cousins, wouldn't it?
Best, Jakob
I imagine that the question is about tools. For now Smalltalk importSelf, so bindings and declarations do agree. If an Environment does not importSelf, then some variables will be invisibles (unbounds). Do we still want to see them in some tool, or not? What's going on if we play with Alias? Do we want to see the Alias in
some
browser? If not, then we'd better stick with declarations. There is no easy solution. A single facade for two dictionaries cannot
fit
all, so we need several different messages. But it's much about what we want to do with those environments.
2016-09-29 7:33 GMT+02:00 H. Hirzel hannes.hirzel@gmail.com:
On 9/28/16, Nicolas Cellier nicolas.cellier.aka.nice@gmail.com
wrote:
Since we are at reviewing Environment, here is a small detail that bothers me. I already asked some months ago, but silence was the only
response,
so ping.
Implementation of Environment is sometimes not obvious:
- Environment>>associationAt: uses declarations inst.var..
- Environment>>associationOrUndeclaredAt: uses bindings inst.var.
How can it be so different, the selector does not speak, does it?
OK, there is a flag: #review in one of them, but that does not make code clearer, it's just a smell of over-complexity or ill-naming.
Whatever the reason (self explaining code?) Colin does not comment class/methods, that's a fact.
Alternatively a description of the general ideas and the mechanism
would
help.
After all Environments is just a clever combination of a few dictionaries to look up class names? Isn't it? ;-)
However the fact that people did not move on much finalising the implementation of environments since 2012 shows that it is hard to reverse-engineer the intentions from the (incomplete) code.
Chris made the effort of commenting Environment but then came this declarations/bindings split, and the comment did rapidly rot. We have here an un-healthy statu quo crying for change.
So if we want to at least comment the class with the meaning/role/responsibility of inst vars, here is my understanding:
environment bind: #Foo to: 0. just add to the declarations. (You see how names are not obvious: bind does not bind the new
binding
to bindings).
Environments
bind: aSymbol to: anObject | binding newBinding | newBinding := aSymbol => anObject.
binding := declarations associationAt: aSymbol ifAbsent:
[nil].
binding ifNotNil: [binding class == newBinding class ifTrue: [binding value: anObject] ifFalse: [binding becomeForward:
newBinding]. ^anObject].
binding := undeclared associationAt: aSymbol ifAbsent:
[nil]. binding ifNil: [binding := newBinding] ifNotNil: [undeclared removeKey: aSymbol. binding class == newBinding class ifTrue: [binding value: anObject] ifFalse: [binding becomeForward: newBinding]].
declarations add: binding. self binding: binding addedTo: self. ^anObject
Could you elaborate a bit please?
If the Environment importSelf, then the ClassBinding/Global also goes to bindings... (thru an observer pattern and the magic of naming
policies)
The bindings is what is used by the compiler, so what if an
environment
does not importSelf? It means that the variable it declares are not bound, so it is not reachable (kind of invisible class/Global).
IOW, the bindings will contain all the imports, including
self-imports.
importSelf is generally what we want to do, unless weird cases of powerless environment for obfuscation or trustless sandboxing reason.
Now, associationAt: does not speak for itself. It's too hard to
decide
if we're speaking of own declarations or bindings... Analyzing the usage is difficult. bindingAt: would be less ambiguous, so IMO we cannot fix without semantic shift.
This would need as well elaboration as well a separate thread.
The semantic will be carried by the senders (the Tools), and the
tools
by usage we want to make of Environment. So we first have to define
that:
what feature do we want to support? With which tool? That probably require yet another thread...
Yes
--Hannes
squeak-dev@lists.squeakfoundation.org