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

Eliot Miranda eliot.miranda at gmail.com
Wed Mar 21 02:56:55 UTC 2018


Hi Jakob,

> On Mar 20, 2018, at 3:34 PM, Jakob Reschke <forums.jakob at resfarm.de> wrote:
> 
> 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.

+1.  Don't avoid it :-).  The name guard is not bad.  The reflectivity of the system implies that class's names are the same as their identifiers.  Why go to all this effort to avoid it?  How can one navigate a system where class names are other than their identifiers?  It's not good in Newspeak.  

> But note further that Environment>>allClassesDo: uses
> #isKindOf: to separate classes from traits...

Ugh.  Please no.  Can we instead have isTrait in ClassDescription and Trait?  IMO isKindOf: has no place in the kernel.


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

But asSet has a cost.  If one can state the thing declaratively, avoid the asSet hack, no?

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