The Trunk: MorphicExtras-cmm.201.mcz

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

The Trunk: MorphicExtras-cmm.201.mcz

commits-2
Chris Muller uploaded a new version of MorphicExtras to project The Trunk:
http://source.squeak.org/trunk/MorphicExtras-cmm.201.mcz

==================== Summary ====================

Name: MorphicExtras-cmm.201
Author: cmm
Time: 7 December 2016, 1:05:55.913807 pm
UUID: 7898b77e-9ccd-435e-89ba-fe3d9868a05d
Ancestors: MorphicExtras-tfel.200

- Some naive patches and reverts to regain use of the Object Catalog and Paint tool.

=============== Diff against MorphicExtras-tfel.200 ===============

Item was changed:
  ----- Method: ObjectsTool>>installQuads:fromButton: (in category 'alphabetic') -----
  installQuads: quads fromButton: aButton
  "Install items in the bottom pane that correspond to the given set of quads, as triggered from the given button"
 
  | aPartsBin sortedQuads oldResizing |
  aPartsBin := self partsBin.
  oldResizing := aPartsBin vResizing.
  aPartsBin removeAllMorphs.
  sortedQuads := (PartsBin translatedQuads: quads)
  asSortedCollection: [:a :b | a third < b third].
+ sortedQuads := sortedQuads select: [ : each | Smalltalk hasClassNamed: each first ].
  aPartsBin listDirection: #leftToRight quadList: sortedQuads.
  aButton ifNotNil: [self tabsPane highlightOnlySubmorph: aButton].
  aPartsBin vResizing: oldResizing.
  aPartsBin layoutChanged; fullBounds.
  self isFlap ifFalse: [ self minimizePartsBinSize ].!

Item was changed:
  ----- Method: PaintBoxMorph>>offsetFromMaxBounds (in category 'other') -----
  offsetFromMaxBounds
  "location of normal PaintBox within maxBounds."
  | left |
  left := self left.
