[squeak-dev] The Trunk: Environments-dtl.72.mcz

Jakob Reschke forums.jakob at resfarm.de
Tue Mar 20 22:34:29 UTC 2018


Note that the following also results in ClassBinding:
Smalltalk globals at: #Foo put: ProtoObject.
(Smalltalk globals associationAt: #Foo) class

...so distinguishing globals that are classes from proper classes is
not that easy.

Environment>>allClassesAndTraitsDo: uses the same [key == value name]
condition that Eliot proposed earlier, so it is probably unjustified
that I avoid it. But note further that Environment>>allClassesDo: uses
#isKindOf: to separate classes from traits...

And for the [each environment == self] bit in my code snippet: each
class (and trait) "has" an environment. Since self in this case is the
environment to which #rootClasses was sent, the condition was intended
to filter out those behaviors that are not indigenous to the queried
environment, but bound there nevertheless (myEnv at: #Foo put:
ProtoObject). Additional globals for root classes would be filtered
out by asSet.

2018-03-20 22:49 GMT+01:00 Eliot Miranda <eliot.miranda at gmail.com>:
> Hi Levente,
>
> On Tue, Mar 20, 2018 at 2:38 PM, Levente Uzonyi <leves at caesar.elte.hu>
> wrote:
>>
>> On Tue, 20 Mar 2018, Eliot Miranda wrote:
>>
>>> Hi Jacob,
>>> On Tue, Mar 20, 2018 at 9:06 AM, Jakob Reschke <forums.jakob at resfarm.de>
>>> wrote:
>>>       Hi Eliot,
>>>
>>>       ok, from your answers, it should access the declarations, not the
>>>       bindings of an environment.
>>>
>>>       With your requirement, that could be:
>>>          (self select: [:each | each isBehavior and: [each superclass
>>> isNil
>>>       and: [each environment == self "not misplaced via at:put:"]]])
>>> asSet
>>>       asArray
>>>
>>>
>>> I don't understand "each environment == self".  A comment as to how this
>>> works would be good.  Further, is it not possible to declare a variable
>>> whose value is a root class?
>>
>>
>> With Environments came a new class hierarchy to replace Associations
>> holding bindings: Binding and its subclasses: Alias, ClassBinding and
>> Global.
>
>
> Thanks.  Now I get it.
>
>>
>>
>> A class's binding is always a ClassBinding, a global variable's binding is
>> always a Global, even if it points to a class. Alias wraps another binding
>> and gives it a different name.
>> So, it is fairly easy to detect if a binding is a class, a variable or a
>> "renamed" class or variable.
>> This also means that having an Association in an environment is a bug: an
>> Association is not a Binding.
>> So, the following should only ever return classes declared in the
>> environment:
>>
>>         | roots |
>>         roots := IdentitySet new.
>>         declarations associationsDo: [ :binding |
>>                 binding class == ClassBinding ifTrue: [
>>                         | class |
>>                         (class := binding value) superclass ifNil: [
>>                                 roots add: class ] ] ].
>>         ^roots asArray
>
>
> OK, but a bit hacky.  As you point out below...
>
>>
>>
>> Another way to write it (though it uses a less up-to-date mechanism) if
>> you're only interested in Classes (and not other kinds of Behavior):
>>
>>         | roots |
>>         roots := IdentitySet new.
>>         self allClassesDo: [ :class |
>>                 class superclass ifNil: [ roots add: class ] ].
>>         ^roots asArray
>
>
> Ah, lovely.  This is the right way to write it.
>
>>>       I removed the #value sends because select: only iterates over the
>>>       values of a dictionary(-like object).
>>>
>>>
>>> Good point.
>>>
>>>       I do not like the dependency on
>>>       the names of things, but that could also be an overreaction as the
>>>       result of my endeavor to make the tools work across environments.
>>> ;-)
>>>
>>>
>>> However it works the issue is avoiding duplicates caused by defining
>>> variables whose values are classes.  I used #name as that's the hammer I
>>> know.  I hope there's a better way :-)  Further, I hope you'll
>>> find it :-)
>>
>>
>> See above.
>>
>> Levente
>>
>>
>>>
>>>
>>>       Kind regards,
>>>       Jakob
>>>
>>>
>>>       2018-03-18 17:02 GMT+01:00 Eliot Miranda <eliot.miranda at gmail.com>:
>>>       > Hi Jacob,
>>>       >
>>>       >> On Mar 18, 2018, at 3:40 AM, Jakob Reschke
>>> <forums.jakob at resfarm.de> wrote:
>>>       >>
>>>       >> Hi Eliot,
>>>       >>
>>>       >> Note that self bindings select: is not the same as self select:
>>> for an
>>>       >> Environment, as the latter only enumerates the declarations (its
>>> "own"
>>>       >> bindings).
>>>       >>
>>>       >> Seems like the only sender is Class rootsOfTheWorld, which
>>> itself is
>>>       >> unsent. In that case, the Smalltalk "root" environment is
>>> hard-coded
>>>       >> and the specifics of bindings vs. declarations do not really
>>> matter.
>>>       >> But what should #rootClasses answer for other, possibly isolated
>>>       >> environments? What does the sender want to know?
>>>       >> - For an empty environment (no classes contained), should it
>>> answer an
>>>       >> empty collection?
>>>       >
>>>       > Yes
>>>       >
>>>       >> - Should the answer change if the "root" environment is
>>> imported?
>>>       >
>>>       > No
>>>       >
>>>       >> - For an environment that a) does not contain ProtoObject or
>>> Object,
>>>       >> but other classes deriving from them, and b) does not import the
>>>       >> "root" environment, should it answer an empty collection,
>>>       >> {ProtoObject} (although it is not imported) via superclass
>>> relations,
>>>       >> or something else?
>>>       >
>>>       > Empty
>>>       >
>>>       >> - Should the answer change if the "root" environment is
>>> imported?
>>>       >>
>>>       >> By the way, would it work to have a second (different)
>>> ProtoObject
>>>       >> class in the image (in a different environment or under a
>>> different
>>>       >> name)?
>>>       >
>>>       > It should, right?
>>>       >
>>>       > the rootsOfTheWorld are easy to understand and hence to extend to
>>> environments.  Pre environments theRootsOfTheWorld are the classes that have
>>> no superclass (have nil as their superclass).
>>>       theRootsOfTheWorld is a set (has no duplicates) but can be a
>>> sequence.  Hence, given that Smalltalk can contain user defined variables,
>>> and the values of these variables can be anything, including
>>>       classes, the computation of theRootsOfTheWorld should filter out
>>> variables that just happen to refer to root classes to ensure that a set is
>>> answered.
>>>       >
>>>       > Extending this to environments then is straight forward.
>>> theRootsOfTheWorld in an environment is a set of the classes defined in that
>>> environment that have no superclass. The computation should
>>>       not be confusable by variables whose values just happen to be toot
>>> classes.
>>>       >
>>>       > Now, given that theRootsOfTheWorld are used as the roots of code
>>> search (allImplementosOf: et al) the notion of a pet-environment
>>> theRootsOfTheWorld is suspect, given that code search should be
>>>       able to search all code.  But let's at least get the
>>> per-environment definition correct before we try and define a system-wide
>>> one.
>>>       >
>>>       >>
>>>       >> Best regards,
>>>       >> Jakob
>>>       >>
>>>       >> 2018-03-18 9:18 GMT+01:00 Eliot Miranda
>>> <eliot.miranda at gmail.com>:
>>>       >>> Hi David,
>>>       >>>
>>>       >>>>> On Mar 17, 2018, at 8:19 PM, David T. Lewis
>>> <lewis at mail.msen.com> wrote:
>>>       >>>>>
>>>       >>>>> On Sat, Mar 17, 2018 at 04:54:36PM -0700, Eliot Miranda
>>> wrote:
>>>       >>>>> Hi David,
>>>       >>>>>
>>>       >>>>>> On Sat, Mar 17, 2018 at 12:10 PM,
>>> <commits at source.squeak.org> wrote:
>>>       >>>>>>
>>>       >>>>>> David T. Lewis uploaded a new version of Environments to
>>> project The Trunk:
>>>       >>>>>> http://source.squeak.org/trunk/Environments-dtl.72.mcz
>>>       >>>>>>
>>>       >>>>>> ==================== Summary ====================
>>>       >>>>>>
>>>       >>>>>> Name: Environments-dtl.72
>>>       >>>>>> Author: dtl
>>>       >>>>>> Time: 17 March 2018, 3:09:49.564301 pm
>>>       >>>>>> UUID: e9aed004-8798-41c0-83f9-a04f5963dd55
>>>       >>>>>> Ancestors: Environments-jr.71, Environments-fbs.27
>>>       >>>>>>
>>>       >>>>>> Merge Environments-fbs.27
>>>       >>>>>>
>>>       >>>>>> =============== Diff against Environments-jr.71
>>> ===============
>>>       >>>>>>
>>>       >>>>>> Item was added:
>>>       >>>>>> + ----- Method: Environment>>rootClasses (in category
>>> 'accessing') -----
>>>       >>>>>> + rootClasses
>>>       >>>>>> +       "return a collection of classes which have a nil
>>> superclass"
>>>       >>>>>> +       ^ (self select: [:each | each isBehavior and: [each
>>> superclass
>>>       >>>>>> isNil]]) asOrderedCollection.!
>>>       >>>>>>
>>>       >>>>>
>>>       >>>>> At least for me this isn't quite good enough.  There's a
>>> possibility that
>>>       >>>>> someone could establish a variable whose value is a root,
>>> e.g. by
>>>       >>>>>
>>>       >>>>> Smalltalk at: #MyRootClass put: ProtoObject
>>>       >>>>>
>>>       >>>>> and that would cause rootClasses to answer a duplicate.  So
>>> IMO it needs to
>>>       >>>>> do one of
>>>       >>>>> - convert to a set and then back to a collection
>>>       >>>>> - answer a set
>>>       >>>>> - enumerate over associations, selecting those classes whose
>>> key is the
>>>       >>>>> same as their name
>>>       >>>>>
>>>       >>>>> _,,,^..^,,,_
>>>       >>>>> best, Eliot
>>>       >>>>
>>>       >>>> Hi Eliot,
>>>       >>>>
>>>       >>>> Do you mean this?
>>>       >>>>
>>>       >>>> Environment>>rootClasses
>>>       >>>>   "return a collection of classes which have a nil superclass"
>>>       >>>>   ^ (self select: [:each | each isBehavior and: [each
>>> superclass isNil]]) asSet asOrderedCollection.
>>>       >>>
>>>       >>> That'll do but perhaps better is
>>>       >>>
>>>       >>>          self bindings select: [:each | each value isBehavior
>>> and: [each value superclass isNil and: [each value name == each key]]])
>>> collect:  [:each | each value]
>>>       >>>
>>>       >>>>
>>>       >>>>
>>>       >>>> Note, I am not the author here, just tending to the inbox :-)
>>>       >>>>
>>>       >>>> Thanks,
>>>       >>>> Dave
>>>       >>>>
>>>       >>>>
>>>       >>>
>>>       >>
>>>       >
>>>
>>>
>>>
>>>
>>> --
>>> _,,,^..^,,,_
>>> best, Eliot
>>>
>>
>>
>>
>
>
>
> --
> _,,,^..^,,,_
> best, Eliot
>
>
>



More information about the Squeak-dev mailing list