Environment declarations vs bindings

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
33 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Environment declarations vs bindings

Nicolas Cellier
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.
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).

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.

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...


Reply | Threaded
Open this post in threaded view
|

Re: Environment declarations vs bindings

Gary Mary
Protecting the environment is very important. It is made up of the very air we breathe, as well as the things which we eat. I would love to answer some of your questions about bothersome details, so ping. For starters, the implementation of the environment in our lives couldn't be more obvious. Like, you literally walk outside and it's like trees and water and ducks and the Taco Bell down the street and it's like: "Woah dude. I'm alive." It's the same thing for us every day. I don't know how it could be less different, and I don't believe in natural selection, it speaks for itself, and it's pretty wild.

On another note, I read a book the other day while I was in school. It was called: "Sus." It went: "Sus." I felt pretty inspired so I went home from school and wrote a story called: "Sus." It went:

"Sussowssaucesoossiissooososousususoes...s..."

I sent it into the paper, still havent heard anything from the editor but I'll let you know how it goes. Nice hearing from you Nicolas!

Sincerely

Gary Mary

On Wed, Sep 28, 2016 at 5:59 PM, Nicolas Cellier <[hidden email]> 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.
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).

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.

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...






Reply | Threaded
Open this post in threaded view
|

Re: Environment declarations vs bindings

Hannes Hirzel
In reply to this post by Nicolas Cellier
On 9/28/16, Nicolas Cellier <[hidden email]> 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

Reply | Threaded
Open this post in threaded view
|

Re: Environment declarations vs bindings

Jakob Reschke-2
In reply to this post by Nicolas Cellier
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

2016-09-29 7:33 GMT+02:00 H. Hirzel <[hidden email]>:

> On 9/28/16, Nicolas Cellier <[hidden email]> 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
>

Reply | Threaded
Open this post in threaded view
|

Re: Environment declarations vs bindings

Nicolas Cellier


2016-09-29 15:15 GMT+02:00 Jakob Reschke <[hidden email]>:
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 <[hidden email]>:
> On 9/28/16, Nicolas Cellier <[hidden email]> 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
>




Reply | Threaded
Open this post in threaded view
|

Re: Environment declarations vs bindings

Jakob Reschke-2
In reply to this post by Jakob Reschke-2
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 <[hidden email]>:

>
>
> 2016-09-29 15:15 GMT+02:00 Jakob Reschke <[hidden email]>:
>>
>> 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 <[hidden email]>:
>> > On 9/28/16, Nicolas Cellier <[hidden email]> 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
>> >
>>
>

Reply | Threaded
Open this post in threaded view
|

Re: Environment declarations vs bindings

Nicolas Cellier
In reply to this post by Hannes Hirzel


2016-09-29 7:33 GMT+02:00 H. Hirzel <[hidden email]>:
On 9/28/16, Nicolas Cellier <[hidden email]> 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.


More than that: we only get core functionalities, the intentions are not written here.
IOW things still are very open.
 



> 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.
This creates either a Global or ClassBinding.
The first one is writeable, the second not.
 

        binding := declarations associationAt: aSymbol ifAbsent: [nil].
A class points to its environment where it is declared.
So we expect this invariant:
    (Foo environment declarationOf: Foo name) value == Foo.
And of course:
    (declarations values select: [:c | c isBehavior]) allSatisfy: [:c | c environment == self].
For globals I don't know why they are attached to a specific environment.
Just because of mechanism for propagating changes?
 
        binding ifNotNil:
                [binding class == newBinding class
                        ifTrue: [binding value: anObject]
                        ifFalse: [binding becomeForward: newBinding].
                ^anObject].


Since we different binding classes we cannot just change the value.
Since bindings are shared by bindings inst. var., CompiledMethods and other environments if we don't use value, we must preserve identity with a become...

Note: above code protects against Object := Array because ClassBinding cannot change value.
But not against Object := 1, become protects nothing. It must be handled somewhere else.
 

        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]].

If we previously had some undeclared reference to such variable name (normally a Global with nil value), it's time to rebind it.
 
        declarations add: binding.
        self binding: binding addedTo: self.
Now propagate the change to every interested observer (those who import declarations from yourself).
 
        ^anObject
like at:put: used to do, we still answer the put object.
 


Could you elaborate a bit please?


See above, by pure reverse engineering ;)



> 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

already opened :)
 

--Hannes




Reply | Threaded
Open this post in threaded view
|

Re: Environment declarations vs bindings

Nicolas Cellier
In reply to this post by Jakob Reschke-2


2016-09-29 18:39 GMT+02:00 Jakob Reschke <[hidden email]>:
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 <[hidden email]>:
>
>
> 2016-09-29 15:15 GMT+02:00 Jakob Reschke <[hidden email]>:
>>
>> 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 <[hidden email]>:
>> > On 9/28/16, Nicolas Cellier <[hidden email]> 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
>> >
>>
>




Reply | Threaded
Open this post in threaded view
|

Re: Environment declarations vs bindings

Frank Shearar-3
On 29 September 2016 at 10:10, Nicolas Cellier <[hidden email]> wrote:


2016-09-29 18:39 GMT+02:00 Jakob Reschke <[hidden email]>:
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 <[hidden email]>:
>
>
> 2016-09-29 15:15 GMT+02:00 Jakob Reschke <[hidden email]>:
>>
>> 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 <[hidden email]>:
>> > On 9/28/16, Nicolas Cellier <[hidden email]> 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
>> >
>>
>








Reply | Threaded
Open this post in threaded view
|

Re: Environment declarations vs bindings

Hannes Hirzel
In reply to this post by Nicolas Cellier
On 9/29/16, Nicolas Cellier <[hidden email]> wrote:

