[squeak-dev] Environment declarations vs bindings

Frank Shearar frank.shearar at gmail.com
Thu Sep 29 18:57:09 UTC 2016


On 29 September 2016 at 10:42, H. Hirzel <hannes.hirzel at gmail.com> wrote:

> On 9/29/16, Frank Shearar <frank.shearar at gmail.com> wrote:
> > On 29 September 2016 at 10:10, Nicolas Cellier <
> > nicolas.cellier.aka.nice at gmail.com> wrote:
> >
> >>
> >>
> >> 2016-09-29 18:39 GMT+02:00 Jakob Reschke <jakob.reschke at student.hpi.de>
> :
> >>
> >>> Many questions should be answered with tooling here, but in the
> >>> particular case I mentioned, IMHO it is not about tooling. Until now,
> >>> code that does `Smalltalk at: something` wants to look up something
> >>> dynamically or it can't be sure that this class is actually loaded. As
> >>> there was only one place to do such lookups, no differentiation about
> >>> visibility or the source of a binding was necessary.
> >>>
> >>> Instances of `Smalltalk at: something` should either be replaced by an
> >>> environment aware equivalent that makes clear if a name should be
> >>> looked up *only* in the receiving environment (in its declarations),
> >>> or if a name should be resolved, looking also in imported environments
> >>> (in the bindings).
> >>
> >>
> >> Agree
> >>
> >>
> >>> As it is inconvenient to find all these pieces of
> >>> code and change them all, `Smalltalk (globals)` could be the "active"
> >>> environment (currently via dynamic scoping with `on:
> >>> CurrentEnvironment do: ...`), not the original global environment.
> >>
> >>
> >> I don't like the idea of CurrentEnvironment at all. IMO global state
> >> stinks.
> >> It would mean that a lotta behavior would change by simply switching one
> >> shared variable...
> >> I see it more like a not so clever workaround to make tools still work
> in
> >> presence of environments with minimal changes.
> >>
> >
> > Global state does indeed stink, which is why Environments is so nice,
> > because "global" isn't global anymore.
> >
> > But that's the whole point of CurrentEnvironment - it's a _delimited
> > dynamic variable_, turning formerly actually global state into something
> > context sensitive.
>
>      Environment current
>
> is parallel to
>
>      Project current
>
> I think this is OK.
>
> @Frank, could you elaborate please what you mean with '_delimited
> dynamic variable_' ?
>

Well, I like to be precise with my terminology. The tl;dr is that a
delimited dynamic variable is just like what other people call a dynamic
variable, except it plays nicely with stack slicing. The
throw-a-Notification-get-an-answer idiom is exactly equivalent to delimited
dynamic variables