+ ((Preferences canUnderstand: #useBiggerPaintingBox) and: [ Preferences useBiggerPaintingBox ]) ifTrue: [left := left  - (( self width * 1.5)- self width)].
- Preferences useBiggerPaintingBox ifTrue: [left := left  - (( self width * 1.5)- self width)].
  ^ left - colorMemory left @ 0!

Item was added:
+ ----- Method: Preferences class>>rotationAndScaleHandlesInPaintBox (in category '*morphicextras') -----
+ rotationAndScaleHandlesInPaintBox
+ ^ true!

Item was changed:
  ----- Method: SketchEditorMorph>>mouseMove: (in category 'event handling') -----
  mouseMove: evt
+ "In the middle of drawing a stroke.  6/11/97 19:51 tk"
- "In the middle of drawing a stroke of any kind."
 
+ | pt priorEvt |
- | pt priorEvt actionSelector |
  WorldState canSurrenderToOS: false. "we want maximum responsiveness"
  pt := evt cursorPoint.
  priorEvt := self get: #lastEvent for: evt.
  (priorEvt notNil and: [pt = priorEvt cursorPoint]) ifTrue: [^self].
+ self perform: (self getActionFor: evt) with: evt.
- self perform: (actionSelector := self getActionFor: evt) with: evt.
  "Each action must do invalidRect:"
  self
  set: #lastEvent
  for: evt
  to: evt.
  false
  ifTrue:
  ["So senders will find the things performed here"
 
  self
  paint: nil;
  fill: nil;
  erase: nil;
  pickup: nil;
  stamp: nil.
  self
  rect: nil;
  ellipse: nil;
  polygon: nil;
  line: nil;
  star: nil]!

Item was changed:
  ----- Method: SketchEditorMorph>>paint: (in category 'actions & preps') -----
  paint: evt
  "While the mouse is down, lay down paint, but only within window bounds.
  11/28/96 sw: no longer stop painting when pen strays out of window; once it comes back in, resume painting rather than waiting for a mouse up"
 
+ |  mousePoint startRect endRect startToEnd pfPen myBrush |
+
- |  mousePoint startToEnd pfPen newPoint |
  pfPen := self get: #paintingFormPen for: evt.
+ myBrush := self getBrushFor: evt.
  mousePoint := evt cursorPoint.
+ startRect := pfPen location + myBrush offset extent: myBrush extent.
+ pfPen goto: mousePoint - bounds origin.
+ endRect := pfPen location + myBrush offset extent: myBrush extent.
+ "self render: (startRect merge: endRect). Show the user what happened"
+ startToEnd := startRect merge: endRect.
- newPoint := mousePoint - bounds origin.
- startToEnd := pfPen regionFor: newPoint.
- evt shiftPressed
- ifTrue: [pfPen gotoBack: newPoint]
- ifFalse: [pfPen goto: newPoint].
  self invalidRect: (startToEnd translateBy: bounds origin).
  !


Reply | Threaded
Open this post in threaded view
|

Re: The Trunk: MorphicExtras-cmm.201.mcz

Bert Freudenberg


On Wed, Dec 7, 2016 at 11:06 AM, <[hidden email]> wrote:
Chris Muller uploaded a new version of MorphicExtras to project The Trunk:
http://source.squeak.org/trunk/MorphicExtras-cmm.201.mcz


+       ((Preferences canUnderstand: #useBiggerPaintingBox) and: [ Preferences useBiggerPaintingBox ]) ifTrue: [left := left  - (( self width * 1.5)- self width)].
-       Preferences useBiggerPaintingBox ifTrue: [left := left  - (( self width


Why did we remove Preferences class>>doesNotUnderstand:?

- Bert -



Reply | Threaded
Open this post in threaded view
|

Re: The Trunk: MorphicExtras-cmm.201.mcz

Chris Muller-3
I guess its still there..  but apparently that trick wasn't working
for this attribute.

I was only interested in getting the basic functionality working
again, I don't know all what access patterns Etoys is using.

On Mon, Dec 12, 2016 at 3:20 PM, Bert Freudenberg <[hidden email]> wrote:

>
>
> On Wed, Dec 7, 2016 at 11:06 AM, <[hidden email]> wrote:
>>
>> Chris Muller uploaded a new version of MorphicExtras to project The Trunk:
>> http://source.squeak.org/trunk/MorphicExtras-cmm.201.mcz
>>
>>
>> +       ((Preferences canUnderstand: #useBiggerPaintingBox) and: [
>> Preferences useBiggerPaintingBox ]) ifTrue: [left := left  - (( self width *
>> 1.5)- self width)].
>> -       Preferences useBiggerPaintingBox ifTrue: [left := left  - (( self
>> width
>
>
>
> Why did we remove Preferences class>>doesNotUnderstand:?
>
> - Bert -
>
>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: The Trunk: MorphicExtras-cmm.201.mcz

Bert Freudenberg
On Tue, Dec 13, 2016 at 8:33 AM, Chris Muller <[hidden email]> wrote:
I guess its still there..  but apparently that trick wasn't working
for this attribute.

Ah, I see. DNU used to return false if the pref was not found, which was a good default behavior. Marcel changed it to return nil instead, which I guess broke some code. Then Tobias changed it to raise an exception. 
 
I was only interested in getting the basic functionality working
again, I don't know all what access patterns Etoys is using.

Sure, and thank you :)

Instead of checking for "understands" we should use valueOfFlag: (which defaults to false) to get back the old behavior. Or we recreate the preference. Or we make it into a "pragma" preference on some class (which seems to be the preferred way nowadays, even though it leads to an explosion of pref accessor methods?)

What would be best?

- Bert -

On Mon, Dec 12, 2016 at 3:20 PM, Bert Freudenberg <[hidden email]> wrote:
>
>
> On Wed, Dec 7, 2016 at 11:06 AM, <[hidden email]> wrote:
>>
>> Chris Muller uploaded a new version of MorphicExtras to project The Trunk:
>> http://source.squeak.org/trunk/MorphicExtras-cmm.201.mcz
>>
>>
>> +       ((Preferences canUnderstand: #useBiggerPaintingBox) and: [
>> Preferences useBiggerPaintingBox ]) ifTrue: [left := left  - (( self width *
>> 1.5)- self width)].
>> -       Preferences useBiggerPaintingBox ifTrue: [left := left  - (( self
>> width
>
>
>
> Why did we remove Preferences class>>doesNotUnderstand:?
>
> - Bert -
>
>
>
>




Reply | Threaded
Open this post in threaded view
|

Re: The Trunk: MorphicExtras-cmm.201.mcz

Chris Muller-3
> Instead of checking for "understands" we should use valueOfFlag: (which
> defaults to false) to get back the old behavior.

Hmm, I'm not sure "false" makes sense as a universal default value.
Apps typically choose their own lazy-initialized values
attribute-by-attribute, and usually based on it having been nil.  This
is a very common pattern for apps to hardcode their own defaults with
an ifNil: ["whatever"].

> Or we recreate the
> preference.

Sure.

> Or we make it into a "pragma" preference on some class (which
> seems to be the preferred way nowadays, even though it leads to an explosion
> of pref accessor methods?)

*Thank you* for leveling a fair critique at pragma preferences.  IMO,
they are preventing the emergence of simple and powerful abstractions
in our Preferences framework while, as you alluded, making lots of
code.  :(  Their real benefits deserve some scrutiny.

> What would be best?

This.

   http://lists.squeakfoundation.org/pipermail/squeak-dev/2016-March/188486.html

Best,
  Chris

Reply | Threaded
Open this post in threaded view
|

Re: The Trunk: MorphicExtras-cmm.201.mcz

Bert Freudenberg
On Tue, Dec 13, 2016 at 11:52 AM, Chris Muller <[hidden email]> wrote:
> Instead of checking for "understands" we should use valueOfFlag: (which
> defaults to false) to get back the old behavior.

Hmm, I'm not sure "false" makes sense as a universal default value.

False is the default for valueOfFlag:. It is nil for valueOfPreference:.
 
Apps typically choose their own lazy-initialized values
attribute-by-attribute, and usually based on it having been nil. 

We're talking about old-style preferences which IMHO used to be a very convenient, succinct, and highly readable. We just wrote "Preferences myFlag ifTrue: [...]" and this would universally work *without any other support code*. This was really nice for live experimenting, you just throw this expression in somewhere without having to worry about breaking anything.

> Or we recreate the
> preference.

Sure.

> Or we make it into a "pragma" preference on some class (which
> seems to be the preferred way nowadays, even though it leads to an explosion
> of pref accessor methods?)

*Thank you* for leveling a fair critique at pragma preferences.  IMO,
they are preventing the emergence of simple and powerful abstractions
in our Preferences framework while, as you alluded, making lots of
code.  :(  Their real benefits deserve some scrutiny.

> What would be best?

This.

   http://lists.squeakfoundation.org/pipermail/squeak-dev/2016-March/188486.html


Agreed, but it doesn't really answer my question of what to write instead of "(Preferences understands: #foo) and: [Preferences foo]".

- Bert - 



Reply | Threaded
Open this post in threaded view
|

Re: The Trunk: MorphicExtras-cmm.201.mcz

Chris Muller-4
On Wed, Dec 14, 2016 at 12:13 PM, Bert Freudenberg <[hidden email]> wrote:

> On Tue, Dec 13, 2016 at 11:52 AM, Chris Muller <[hidden email]> wrote:
>>
>> > Instead of checking for "understands" we should use valueOfFlag: (which
>> > defaults to false) to get back the old behavior.
>>
>> Hmm, I'm not sure "false" makes sense as a universal default value.
>
>
> False is the default for valueOfFlag:. It is nil for valueOfPreference:.
>
>>
>> Apps typically choose their own lazy-initialized values
>> attribute-by-attribute, and usually based on it having been nil.
>
>
> We're talking about old-style preferences which IMHO used to be a very
> convenient, succinct, and highly readable. We just wrote "Preferences myFlag
> ifTrue: [...]" and this would universally work *without any other support
> code*. This was really nice for live experimenting, you just throw this
> expression in somewhere without having to worry about breaking anything.

Even though I struggle with seemingly arbitrary default, I can
actually appreciate that point.  Its like, better "usability" for the
programmer.  And with the #valueOfPreference: maintaining access to
the true internal value, seems like a good balance with functionality
needed for other use-cases.   +1

Best,
  Chris

Reply | Threaded
Open this post in threaded view
|

Re: The Trunk: MorphicExtras-cmm.201.mcz

Eliot Miranda-2
In reply to this post by Bert Freudenberg
Hi Bert,

On Tue, Dec 13, 2016 at 11:16 AM, Bert Freudenberg <[hidden email]> wrote:
On Tue, Dec 13, 2016 at 8:33 AM, Chris Muller <[hidden email]> wrote:
I guess its still there..  but apparently that trick wasn't working
for this attribute.

Ah, I see. DNU used to return false if the pref was not found, which was a good default behavior. Marcel changed it to return nil instead, which I guess broke some code. Then Tobias changed it to raise an exception. 
 
I was only interested in getting the basic functionality working
again, I don't know all what access patterns Etoys is using.

Sure, and thank you :)

Instead of checking for "understands" we should use valueOfFlag: (which defaults to false) to get back the old behavior. Or we recreate the preference. Or we make it into a "pragma" preference on some class (which seems to be the preferred way nowadays, even though it leads to an explosion of pref accessor methods?)

Well, the current scheme leads to an explosion of preference accessor methods in Preference class.  I think the pragma style is far more preferable to this.  At least one doesn't have the System package being marked as dirty just because preferences have been accessed.

I agree that a default MNU that answers false, and doesn't create an accessor method, is a good default.  Although it does suffer the disadvantage that a misspelled reference will simply go unnoticed, defaulting to false.
 

What would be best?

Not sure.  Add a preference to log "anonymous" preference accessors to the Transcript ? ;-)  Only kidding.
 

- Bert -

On Mon, Dec 12, 2016 at 3:20 PM, Bert Freudenberg <[hidden email]> wrote:
>
>
> On Wed, Dec 7, 2016 at 11:06 AM, <[hidden email]> wrote:
>>
>> Chris Muller uploaded a new version of MorphicExtras to project The Trunk:
>> http://source.squeak.org/trunk/MorphicExtras-cmm.201.mcz
>>
>>
>> +       ((Preferences canUnderstand: #useBiggerPaintingBox) and: [
>> Preferences useBiggerPaintingBox ]) ifTrue: [left := left  - (( self width *
>> 1.5)- self width)].
>> -       Preferences useBiggerPaintingBox ifTrue: [left := left  - (( self
>> width
>
>
>
> Why did we remove Preferences class>>doesNotUnderstand:?
>
> - Bert -
>
>
>
>








--
_,,,^..^,,,_
best, Eliot


Reply | Threaded
Open this post in threaded view
|

Re: The Trunk: MorphicExtras-cmm.201.mcz

Bert Freudenberg
On Fri, Dec 16, 2016 at 11:32 AM, Eliot Miranda <[hidden email]> wrote:
Instead of checking for "understands" we should use valueOfFlag: (which defaults to false) to get back the old behavior. Or we recreate the preference. Or we make it into a "pragma" preference on some class (which seems to be the preferred way nowadays, even though it leads to an explosion of pref accessor methods?)

Well, the current scheme leads to an explosion of preference accessor methods in Preference class.

Well, only because SomeOne™ changed the accessors generator to actually put them into the package, when they used to be in their own "*autogenerated" package.

These accessor methods are only there to speed up the DNU, which is the default handler. Maybe on Cog we don't even need the precompiled accessors.
 
  I think the pragma style is far more preferable to this. 

I think pragmas are good for finding preference declarations. 

But having to implement preference storage over and over again is not the best solution. But that's what the current pragma prefs require - a setter and a getter and a class var and logic for initialization and if a class has many prefs then maybe a prefs dictionary because too many class vars are annoying etc. pp.

Having actual Preference objects managed by a Preferences class takes care of all of that, once and for all.
 
At least one doesn't have the System package being marked as dirty just because preferences have been accessed.

See above - that's a bug IMHO.
 
I agree that a default MNU that answers false, and doesn't create an accessor method, is a good default.  Although it does suffer the disadvantage that a misspelled reference will simply go unnoticed, defaulting to false.

True. Maybe in a dev image it indeed should raise an exception.
 
Btw, this is a good discussion :)

- Bert -


Reply | Threaded
Open this post in threaded view
|

Re: The Trunk: MorphicExtras-cmm.201.mcz

Eliot Miranda-2
Hi Bert,

On Fri, Dec 16, 2016 at 11:50 AM, Bert Freudenberg <[hidden email]> wrote:
On Fri, Dec 16, 2016 at 11:32 AM, Eliot Miranda <[hidden email]> wrote:
Instead of checking for "understands" we should use valueOfFlag: (which defaults to false) to get back the old behavior. Or we recreate the preference. Or we make it into a "pragma" preference on some class (which seems to be the preferred way nowadays, even though it leads to an explosion of pref accessor methods?)

Well, the current scheme leads to an explosion of preference accessor methods in Preference class.

Well, only because SomeOne™ changed the accessors generator to actually put them into the package, when they used to be in their own "*autogenerated" package.

Ah.  Indeed,  That's the bug.
 

These accessor methods are only there to speed up the DNU, which is the default handler. Maybe on Cog we don't even need the precompiled accessors.

While MNU is much faster in contexts like proxies on Cog, its not going to speed up occasional use.  However, in a tight loop it does help.  
 
 
  I think the pragma style is far more preferable to this. 

I think pragmas are good for finding preference declarations. 

We're in agreement.  The pragma approach has two main advantages; one it to identify and allow documenting methods that provide preferences, the other is in being modular, in that the pragma method can live in the package to which it belongs.
 

But having to implement preference storage over and over again is not the best solution. But that's what the current pragma prefs require - a setter and a getter and a class var and logic for initialization and if a class has many prefs then maybe a prefs dictionary because too many class vars are annoying etc. pp.

Well, in the case where code wants to update the preference I think the setter is acceptable,.  But it ould be nice if the Preferences package could infer how to set the variable from the getter, something i think is fairly trivial if the getter returns a class var (or even a class inst var?).  Also, the getter can (and should) provide the initialization if the body is written as

    ^Var ifNil: [Var := true/false/aSymbol]

So with this approach and help from the Preferences framework one should be able to get away with just the getter, whose pragma should; include the help[ text, etc, and the revised class definition to declare the class var.  I'm happy to pay that cost for the modularity and documentation.

Having actual Preference objects managed by a Preferences class takes care of all of that, once and for all.

The main problem is that while a preference object can encapsulate the same state as the pragma preference getter method, one also needs code to create the object and add it to the framework.  It's that that makes the two essentially similar in cost, and makes me dislike the preference objects.  The preference getter method stands alone, and so can be added and removed freely.  In a class such as Compiler or Parser where one may have several preferences, one ends up having to edit the method that adds preferences whenever adding or removing a preference.  There's a collision.  The pragma approach solves these collisions by providing an implicit way to add a complex object.  Its analogous to how pragma menu actions allow menus to be extended without collision between different extensions.  But to achieve this elegance the pragma scheme must be thought through; for example extending the Preference system to allow preferences to be set without needing preference setter methods (and maybe even modifying the compiler to declare variables in pragma preference methods as class vars?).


At least one doesn't have the System package being marked as dirty just because preferences have been accessed.

See above - that's a bug IMHO.

+1
 
I agree that a default MNU that answers false, and doesn't create an accessor method, is a good default.  Although it does suffer the disadvantage that a misspelled reference will simply go unnoticed, defaulting to false.

True. Maybe in a dev image it indeed should raise an exception.
 
Btw, this is a good discussion :)

+1

- Bert -
 
_,,,^..^,,,_
best, Eliot


Reply | Threaded
Open this post in threaded view
|

Re: The Trunk: MorphicExtras-cmm.201.mcz

Chris Muller-3
Gentlemen, may I ask what you thought of my list of requirements?

   http://lists.squeakfoundation.org/pipermail/squeak-dev/2016-March/188486.html

These were derived through careful consideration of the real-world use
cases, both for Squeak and external applications.  They are open for
discussion, of course!

We don't need a special language feature to provide a simple and
elegant wrapping of a Dictionary.  We just need to get back to
Smalltalk and objects.

> We're in agreement.  The pragma approach has two main advantages; one it to
> identify and allow documenting methods that provide preferences,

I honestly think we don't need pragmas to do it.

> the other
> is in being modular, in that the pragma method can live in the package to
> which it belongs.

Let's not let package concerns dictate the design.  Let's make the
right design for users, *then* optimize out any packaging issues that
may arise.  There's no reason Preference accessors can't just as
easily live in the package they belong without needing to use pragma's
and class-vars.

>> But having to implement preference storage over and over again is not the
>> best solution. But that's what the current pragma prefs require - a setter
>> and a getter and a class var and logic for initialization and if a class has
>> many prefs then maybe a prefs dictionary because too many class vars are
>> annoying etc. pp.
>
>
> Well, in the case where code wants to update the preference I think the
> setter is acceptable,.  But it ould be nice if the Preferences package could
> infer how to set the variable from the getter, something i think is fairly
> trivial if the getter returns a class var (or even a class inst var?).
> Also, the getter can (and should) provide the initialization if the body is
> written as
>
>     ^Var ifNil: [Var := true/false/aSymbol]

That's what I thought too, and why I originally argued against
answering arbitrary default value of false, before agreeing, but then
someone mentioned that the developer could have easily misspelled it,
causing a hidden bug.  I couldn't agree more, and that seems like it
really dilutes any net gain for the user.  Its complex and magic,
instead of just simple.

> So with this approach and help from the Preferences framework one should be
> able to get away with just the getter, whose pragma should; include the
> help[ text, etc, and the revised class definition to declare the class var.
> I'm happy to pay that cost for the modularity and documentation.
>
>> Having actual Preference objects managed by a Preferences class takes care
>> of all of that, once and for all.
>
>
> The main problem is that while a preference object can encapsulate the same
> state as the pragma preference getter method, one also needs code to create
> the object and add it to the framework.  It's that that makes the two
> essentially similar in cost, and makes me dislike the preference objects.
> The preference getter method stands alone, and so can be added and removed
> freely.  In a class such as Compiler or Parser where one may have several
> preferences, one ends up having to edit the method that adds preferences
> whenever adding or removing a preference.  There's a collision.  The pragma
> approach solves these collisions by providing an implicit way to add a
> complex object.  Its analogous to how pragma menu actions allow menus to be
> extended without collision between different extensions.

A pure-Smalltalk pattern can do it.  If we want to co-locate access
and the default value in a lazy accessor like this.

  somePreference
     ^ (Preferences somePreference ifNil:
            [ Preferences
                 addPreferenceNamed: #somePreference
                 description: 'When true it means...'
                 default: theDefaultValueForSomePreference ]) value

#somePreference resides in the package it lives in, of course.

Okay, accessing the list of all preferences (requirement 2, from my
list) could be done by enumerating all the methods in the system which
are in a 'preferences' category, or something like that.

Protocols is something that's part of Smalltalk forever, we should
leverage it more.  We could bring more power to the system with some
simple toolage over of our "protocols" that can browse such
programmatic usages..

The current pragma approach with class-vars makes it impossible to
meet the basic requirements at all.

It also takes our deployment image from being a pure-and-simple,
traditional Smalltalk -- of just classes, objects and messages -- and
tacks on a new computery whiz-bang concept called a Pragma.  Now, a
lot of users' eyes are gonna glaze over.  They're done.  Their hope
that Squeak was an empowering application tool-kit for non-nerds has
been quashed.  It's in-the-weeds programming afterall.   :(

> But to achieve
> this elegance the pragma scheme must be thought through; for example
> extending the Preference system to allow preferences to be set without
> needing preference setter methods (and maybe even modifying the compiler to
> declare variables in pragma preference methods as class vars?).

It's just a wrapped Dictionary!  Isn't it?

Friends, IMO, Squeak's potential beyond our little group of developer
dudes lies in the how well we can bring the power of the class library
to regular, non-programmer *users*.  People who don't identify
themselves as programmers, but want something more powerful than a
spreadsheet.  Right now, I believe that's still possible.  But I
believe designing Squeak around our developer-centric selves,
increasing usage of whiz-bang language features will not get us there.
IMO the philosophy of staying as simple and traditional and fighting
complexity as long as we possibly can, will improve chances of wider
adoption.

IMO, we should just do Smalltalk and objects.  1) Get rid of teh class
vars, 2) change the getter/setters to access Preferences
wrapped-dictionary, which still compiles dynamic accessors, if
necessary, and 3) hopefully also ditch the pragmas in favor of a
protocol selection.

Best.

Reply | Threaded
Open this post in threaded view
|

Re: The Trunk: MorphicExtras-cmm.201.mcz

David T. Lewis
Hi Chris,

On Sat, Dec 17, 2016 at 04:25:10PM -0600, Chris Muller wrote:

> Gentlemen, may I ask what you thought of my list of requirements?
>
>    http://lists.squeakfoundation.org/pipermail/squeak-dev/2016-March/188486.html
>
> These were derived through careful consideration of the real-world use
> cases, both for Squeak and external applications.  They are open for
> discussion, of course!
>
> We don't need a special language feature to provide a simple and
> elegant wrapping of a Dictionary.  We just need to get back to
> Smalltalk and objects.
>

I have no strong preference one way or the other ;-)

Having said that, I think that having two kinds of preference is already
one too many. So my only strong opinion here is that we should not start
another design and implementation until we finish implementing one of the
existing ones. If we are moving to pragma preferences, then let's finish
doing that. If there are known deficiencies or bugs in the pragma preference
implementation, then let's fix them if we know how to do so.

I am not saying that I am an advocate of using or not using pragmas, I am
just saying that sometimes it is more important to get things done than
to get them perfect.

Dave


> > We're in agreement.  The pragma approach has two main advantages; one it to
> > identify and allow documenting methods that provide preferences,
>
> I honestly think we don't need pragmas to do it.
>
> > the other
> > is in being modular, in that the pragma method can live in the package to
> > which it belongs.
>
> Let's not let package concerns dictate the design.  Let's make the
> right design for users, *then* optimize out any packaging issues that
> may arise.  There's no reason Preference accessors can't just as
> easily live in the package they belong without needing to use pragma's
> and class-vars.
>
> >> But having to implement preference storage over and over again is not the
> >> best solution. But that's what the current pragma prefs require - a setter
> >> and a getter and a class var and logic for initialization and if a class has
> >> many prefs then maybe a prefs dictionary because too many class vars are
> >> annoying etc. pp.
> >
> >
> > Well, in the case where code wants to update the preference I think the
> > setter is acceptable,.  But it ould be nice if the Preferences package could
> > infer how to set the variable from the getter, something i think is fairly
> > trivial if the getter returns a class var (or even a class inst var?).
> > Also, the getter can (and should) provide the initialization if the body is
> > written as
> >
> >     ^Var ifNil: [Var := true/false/aSymbol]
>
> That's what I thought too, and why I originally argued against
> answering arbitrary default value of false, before agreeing, but then
> someone mentioned that the developer could have easily misspelled it,
> causing a hidden bug.  I couldn't agree more, and that seems like it
> really dilutes any net gain for the user.  Its complex and magic,
> instead of just simple.
>
> > So with this approach and help from the Preferences framework one should be
> > able to get away with just the getter, whose pragma should; include the
> > help[ text, etc, and the revised class definition to declare the class var.
> > I'm happy to pay that cost for the modularity and documentation.
> >
> >> Having actual Preference objects managed by a Preferences class takes care
> >> of all of that, once and for all.
> >
> >
> > The main problem is that while a preference object can encapsulate the same
> > state as the pragma preference getter method, one also needs code to create
> > the object and add it to the framework.  It's that that makes the two
> > essentially similar in cost, and makes me dislike the preference objects.
> > The preference getter method stands alone, and so can be added and removed
> > freely.  In a class such as Compiler or Parser where one may have several
> > preferences, one ends up having to edit the method that adds preferences
> > whenever adding or removing a preference.  There's a collision.  The pragma
> > approach solves these collisions by providing an implicit way to add a
> > complex object.  Its analogous to how pragma menu actions allow menus to be
> > extended without collision between different extensions.
>
> A pure-Smalltalk pattern can do it.  If we want to co-locate access
> and the default value in a lazy accessor like this.
>
>   somePreference
>      ^ (Preferences somePreference ifNil:
>             [ Preferences
>                  addPreferenceNamed: #somePreference
>                  description: 'When true it means...'
>                  default: theDefaultValueForSomePreference ]) value
>
> #somePreference resides in the package it lives in, of course.
>
> Okay, accessing the list of all preferences (requirement 2, from my
> list) could be done by enumerating all the methods in the system which
> are in a 'preferences' category, or something like that.
>
> Protocols is something that's part of Smalltalk forever, we should
> leverage it more.  We could bring more power to the system with some
> simple toolage over of our "protocols" that can browse such
> programmatic usages..
>
> The current pragma approach with class-vars makes it impossible to
> meet the basic requirements at all.
>
> It also takes our deployment image from being a pure-and-simple,
> traditional Smalltalk -- of just classes, objects and messages -- and
> tacks on a new computery whiz-bang concept called a Pragma.  Now, a
> lot of users' eyes are gonna glaze over.  They're done.  Their hope
> that Squeak was an empowering application tool-kit for non-nerds has
> been quashed.  It's in-the-weeds programming afterall.   :(
>
> > But to achieve
> > this elegance the pragma scheme must be thought through; for example
> > extending the Preference system to allow preferences to be set without
> > needing preference setter methods (and maybe even modifying the compiler to
> > declare variables in pragma preference methods as class vars?).
>
> It's just a wrapped Dictionary!  Isn't it?
>
> Friends, IMO, Squeak's potential beyond our little group of developer
> dudes lies in the how well we can bring the power of the class library
> to regular, non-programmer *users*.  People who don't identify
> themselves as programmers, but want something more powerful than a
> spreadsheet.  Right now, I believe that's still possible.  But I
> believe designing Squeak around our developer-centric selves,
> increasing usage of whiz-bang language features will not get us there.
> IMO the philosophy of staying as simple and traditional and fighting
> complexity as long as we possibly can, will improve chances of wider
> adoption.
>
> IMO, we should just do Smalltalk and objects.  1) Get rid of teh class
> vars, 2) change the getter/setters to access Preferences
> wrapped-dictionary, which still compiles dynamic accessors, if
> necessary, and 3) hopefully also ditch the pragmas in favor of a
> protocol selection.
>
> Best.
>

Reply | Threaded
Open this post in threaded view
|

Re: The Trunk: MorphicExtras-cmm.201.mcz

Chris Muller-3
Well, the pragmas ARE the second way of doing preferences, and so
let's go back and finish *original* pure-objects implementation,
rather than continuing down this 2nd way, a long detour which is
knowingly unfit for the requirements.

If you continue to the end of my email, I assert that the known
deficiencies with pragmas is their very existence, because they bring
an unneessary blemish of complexity into the system, and so the only
way to "fix" that is to remove them.

On Sat, Dec 17, 2016 at 6:13 PM, David T. Lewis <[hidden email]> wrote:

> Hi Chris,
>
> On Sat, Dec 17, 2016 at 04:25:10PM -0600, Chris Muller wrote:
>> Gentlemen, may I ask what you thought of my list of requirements?
>>
>>    http://lists.squeakfoundation.org/pipermail/squeak-dev/2016-March/188486.html
>>
>> These were derived through careful consideration of the real-world use
>> cases, both for Squeak and external applications.  They are open for
>> discussion, of course!
>>
>> We don't need a special language feature to provide a simple and
>> elegant wrapping of a Dictionary.  We just need to get back to
>> Smalltalk and objects.
>>
>
> I have no strong preference one way or the other ;-)
>
> Having said that, I think that having two kinds of preference is already
> one too many. So my only strong opinion here is that we should not start
> another design and implementation until we finish implementing one of the
> existing ones. If we are moving to pragma preferences, then let's finish
> doing that. If there are known deficiencies or bugs in the pragma preference
> implementation, then let's fix them if we know how to do so.
>
> I am not saying that I am an advocate of using or not using pragmas, I am
> just saying that sometimes it is more important to get things done than
> to get them perfect.
>
> Dave
>
>
>> > We're in agreement.  The pragma approach has two main advantages; one it to
>> > identify and allow documenting methods that provide preferences,
>>
>> I honestly think we don't need pragmas to do it.
>>
>> > the other
>> > is in being modular, in that the pragma method can live in the package to
>> > which it belongs.
>>
>> Let's not let package concerns dictate the design.  Let's make the
>> right design for users, *then* optimize out any packaging issues that
>> may arise.  There's no reason Preference accessors can't just as
>> easily live in the package they belong without needing to use pragma's
>> and class-vars.
>>
>> >> But having to implement preference storage over and over again is not the
>> >> best solution. But that's what the current pragma prefs require - a setter
>> >> and a getter and a class var and logic for initialization and if a class has
>> >> many prefs then maybe a prefs dictionary because too many class vars are
>> >> annoying etc. pp.
>> >
>> >
>> > Well, in the case where code wants to update the preference I think the
>> > setter is acceptable,.  But it ould be nice if the Preferences package could
>> > infer how to set the variable from the getter, something i think is fairly
>> > trivial if the getter returns a class var (or even a class inst var?).
>> > Also, the getter can (and should) provide the initialization if the body is
>> > written as
>> >
>> >     ^Var ifNil: [Var := true/false/aSymbol]
>>
>> That's what I thought too, and why I originally argued against
>> answering arbitrary default value of false, before agreeing, but then
>> someone mentioned that the developer could have easily misspelled it,
>> causing a hidden bug.  I couldn't agree more, and that seems like it
>> really dilutes any net gain for the user.  Its complex and magic,
>> instead of just simple.
>>
>> > So with this approach and help from the Preferences framework one should be
>> > able to get away with just the getter, whose pragma should; include the
>> > help[ text, etc, and the revised class definition to declare the class var.
>> > I'm happy to pay that cost for the modularity and documentation.
>> >
>> >> Having actual Preference objects managed by a Preferences class takes care
>> >> of all of that, once and for all.
>> >
>> >
>> > The main problem is that while a preference object can encapsulate the same
>> > state as the pragma preference getter method, one also needs code to create
>> > the object and add it to the framework.  It's that that makes the two
>> > essentially similar in cost, and makes me dislike the preference objects.
>> > The preference getter method stands alone, and so can be added and removed
>> > freely.  In a class such as Compiler or Parser where one may have several
>> > preferences, one ends up having to edit the method that adds preferences
>> > whenever adding or removing a preference.  There's a collision.  The pragma
>> > approach solves these collisions by providing an implicit way to add a
>> > complex object.  Its analogous to how pragma menu actions allow menus to be
>> > extended without collision between different extensions.
>>
>> A pure-Smalltalk pattern can do it.  If we want to co-locate access
>> and the default value in a lazy accessor like this.
>>
>>   somePreference
>>      ^ (Preferences somePreference ifNil:
>>             [ Preferences
>>                  addPreferenceNamed: #somePreference
>>                  description: 'When true it means...'
>>                  default: theDefaultValueForSomePreference ]) value
>>
>> #somePreference resides in the package it lives in, of course.
>>
>> Okay, accessing the list of all preferences (requirement 2, from my
>> list) could be done by enumerating all the methods in the system which
>> are in a 'preferences' category, or something like that.
>>
>> Protocols is something that's part of Smalltalk forever, we should
>> leverage it more.  We could bring more power to the system with some
>> simple toolage over of our "protocols" that can browse such
>> programmatic usages..
>>
>> The current pragma approach with class-vars makes it impossible to
>> meet the basic requirements at all.
>>
>> It also takes our deployment image from being a pure-and-simple,
>> traditional Smalltalk -- of just classes, objects and messages -- and
>> tacks on a new computery whiz-bang concept called a Pragma.  Now, a
>> lot of users' eyes are gonna glaze over.  They're done.  Their hope
>> that Squeak was an empowering application tool-kit for non-nerds has
>> been quashed.  It's in-the-weeds programming afterall.   :(
>>
>> > But to achieve
>> > this elegance the pragma scheme must be thought through; for example
>> > extending the Preference system to allow preferences to be set without
>> > needing preference setter methods (and maybe even modifying the compiler to
>> > declare variables in pragma preference methods as class vars?).
>>
>> It's just a wrapped Dictionary!  Isn't it?
>>
>> Friends, IMO, Squeak's potential beyond our little group of developer
>> dudes lies in the how well we can bring the power of the class library
>> to regular, non-programmer *users*.  People who don't identify
>> themselves as programmers, but want something more powerful than a
>> spreadsheet.  Right now, I believe that's still possible.  But I
>> believe designing Squeak around our developer-centric selves,
>> increasing usage of whiz-bang language features will not get us there.
>> IMO the philosophy of staying as simple and traditional and fighting
>> complexity as long as we possibly can, will improve chances of wider
>> adoption.
>>
>> IMO, we should just do Smalltalk and objects.  1) Get rid of teh class
>> vars, 2) change the getter/setters to access Preferences
>> wrapped-dictionary, which still compiles dynamic accessors, if
>> necessary, and 3) hopefully also ditch the pragmas in favor of a
>> protocol selection.
>>
>> Best.
>>
>

bpi
Reply | Threaded
Open this post in threaded view
|

Re: The Trunk: MorphicExtras-cmm.201.mcz

bpi
In reply to this post by Chris Muller-3
Hi Chris,

See my answers below.

> Am 17.12.2016 um 23:25 schrieb Chris Muller <[hidden email]>:
>
> Gentlemen, may I ask what you thought of my list of requirements?
>
>   http://lists.squeakfoundation.org/pipermail/squeak-dev/2016-March/188486.html
IMHO the first point is not a requirement (what?) at all but a solution (how?).

> I honestly think we don’t need pragmas to do it.
I agree but I cannot understand why you seem to hate pragmas.

>> the other
>> is in being modular, in that the pragma method can live in the package to
>> which it belongs.
>
> Let’s not let package concerns dictate the design.
IMHO packaging concerns are very important design drivers. I consider missing modularity one of the main problems with Smalltalk.

>  Let's make the
> right design for users, *then* optimize out any packaging issues that
> may arise.  There's no reason Preference accessors can't just as
> easily live in the package they belong without needing to use pragma's
> and class-vars.
>
>>> But having to implement preference storage over and over again is not the
>>> best solution. But that's what the current pragma prefs require - a setter
>>> and a getter and a class var and logic for initialization and if a class has
>>> many prefs then maybe a prefs dictionary because too many class vars are
>>> annoying etc. pp.
>>
>>
>> Well, in the case where code wants to update the preference I think the
>> setter is acceptable,.  But it ould be nice if the Preferences package could
>> infer how to set the variable from the getter, something i think is fairly
>> trivial if the getter returns a class var (or even a class inst var?).
>> Also, the getter can (and should) provide the initialization if the body is
>> written as
>>
>>    ^Var ifNil: [Var := true/false/aSymbol]
>
> That's what I thought too, and why I originally argued against
> answering arbitrary default value of false, before agreeing, but then
> someone mentioned that the developer could have easily misspelled it,
> causing a hidden bug.  I couldn't agree more, and that seems like it
> really dilutes any net gain for the user.  Its complex and magic,
> instead of just simple.
>
>> So with this approach and help from the Preferences framework one should be
>> able to get away with just the getter, whose pragma should; include the
>> help[ text, etc, and the revised class definition to declare the class var.
>> I'm happy to pay that cost for the modularity and documentation.
>>
>>> Having actual Preference objects managed by a Preferences class takes care
>>> of all of that, once and for all.
>>
>>
>> The main problem is that while a preference object can encapsulate the same
>> state as the pragma preference getter method, one also needs code to create
>> the object and add it to the framework.  It's that that makes the two
>> essentially similar in cost, and makes me dislike the preference objects.
>> The preference getter method stands alone, and so can be added and removed
>> freely.  In a class such as Compiler or Parser where one may have several
>> preferences, one ends up having to edit the method that adds preferences
>> whenever adding or removing a preference.  There's a collision.  The pragma
>> approach solves these collisions by providing an implicit way to add a
>> complex object.  Its analogous to how pragma menu actions allow menus to be
>> extended without collision between different extensions.
>
> A pure-Smalltalk pattern can do it.  If we want to co-locate access
> and the default value in a lazy accessor like this.
>
>  somePreference
>     ^ (Preferences somePreference ifNil:
>            [ Preferences
>                 addPreferenceNamed: #somePreference
>                 description: 'When true it means...'
>                 default: theDefaultValueForSomePreference ]) value
But, but, but… IMO that is much, much more complicated than pragma preferences. And it adds a lot of duplication, no?

>
> #somePreference resides in the package it lives in, of course.
>
> Okay, accessing the list of all preferences (requirement 2, from my
> list) could be done by enumerating all the methods in the system which
> are in a 'preferences' category, or something like that.
>
> Protocols is something that's part of Smalltalk forever, we should
> leverage it more.  We could bring more power to the system with some
> simple toolage over of our "protocols" that can browse such
> programmatic usages..
>
> The current pragma approach with class-vars makes it impossible to
> meet the basic requirements at all.
>
> It also takes our deployment image from being a pure-and-simple,
> traditional Smalltalk -- of just classes, objects and messages -- and
> tacks on a new computery whiz-bang concept called a Pragma.  Now, a
> lot of users' eyes are gonna glaze over.  They're done.  Their hope
> that Squeak was an empowering application tool-kit for non-nerds has
> been quashed.  It’s in-the-weeds programming afterall.   :(
I don’t understand why you consider pragma more computery whihz-bang than classes, objects and messages. I’d even say they are much simpler to understand than metaclasses. And pragmas are in all commonly used Smalltalk implementations by now.

> But to achieve
>> this elegance the pragma scheme must be thought through; for example
>> extending the Preference system to allow preferences to be set without
>> needing preference setter methods (and maybe even modifying the compiler to
>> declare variables in pragma preference methods as class vars?).
>
> It's just a wrapped Dictionary!  Isn't it?
>
> Friends, IMO, Squeak's potential beyond our little group of developer
> dudes lies in the how well we can bring the power of the class library
> to regular, non-programmer *users*.  People who don't identify
> themselves as programmers, but want something more powerful than a
> spreadsheet.  Right now, I believe that's still possible.  But I
> believe designing Squeak around our developer-centric selves,
> increasing usage of whiz-bang language features will not get us there.
> IMO the philosophy of staying as simple and traditional and fighting
> complexity as long as we possibly can, will improve chances of wider
> adoption.
Every time I look at the old Preference implementation I get lost in its complexity. Whereas the pragma style preferences are super simple. One class (instance) variable and two accessors.

> IMO, we should just do Smalltalk and objects.  1) Get rid of teh class
> vars, 2) change the getter/setters to access Preferences
> wrapped-dictionary, which still compiles dynamic accessors, if
> necessary, and 3) hopefully also ditch the pragmas in favor of a
> protocol selection.
Please no.

> Best.
Cheers,
Bernhard

bpi
Reply | Threaded
Open this post in threaded view
|

Re: The Trunk: MorphicExtras-cmm.201.mcz

bpi
In reply to this post by David T. Lewis

> Am 18.12.2016 um 01:13 schrieb David T. Lewis <[hidden email]>:
> Having said that, I think that having two kinds of preference is already
> one too many. So my only strong opinion here is that we should not start
> another design and implementation until we finish implementing one of the
> existing ones. If we are moving to pragma preferences, then let's finish
> doing that. If there are known deficiencies or bugs in the pragma preference
> implementation, then let's fix them if we know how to do so.
>
> I am not saying that I am an advocate of using or not using pragmas, I am
> just saying that sometimes it is more important to get things done than
> to get them perfect.
I totally agree. I had thought there had been a decision (by the board?) or at least a consensus that the pragma preferences were they way to go. :-/

Bernhard

Reply | Threaded
Open this post in threaded view
|

Re: The Trunk: MorphicExtras-cmm.201.mcz

Tobias Pape
In reply to this post by Chris Muller-3

On 17.12.2016, at 23:25, Chris Muller <[hidden email]> wrote:

> Let's not let package concerns dictate the design.

Let's _please yes_ let package concerns dictate the design.
Really.

-t

Reply | Threaded
Open this post in threaded view
|

Re: The Trunk: MorphicExtras-cmm.201.mcz

Levente Uzonyi
In reply to this post by Chris Muller-3
This is something I had written before the discussion started up, but I
decided to postpone it.

Pragma preferences are way older than the list of "minimum requirements"
you linked. Seven years ago the goal was to get rid of the central
collection of preferences and replace it with distributed pragma
preferences.

About the list:

>  1)  it must have a first-class model (which it already does)
>     Preferences and Preference.  All of the following requirements must be
>     able to be satisfied by talking strictly to this model, (no required
>     browsers or sends to outside classes) with uniform API usage
>     regardless whether the underlying implementation (Pragma or
>     otherwise).

This is more like a request than a requirement. Also, just because
Preferences still exists, it doesn't mean it should be part of the model.

(Why do I say this? Because you use "must", while I don't think we "must"
do these; we could do things differently. Perhaps I just haven't found
yet why we must do it this way.)

>  3)  Ability to access any single Preference object by its Symbolic
>    name.  (We want to maintain the standard Smalltalk "senders" being
>    able to easily find users of preferences by their name).

Does it mean that two external packages cannot use the same name for
their own preferences? If yes, what will happen if they do?

> 5)  Ability to reset any Preference to its default value, another
>     fixed value, or cycle from its current value to its next value.

What's the next value of the current "Update URL" preference?

Also, 8 makes no sense if external packages can add new preferences, which
is a must. And 10 depends on 9, so 9 can't be "nice-to-have".


Levente

On Sat, 17 Dec 2016, Chris Muller wrote:

> Well, the pragmas ARE the second way of doing preferences, and so
> let's go back and finish *original* pure-objects implementation,
> rather than continuing down this 2nd way, a long detour which is
> knowingly unfit for the requirements.
>
> If you continue to the end of my email, I assert that the known
> deficiencies with pragmas is their very existence, because they bring
> an unneessary blemish of complexity into the system, and so the only
> way to "fix" that is to remove them.
>
> On Sat, Dec 17, 2016 at 6:13 PM, David T. Lewis <[hidden email]> wrote:
>> Hi Chris,
>>
>> On Sat, Dec 17, 2016 at 04:25:10PM -0600, Chris Muller wrote:
>>> Gentlemen, may I ask what you thought of my list of requirements?
>>>
>>>    http://lists.squeakfoundation.org/pipermail/squeak-dev/2016-March/188486.html
>>>
>>> These were derived through careful consideration of the real-world use
>>> cases, both for Squeak and external applications.  They are open for
>>> discussion, of course!
>>>
>>> We don't need a special language feature to provide a simple and
>>> elegant wrapping of a Dictionary.  We just need to get back to
>>> Smalltalk and objects.
>>>
>>
>> I have no strong preference one way or the other ;-)
>>
>> Having said that, I think that having two kinds of preference is already
>> one too many. So my only strong opinion here is that we should not start
>> another design and implementation until we finish implementing one of the
>> existing ones. If we are moving to pragma preferences, then let's finish
>> doing that. If there are known deficiencies or bugs in the pragma preference
>> implementation, then let's fix them if we know how to do so.
>>
>> I am not saying that I am an advocate of using or not using pragmas, I am
>> just saying that sometimes it is more important to get things done than
>> to get them perfect.
>>
>> Dave
>>
>>
>>> > We're in agreement.  The pragma approach has two main advantages; one it to
>>> > identify and allow documenting methods that provide preferences,
>>>
>>> I honestly think we don't need pragmas to do it.
>>>
>>> > the other
>>> > is in being modular, in that the pragma method can live in the package to
>>> > which it belongs.
>>>
>>> Let's not let package concerns dictate the design.  Let's make the
>>> right design for users, *then* optimize out any packaging issues that
>>> may arise.  There's no reason Preference accessors can't just as
>>> easily live in the package they belong without needing to use pragma's
>>> and class-vars.
>>>
>>> >> But having to implement preference storage over and over again is not the
>>> >> best solution. But that's what the current pragma prefs require - a setter
>>> >> and a getter and a class var and logic for initialization and if a class has
>>> >> many prefs then maybe a prefs dictionary because too many class vars are
>>> >> annoying etc. pp.
>>> >
>>> >
>>> > Well, in the case where code wants to update the preference I think the
>>> > setter is acceptable,.  But it ould be nice if the Preferences package could
>>> > infer how to set the variable from the getter, something i think is fairly
>>> > trivial if the getter returns a class var (or even a class inst var?).
>>> > Also, the getter can (and should) provide the initialization if the body is
>>> > written as
>>> >
>>> >     ^Var ifNil: [Var := true/false/aSymbol]
>>>
>>> That's what I thought too, and why I originally argued against
>>> answering arbitrary default value of false, before agreeing, but then
>>> someone mentioned that the developer could have easily misspelled it,
>>> causing a hidden bug.  I couldn't agree more, and that seems like it
>>> really dilutes any net gain for the user.  Its complex and magic,
>>> instead of just simple.
>>>
>>> > So with this approach and help from the Preferences framework one should be
>>> > able to get away with just the getter, whose pragma should; include the
>>> > help[ text, etc, and the revised class definition to declare the class var.
>>> > I'm happy to pay that cost for the modularity and documentation.
>>> >
>>> >> Having actual Preference objects managed by a Preferences class takes care
>>> >> of all of that, once and for all.
>>> >
>>> >
>>> > The main problem is that while a preference object can encapsulate the same
>>> > state as the pragma preference getter method, one also needs code to create
>>> > the object and add it to the framework.  It's that that makes the two
>>> > essentially similar in cost, and makes me dislike the preference objects.
>>> > The preference getter method stands alone, and so can be added and removed
>>> > freely.  In a class such as Compiler or Parser where one may have several
>>> > preferences, one ends up having to edit the method that adds preferences
>>> > whenever adding or removing a preference.  There's a collision.  The pragma
>>> > approach solves these collisions by providing an implicit way to add a
>>> > complex object.  Its analogous to how pragma menu actions allow menus to be
>>> > extended without collision between different extensions.
>>>
>>> A pure-Smalltalk pattern can do it.  If we want to co-locate access
>>> and the default value in a lazy accessor like this.
>>>
>>>   somePreference
>>>      ^ (Preferences somePreference ifNil:
>>>             [ Preferences
>>>                  addPreferenceNamed: #somePreference
>>>                  description: 'When true it means...'
>>>                  default: theDefaultValueForSomePreference ]) value
>>>
>>> #somePreference resides in the package it lives in, of course.
>>>
>>> Okay, accessing the list of all preferences (requirement 2, from my
>>> list) could be done by enumerating all the methods in the system which
>>> are in a 'preferences' category, or something like that.
>>>
>>> Protocols is something that's part of Smalltalk forever, we should
>>> leverage it more.  We could bring more power to the system with some
>>> simple toolage over of our "protocols" that can browse such
>>> programmatic usages..
>>>
>>> The current pragma approach with class-vars makes it impossible to
>>> meet the basic requirements at all.
>>>
>>> It also takes our deployment image from being a pure-and-simple,
>>> traditional Smalltalk -- of just classes, objects and messages -- and
>>> tacks on a new computery whiz-bang concept called a Pragma.  Now, a
>>> lot of users' eyes are gonna glaze over.  They're done.  Their hope
>>> that Squeak was an empowering application tool-kit for non-nerds has
>>> been quashed.  It's in-the-weeds programming afterall.   :(
>>>
>>> > But to achieve
>>> > this elegance the pragma scheme must be thought through; for example
>>> > extending the Preference system to allow preferences to be set without
>>> > needing preference setter methods (and maybe even modifying the compiler to
>>> > declare variables in pragma preference methods as class vars?).
>>>
>>> It's just a wrapped Dictionary!  Isn't it?
>>>
>>> Friends, IMO, Squeak's potential beyond our little group of developer
>>> dudes lies in the how well we can bring the power of the class library
>>> to regular, non-programmer *users*.  People who don't identify
>>> themselves as programmers, but want something more powerful than a
>>> spreadsheet.  Right now, I believe that's still possible.  But I
>>> believe designing Squeak around our developer-centric selves,
>>> increasing usage of whiz-bang language features will not get us there.
>>> IMO the philosophy of staying as simple and traditional and fighting
>>> complexity as long as we possibly can, will improve chances of wider
>>> adoption.
>>>
>>> IMO, we should just do Smalltalk and objects.  1) Get rid of teh class
>>> vars, 2) change the getter/setters to access Preferences
>>> wrapped-dictionary, which still compiles dynamic accessors, if
>>> necessary, and 3) hopefully also ditch the pragmas in favor of a
>>> protocol selection.
>>>
>>> Best.
>>>
>>