> 2016-09-29 18:39 GMT+02:00 Jakob Reschke <[hidden email]>:
>
>> 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
>> > <[hidden email]>:
>> >>
>> >> 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 <[hidden email]>:
>> >> > On 9/28/16, Nicolas Cellier <[hidden email]>
>> 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
>> >> >
>> >>
>> >
>>
>>
>

Reply | Threaded
Open this post in threaded view
|

Re: Environment declarations vs bindings

Hannes Hirzel
In reply to this post by Frank Shearar-3
On 9/29/16, Frank Shearar <[hidden email]> wrote:

> On 29 September 2016 at 10:10, Nicolas Cellier <
> [hidden email]> wrote:
>
>>
>>
>> 2016-09-29 18:39 GMT+02:00 Jakob Reschke <[hidden email]>:
>>
>>> 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
>>> > <[hidden email]>
>>> :
>>> >>
>>> >> 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 <[hidden email]>:
>>> >> > On 9/28/16, Nicolas Cellier <[hidden email]>
>>> 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
>>> >> >
>>> >>
>>> >
>>>
>>>
>>
>>
>>
>>
>

Reply | Threaded
Open this post in threaded view
|

Re: Environment declarations vs bindings

Hannes Hirzel
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 <[hidden email]> wrote:

> On 9/29/16, Frank Shearar <[hidden email]> wrote:
>> On 29 September 2016 at 10:10, Nicolas Cellier <
>> [hidden email]> wrote:
>>
>>>
>>>
>>> 2016-09-29 18:39 GMT+02:00 Jakob Reschke <[hidden email]>:
>>>
>>>> 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
>>>> > <[hidden email]>
>>>> :
>>>> >>
>>>> >> 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 <[hidden email]>:
>>>> >> > On 9/28/16, Nicolas Cellier <[hidden email]>
>>>> 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
>>>> >> >
>>>> >>
>>>> >
>>>>
>>>>
>>>
>>>
>>>
>>>
>>
>

Reply | Threaded
Open this post in threaded view
|

Re: Environment declarations vs bindings

Frank Shearar-3
In reply to this post by Hannes Hirzel
On 29 September 2016 at 10:42, H. Hirzel <[hidden email]> wrote:
On 9/29/16, Frank Shearar <[hidden email]> wrote:
> On 29 September 2016 at 10:10, Nicolas Cellier <
> [hidden email]> wrote:
>
>>
>>
>> 2016-09-29 18:39 GMT+02:00 Jakob Reschke <[hidden email]>:
>>
>>> 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.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.

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
>>> > <[hidden email]>
>>> :
>>> >>
>>> >> 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 <[hidden email]>:
>>> >> > On 9/28/16, Nicolas Cellier <[hidden email]>
>>> 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
>>> >> >
>>> >>
>>> >
>>>
>>>
>>
>>
>>
>>
>




Reply | Threaded
Open this post in threaded view
|

Re: Environment declarations vs bindings

Tobias Pape

On 29.09.2016, at 20:57, Frank Shearar <[hidden email]> 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.

========

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…


Reply | Threaded
Open this post in threaded view
|

Re: Environment declarations vs bindings

Frank Shearar-3
On 29 September 2016 at 12:19, Tobias Pape <[hidden email]> wrote:

On 29.09.2016, at 20:57, Frank Shearar <[hidden email]> 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…





Reply | Threaded
Open this post in threaded view
|

Re: Environment declarations vs bindings

Tobias Pape

On 30.09.2016, at 02:02, Frank Shearar <[hidden email]> wrote:

> On 29 September 2016 at 12:19, Tobias Pape <[hidden email]> wrote:
>
> On 29.09.2016, at 20:57, Frank Shearar <[hidden email]> 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.

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…
>
>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: Environment declarations vs bindings

Chris Muller-3
In reply to this post by Frank Shearar-3
>> 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

Reply | Threaded
Open this post in threaded view
|

Re: Environment declarations vs bindings

Jakob Reschke-2
In reply to this post by Frank Shearar-3
I suppose nobody of us wants throw everything over and force
Environments onto it. All of this is about opportunities that were
available if Environments could actually be used and operated
intuitively, right? I, too, think that you should not have to care
about Environments if you do not want to. Though, it might be
neccessary or advantageous in some uncommon cases, some of which we
have collected already.

Some code, however, like the loading facilities of Monticello,
currently seem to not play very well together with Environments
(because of the access to the Smalltalk dictionary, how that is
implemented in Environment, and the dynamic binding issue). But if you
cannot load/install something into an Environment and if there are no
(additional) tools to put code into an Environment and then run it,
then how are you supposed to make use of the feature?

Now that I formulated it that way, I think somebody claimed to already
use Environments for something at some point in another, older
discussion. I would like to know how they did it, given Environments'
current state.

If you only refer to the dynamic Environment issue with your comment
about added complexity, an alternate solution would possibly be to add
explicit environment parameters to all facilities that would need them
and that do not have them yet (thinking of Monticello again). But that
seems even more invasive to me and it bloats interfaces if you also
want to keep the existing environment-agnostic interface, which we
certainly want to do.

Kind regards,
Jakob

2016-09-30 23:36 GMT+02:00 Chris Muller <[hidden email]>:

>>> 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
>

Reply | Threaded
Open this post in threaded view
|

Re: Environment declarations vs bindings

Stéphane Rollandin
In reply to this post by Chris Muller-3
> 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


Reply | Threaded
Open this post in threaded view
|

Re: Environment declarations vs bindings

Frank Shearar-3
In reply to this post by Chris Muller-3
On 30 September 2016 at 14:36, Chris Muller <[hidden email]> 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


12