http://lists.squeakfoundation.org/pipermail/squeak-dev/2014-February/176777.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 at gmai
> >>> l.com>:
> >>> >
> >>> >
> >>> > 2016-09-29 15:15 GMT+02:00 Jakob Reschke
> >>> > <jakob.reschke at student.hpi.de>
> >>> :
> >>> >>
> >>> >> Hi,
> >>> >>
> >>> >> Environment>>associationAt: is part of the Smalltalk globals
> >>> >> Dictionary compatibility interface, right? As a quick and dirty fix,
> >>> >> I
> >>> >> changed instances of Smalltalk at: xyz in Monticello code to
> >>> >> CurrentEnvironment signal at: xyz, but #at: also only reads in the
> >>> >> declarations, so myEnvironment at: #MCWriter or myEnvironment at:
> >>> >> #Object returns nil by default. It would make more sense to perform
> a
> >>> >> full lookup via #valueOf:ifAbsent: in #at: and its cousins, wouldn't
> >>> >> it?
> >>> >>
> >>> >> Best,
> >>> >> Jakob
> >>> >>
> >>> >
> >>> > I imagine that the question is about tools.
> >>> > For now Smalltalk importSelf, so bindings and declarations do agree.
> >>> > If an Environment does not importSelf, then some variables will be
> >>> > invisibles (unbounds). Do we still want to see them in some tool, or
> >>> not?
> >>> > What's going on if we play with Alias? Do we want to see the Alias in
> >>> some
> >>> > browser? If not, then we'd better stick with declarations.
> >>> > There is no easy solution. A single facade for two dictionaries
> cannot
> >>> fit
> >>> > all, so we need several different messages.
> >>> > But it's much about what we want to do with those environments.
> >>> >
> >>> >
> >>> >>
> >>> >> 2016-09-29 7:33 GMT+02:00 H. Hirzel <hannes.hirzel at gmail.com>:
> >>> >> > On 9/28/16, Nicolas Cellier <nicolas.cellier.aka.nice at gmail.com>
> >>> wrote:
> >>> >> >> Since we are at reviewing Environment, here is a small detail
> that
> >>> >> >> bothers
> >>> >> >> me. I already asked some months ago, but silence was the only
> >>> response,
> >>> >> >> so
> >>> >> >> ping.
> >>> >> >>
> >>> >> >> Implementation of Environment is sometimes not obvious:
> >>> >> >> - Environment>>associationAt: uses declarations inst.var..
> >>> >> >> - Environment>>associationOrUndeclaredAt: uses bindings
> inst.var.
> >>> >> >> How can it be so different, the selector does not speak, does it?
> >>> >> >>
> >>> >> >> OK, there is a flag: #review in one of them, but that does not
> >>> >> >> make
> >>> >> >> code
> >>> >> >> clearer, it's just a smell of over-complexity or ill-naming.
> >>> >> >>
> >>> >> >> Whatever the reason (self explaining code?) Colin does not
> comment
> >>> >> >> class/methods, that's a fact.
> >>> >> >
> >>> >> > Alternatively a description of the general ideas and the mechanism
> >>> would
> >>> >> > help.
> >>> >> >
> >>> >> > After all Environments is just a clever combination of a few
> >>> >> > dictionaries  to look up class names? Isn't it?  ;-)
> >>> >> >
> >>> >> > However the fact that people did not move on much finalising the
> >>> >> > implementation of environments  since 2012 shows that it is hard
> to
> >>> >> > reverse-engineer the intentions from the (incomplete) code.
> >>> >> >
> >>> >> >
> >>> >> >
> >>> >> >
> >>> >> >
> >>> >> >> Chris made the effort of commenting Environment but then came
> this
> >>> >> >> declarations/bindings split, and the comment did rapidly rot.
> >>> >> >> We have here an un-healthy statu quo crying for change.
> >>> >> >>
> >>> >> >> So if we want to at least comment the class with the
> >>> >> >> meaning/role/responsibility of inst vars, here is my
> >>> >> >> understanding:
> >>> >> >>
> >>> >> >> environment bind: #Foo to: 0. just add to the declarations.
> >>> >> >> (You see how names are not obvious: bind does not bind the new
> >>> binding
> >>> >> >> to
> >>> >> >> bindings).
> >>> >> >
> >>> >> > Environments
> >>> >> >
> >>> >> > bind: aSymbol to: anObject
> >>> >> >         | binding newBinding |
> >>> >> >         newBinding := aSymbol => anObject.
> >>> >> >
> >>> >> >         binding := declarations associationAt: aSymbol ifAbsent:
> >>> [nil].
> >>> >> >         binding ifNotNil:
> >>> >> >                 [binding class == newBinding class
> >>> >> >                         ifTrue: [binding value: anObject]
> >>> >> >                         ifFalse: [binding becomeForward:
> >>> >> > newBinding].
> >>> >> >                 ^anObject].
> >>> >> >
> >>> >> >         binding := undeclared associationAt: aSymbol ifAbsent:
> >>> >> > [nil].
> >>> >> >         binding
> >>> >> >                 ifNil: [binding := newBinding]
> >>> >> >                 ifNotNil:
> >>> >> >                         [undeclared removeKey: aSymbol.
> >>> >> >                         binding class == newBinding class
> >>> >> >                                 ifTrue: [binding value: anObject]
> >>> >> >                                 ifFalse: [binding becomeForward:
> >>> >> > newBinding]].
> >>> >> >
> >>> >> >         declarations add: binding.
> >>> >> >         self binding: binding addedTo: self.
> >>> >> >         ^anObject
> >>> >> >
> >>> >> >
> >>> >> > Could you elaborate a bit please?
> >>> >> >
> >>> >> >
> >>> >> >
> >>> >> >
> >>> >> >> If the Environment importSelf, then the ClassBinding/Global also
> >>> goes
> >>> >> >> to
> >>> >> >> bindings... (thru an observer pattern and the magic of naming
> >>> policies)
> >>> >> >>
> >>> >> >> The bindings is what is used by the compiler, so what if an
> >>> environment
> >>> >> >> does not importSelf? It means that the variable it declares are
> >>> >> >> not
> >>> >> >> bound,
> >>> >> >> so it is not reachable (kind of invisible class/Global).
> >>> >> >>
> >>> >> >> IOW, the bindings will contain all the imports, including
> >>> self-imports.
> >>> >> >> importSelf is generally what we want to do, unless weird cases of
> >>> >> >> powerless
> >>> >> >> environment for obfuscation or trustless sandboxing reason.
> >>> >> >>
> >>> >> >> Now, associationAt: does not speak for itself. It's too hard to
> >>> decide
> >>> >> >> if
> >>> >> >> we're speaking of own declarations or bindings... Analyzing the
> >>> usage
> >>> >> >> is
> >>> >> >> difficult. bindingAt: would be less ambiguous, so IMO we cannot
> >>> >> >> fix
> >>> >> >> without
> >>> >> >> semantic shift.
> >>> >> >
> >>> >> > This would need as well elaboration as well a separate thread.
> >>> >> >
> >>> >> >
> >>> >> >> The semantic will be carried by the senders (the Tools), and the
> >>> tools
> >>> >> >> by
> >>> >> >> usage we want to make of Environment. So we first have to define
> >>> that:
> >>> >> >> what
> >>> >> >> feature do we want to support? With which tool? That probably
> >>> require
> >>> >> >> yet
> >>> >> >> another thread...
> >>> >> >
> >>> >> > Yes
> >>> >> >
> >>> >> > --Hannes
> >>> >> >
> >>> >>
> >>> >
> >>>
> >>>
> >>
> >>
> >>
> >>
> >
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20160929/e9506d58/attachment-0001.htm


More information about the Squeak-dev mailing list