Pharo-users
By thread
pharo-users@lists.pharo.org
By month
Messages by month
- ----- 2026 -----
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
March 2022
- 32 participants
- 104 messages
Re: ESUG 2022 call for presentations & Call for student volunteers
by Stéphane Ducasse
âHelloâ, âworldâ please: #readAndDistribute
> On 13 Jan 2022, at 13:25, stephane ducasse <stephane.ducasse(a)inria.fr> wrote:
>
> ESUG 2022
> Novisad Serbia 22. â 26.8.
> https://esug.github.io/2022-Conference/call2022.html <https://esug.github.io/2022-Conference/call2022.html>
>
> You can support the ESUG conference in many different ways:
> Sponsor the conference. New sponsoring packages are described at http://www.esug.org/supportesug/becomeasponsor/ <http://www.esug.org/supportesug/becomeasponsor/>
> Submit a talk, a software or a paper to one of the events. See below.
> Attend the conference. We'd like to beat the previous record of attendance (170 people at Amsterdam 2008)!
> Students can get free registration and hosting if they enroll into the the Student Volunteers program. See below.
> <>Developers Forum: International Smalltalk Developers Conference
>
> We are looking for YOUR experience on using Smalltalk. You will have 30 min for presentations and 45 min for hands-on tutorials.
> The list of topics for the normal talks and tutorials includes, but is not limited to the following:
> XP practices, Development tools, Experience reports
> Model driven development, Web development, Team management
> Meta-Modeling, Security, New libraries & frameworks
> Educational material, Embedded systems and robotics
> SOA and Web services, Interaction with other programming languages
> <>Teaching Pearls and Show us Your Business
>
> New this year!!! We added two types of sessions in addition to the regular talks and show us your projects sessions.
> Show your business 10 min session (Get prepared!!)
> Teaching pearls : we want some session on how to teach some design aspects. We want your tip and tricks to teach Smalltalk or OOP.
> We expect to have several 10 to 15 min sessions aggregated.
> <>How to submit?
>
> Make a Pull Request here https://github.com/ESUG/esug.github.io/tree/source/2022-Conference/talks <https://github.com/ESUG/esug.github.io/tree/source/2022-Conference/talks>
>
> Or but only if you are not connected to the world⦠send an email to stephane.ducasse(a)inria.fr <mailto:stephane.ducasse@inria.fr>
>
> Title: [ESUG 2022] Please follow the template below the email will be automatically processed!
> Name:
> Email:
> Abstract:
> Bio:
>
> Call for Student Volunteers
> Student volunteers help keep the conference running smoothly; in return, they have free accommodations, while still having most of the time to enjoy the conference.
>
> Pay attention: the places are limited so do not wait till the last minute to apply.
>
> Conference details:
> Send an email to stephane.ducasse at inria.fr <http://inria.fr/> and serge.stinckwich at gmail.com <http://gmail.com/> with:
>
> title: [ESUG 2022 Student]
> name, gender, university/school, country, email address
> short description of you and why you are interested in participating
> For which period is accommodation covered? Accommodation is covered from Sunday 21 August until Friday 26 August 2022 (including nights from Sunday to Monday and from Thursday to Friday). Students will be hosted in student rooms. ESUG additionally covers for the lunches during the week and one dinner.
>
> Duties include handling registration as people arrive at the conference, filling coffee machines, collecting presentation slides for ESUG right after the presentation is given, being present at an information desk to answer questions, and generally being helpful. Student volunteering makes the conference better, takes a fairly small amount of time and doesn't significantly interfere with enjoying and learning from the conference. Please Note, this role requires discipline and constant attention to all attendees.
>
> Information about hotel
> Student Volunteer rooms are booked at (to be announced). If you are student volunteer, do not book yourself, we have arranged the booking already!
>
March 30, 2022
Re: [Esug-list] [PDFtalk] Porting to non-namespace Smalltalks
by christian.haider@smalltalked-visuals.com
Yes, I heard from several people that they could not get a PUL license. This is sad :(.
But I donât understand why there should be a legal problem. You are using an open source tool (Smalltalk transform) to read another open source project (PDFtalk) to generate open source code for another open source platform (Pharo). I think that this should be possible with a PUL version. (But I am not lawyerâ¦)
I still would be happy to hear more about your port.
Very helpful would also be some code review and suggestions on how to do things better, especially the meta data and âpackageâ conventions in Pharo.
Happy hacking,
Christian
Von: stephane ducasse <stephane.ducasse(a)inria.fr>
Gesendet: Sonntag, 27. März 2022 22:17
An: Any question about pharo is welcome <pharo-users(a)lists.pharo.org>
Betreff: [Pharo-users] Re: [Esug-list] [PDFtalk] Porting to non-namespace Smalltalks
BTW about porting from VW, you see a friend of mine wanted to see how to help porting Siren to Pharo.
Now this is not possible because he could not get a personal VW license.
So even if people want to help pointing to a store database is equivalent to /dev/null for most people.
For example I cannot (and also does not for legal reason) run VW on my machine.
Not talking about the new M1 I will get.
S
On 27 Mar 2022, at 22:12, seasidebook <seasidebook(a)free.fr <mailto:seasidebook@free.fr> > wrote:
Hi christian
I took the squeakValues60 becau se I thought that this is what you wanted that we do.
I should continue but Iâm busy
ahhh I did not know that you already did it.
Do you need help to package your changes?
Because you can fork my repo and load your changes.
I got lost with the explanation of OrderedDictionary below because Iâm dead :) - worked too mcuh today.
But what we can do is to package the one that is working for you under http://github.com/pharo-container
and update the baseline to load it.
Alternatively we could see what is wrong in the pharoâs one.
Now my brain decided to shut down :) so I need to sleep.
S
Hi Stef,
Great! Thank you for your work.
Good example for the tonel format.
Which sources were you using?
How did you generate this?
Do you use VW to create the output?
For the last ESUG (2.5 years ago â sigh), I already did the transformation for Values for Pharo. Thanks to you, I revised them and published the result on GitHub (https://github.com/PortingPDFtalk/PharoValues) and added a Pharo porting page to the wiki (https://wiki.pdftalk.de/doku.php?id=pharoport) Please have a look.
The fileouts are for Pharo versions 6.1, 7.0, 8.0 and 9.0 (7.0 to 9.0 have identical sources). The sources load without errors or warnings and all 27 tests pass.
Some of the problems in your code have to do with OrderedDictionary as superclass of Valuemap. When I did my first round on the port, I had a class OrderedDictionary in my Values implementation. Unfortunately, OrderedDictionary does not work as I expected.
(OrderedDictionary with: #a -> 1 with: #b -> 2) = (OrderedDictionary with: #b -> 2 with: #a -> 1)
answers true, although the order is different. Therefore, it cannot be used as value.
Instead of raising this issue on a Pharo list (sorry), I decided to use a new name: Valuemap.
A Valuemap is an OrderedDictionary where the order is relevant for comparisons.
Squeak had the same problem where it was considered a bug and fixed.
While I subclass Dictionary for Valuemap in Pharo, I can use OrderedDictionary in Squeak. This removes a lot of methods from the fileout.
A remark about the renamings you propose in your commit comment.
Thank you for the suggestions, but I decline for two reasons:
1. Names for classes, methods and variables are very important to me. Naming is part of the creative expression of the code author. I do think much about the right names and therefore, I claim the liberty and right to name things according to my feeling.
Yes now you may want to read an excellent book that just came out: http://books.pharo.org <http://books.pharo.org/> Pharo with Styles.
If you want to have future contributors this is good to follow good practices
Else Iâm quite sure that you would not like a French Pharo :)
1. Maybe my names are a bit influenced by German, where we tend to have longer names. Therefore, my names are not so heavily camel-cased :). In contrast, Pharo has quite a different style with a love for camel-casing :) (#timeStamp, #nanoSeconds etc.).
2. From a practical view, it would be a lot of work to rename all references to the items in this basic systems library. There is a lot of code out there using it. Of course, if there is a good reason for a renaming (like a spelling mistake or misleading name), it should be done and I am appreciating any suggestions.
A pattern that we use is the following.
You introduce a new name and let the old one as an empty subclass. Like that you can migrate and still be backward compatible.
For the method level refactoring we have a gorgeous mechanism that automatically rewrite client codeâ¦.
http://www.jot.fm/issues/issue_2022_01/article1.pdf
S
March 28, 2022
Re: [Esug-list] [PDFtalk] Porting to non-namespace Smalltalks
by Marcus Denker
> On 27 Mar 2022, at 20:29, christian.haider(a)smalltalked-visuals.com wrote:
>
> Hi Stef,
>
> Great! Thank you for your work.
> Good example for the tonel format.
>
> Which sources were you using?
> How did you generate this?
> Do you use VW to create the output?
>
>
> For the last ESUG (2.5 years ago â sigh), I already did the transformation for Values for Pharo. Thanks to you, I revised them and published the result on GitHub (https://github.com/PortingPDFtalk/PharoValues <https://github.com/PortingPDFtalk/PharoValues>) and added a Pharo porting page to the wiki (https://wiki.pdftalk.de/doku.php?id=pharoport <https://wiki.pdftalk.de/doku.php?id=pharoport>). Please have a look.
>
> The fileouts are for Pharo versions 6.1, 7.0, 8.0 and 9.0 (7.0 to 9.0 have identical sources). The sources load without errors or warnings and all 27 tests pass.
>
>
> Some of the problems in your code have to do with OrderedDictionary as superclass of Valuemap. When I did my first round on the port, I had a class OrderedDictionary in my Values implementation. Unfortunately, OrderedDictionary does not work as I expected.
>
> (OrderedDictionary with: #a -> 1 with: #b -> 2) = (OrderedDictionary with: #b -> 2 with: #a -> 1)
>
> answers true, although the order is different. Therefore, it cannot be used as value.
>
I have added an issue tracker entry:
https://github.com/pharo-project/pharo/issues/11065 <https://github.com/pharo-project/pharo/issues/11065>
To me it looks like yes, it #= should take order into account.
Marcus
March 28, 2022
Re: [Esug-list] [PDFtalk] Porting to non-namespace Smalltalks
by James Foster
https://github.com/GemTalk/SETT <https://github.com/GemTalk/SETT>
> On Mar 27, 2022, at 3:56 PM, Richard Sargent <richard.sargent(a)gemtalksystems.com> wrote:
>
> GemTalk Systems published a tool called SETT which is designed to extract sources from Store into a git repository. I think it's filetree, not to El format, but getting it (and its history) out of Store is the primary motivation.
>
> It requires direct access to the Store database, as far as I understand.
>
> Look at the GemTalk area on GitHub for the project and details. (I'm on vacation, using my phone and memory, so pardon the scarcity of detail.)
>
> On Sun, Mar 27, 2022, 13:17 stephane ducasse <stephane.ducasse(a)inria.fr <mailto:stephane.ducasse@inria.fr>> wrote:
> BTW about porting from VW, you see a friend of mine wanted to see how to help porting Siren to Pharo.
> Now this is not possible because he could not get a personal VW license.
>
> So even if people want to help pointing to a store database is equivalent to /dev/null for most people.
> For example I cannot (and also does not for legal reason) run VW on my machine.
> Not talking about the new M1 I will get.
>
> S
>
>> On 27 Mar 2022, at 22:12, seasidebook <seasidebook(a)free.fr <mailto:seasidebook@free.fr>> wrote:
>>
>> Hi christian
>>
>> I took the squeakValues60 becau se I thought that this is what you wanted that we do.
>> I should continue but Iâm busy
>>
>>
>> ahhh I did not know that you already did it.
>> Do you need help to package your changes?
>> Because you can fork my repo and load your changes.
>>
>> I got lost with the explanation of OrderedDictionary below because Iâm dead :) - worked too mcuh today.
>> But what we can do is to package the one that is working for you under http://github.com/pharo-container <http://github.com/pharo-container>
>> and update the baseline to load it.
>> Alternatively we could see what is wrong in the pharoâs one.
>>
>> Now my brain decided to shut down :) so I need to sleep.
>>
>> S
>>
>>> Hi Stef,
>>>
>>> Great! Thank you for your work.
>>> Good example for the tonel format.
>>>
>>> Which sources were you using?
>>> How did you generate this?
>>> Do you use VW to create the output?
>>>
>>>
>>> For the last ESUG (2.5 years ago â sigh), I already did the transformation for Values for Pharo. Thanks to you, I revised them and published the result on GitHub (https://github.com/PortingPDFtalk/PharoValues <https://github.com/PortingPDFtalk/PharoValues>) and added a Pharo porting page to the wiki (https://wiki.pdftalk.de/doku.php?id=pharoport <https://wiki.pdftalk.de/doku.php?id=pharoport>). Please have a look.
>>>
>>> The fileouts are for Pharo versions 6.1, 7.0, 8.0 and 9.0 (7.0 to 9.0 have identical sources). The sources load without errors or warnings and all 27 tests pass.
>>>
>>>
>>> Some of the problems in your code have to do with OrderedDictionary as superclass of Valuemap. When I did my first round on the port, I had a class OrderedDictionary in my Values implementation. Unfortunately, OrderedDictionary does not work as I expected.
>>>
>>> (OrderedDictionary with: #a -> 1 with: #b -> 2) = (OrderedDictionary with: #b -> 2 with: #a -> 1)
>>>
>>> answers true, although the order is different. Therefore, it cannot be used as value.
>>>
>>> Instead of raising this issue on a Pharo list (sorry), I decided to use a new name: Valuemap.
>>> A Valuemap is an OrderedDictionary where the order is relevant for comparisons.
>>> Squeak had the same problem where it was considered a bug and fixed.
>>> While I subclass Dictionary for Valuemap in Pharo, I can use OrderedDictionary in Squeak. This removes a lot of methods from the fileout.
>>>
>>>
>>> A remark about the renamings you propose in your commit comment.
>>> Thank you for the suggestions, but I decline for two reasons:
>>> Names for classes, methods and variables are very important to me. Naming is part of the creative expression of the code author. I do think much about the right names and therefore, I claim the liberty and right to name things according to my feeling.
>>
>> Yes now you may want to read an excellent book that just came out: http://books.pharo.org <http://books.pharo.org/> Pharo with Styles.
>> If you want to have future contributors this is good to follow good practices
>> Else Iâm quite sure that you would not like a French Pharo :)
>>
>>> Maybe my names are a bit influenced by German, where we tend to have longer names. Therefore, my names are not so heavily camel-cased J. In contrast, Pharo has quite a different style with a love for camel-casing J (#timeStamp, #nanoSeconds etc.).
>>> From a practical view, it would be a lot of work to rename all references to the items in this basic systems library. There is a lot of code out there using it. Of course, if there is a good reason for a renaming (like a spelling mistake or misleading name), it should be done and I am appreciating any suggestions.
>>
>> A pattern that we use is the following.
>> You introduce a new name and let the old one as an empty subclass. Like that you can migrate and still be backward compatible.
>>
>> For the method level refactoring we have a gorgeous mechanism that automatically rewrite client codeâ¦.
>>
>> http://www.jot.fm/issues/issue_2022_01/article1.pdf <http://www.jot.fm/issues/issue_2022_01/article1.pdf>
>>
>> S
>
March 27, 2022
Re: [Esug-list] [PDFtalk] Porting to non-namespace Smalltalks
by Richard Sargent
GemTalk Systems published a tool called SETT which is designed to extract
sources from Store into a git repository. I think it's filetree, not to El
format, but getting it (and its history) out of Store is the primary
motivation.
It requires direct access to the Store database, as far as I understand.
Look at the GemTalk area on GitHub for the project and details. (I'm on
vacation, using my phone and memory, so pardon the scarcity of detail.)
On Sun, Mar 27, 2022, 13:17 stephane ducasse <stephane.ducasse(a)inria.fr>
wrote:
> BTW about porting from VW, you see a friend of mine wanted to see how to
> help porting Siren to Pharo.
> Now this is not possible because he could not get a personal VW license.
>
> So even if people want to help pointing to a store database is equivalent
> to /dev/null for most people.
> For example I cannot (and also does not for legal reason) run VW on my
> machine.
> Not talking about the new M1 I will get.
>
> S
>
> On 27 Mar 2022, at 22:12, seasidebook <seasidebook(a)free.fr> wrote:
>
> Hi christian
>
> I took the squeakValues60 becau se I thought that this is what you wanted
> that we do.
> I should continue but Iâm busy
>
>
> ahhh I did not know that you already did it.
> Do you need help to package your changes?
> Because you can fork my repo and load your changes.
>
> I got lost with the explanation of OrderedDictionary below because Iâm
> dead :) - worked too mcuh today.
> But what we can do is to package the one that is working for you under
> http://github.com/pharo-container
> and update the baseline to load it.
> Alternatively we could see what is wrong in the pharoâs one.
>
> Now my brain decided to shut down :) so I need to sleep.
>
> S
>
> Hi Stef,
>
> Great! Thank you for your work.
> Good example for the tonel format.
>
> Which sources were you using?
> How did you generate this?
> Do you use VW to create the output?
>
>
> For the last ESUG (2.5 years ago â sigh), I already did the transformation
> for Values for Pharo. Thanks to you, I revised them and published the
> result on GitHub (https://github.com/PortingPDFtalk/PharoValues) and
> added a Pharo porting page to the wiki (
> https://wiki.pdftalk.de/doku.php?id=pharoport) Please have a look.
>
> The fileouts are for Pharo versions 6.1, 7.0, 8.0 and 9.0 (7.0 to 9.0 have
> identical sources). The sources load without errors or warnings and all 27
> tests pass.
>
>
> Some of the problems in your code have to do with OrderedDictionary as
> superclass of Valuemap. When I did my first round on the port, I had a
> class OrderedDictionary in my Values implementation. Unfortunately,
> OrderedDictionary does not work as I expected.
>
> (OrderedDictionary with: #a -> 1 with: #b -> 2) =
> (OrderedDictionary with: #b -> 2 with: #a -> 1)
>
> answers true, although the order is different. Therefore, it cannot be
> used as value.
>
> Instead of raising this issue on a Pharo list (sorry), I decided to use a
> new name: Valuemap.
> A Valuemap is an OrderedDictionary where the order is relevant for
> comparisons.
> Squeak had the same problem where it was considered a bug and fixed.
> While I subclass Dictionary for Valuemap in Pharo, I can use
> OrderedDictionary in Squeak. This removes a lot of methods from the fileout.
>
>
> A remark about the renamings you propose in your commit comment.
> Thank you for the suggestions, but I decline for two reasons:
>
> 1. Names for classes, methods and variables are very important to me.
> Naming is part of the creative expression of the code author. I do think
> much about the right names and therefore, I claim the liberty and right to
> name things according to my feeling.
>
>
> Yes now you may want to read an excellent book that just came out:
> http://books.pharo.org Pharo with Styles.
> If you want to have future contributors this is good to follow good
> practices
> Else Iâm quite sure that you would not like a French Pharo :)
>
>
> 1. Maybe my names are a bit influenced by German, where we tend to
> have longer names. Therefore, my names are not so heavily camel-cased J.
> In contrast, Pharo has quite a different style with a love for camel-casing
> J (#timeStamp, #nanoSeconds etc.).
> 2. From a practical view, it would be a lot of work to rename all
> references to the items in this basic systems library. There is a lot of
> code out there using it. Of course, if there is a good reason for a
> renaming (like a spelling mistake or misleading name), it should be done
> and I am appreciating any suggestions.
>
>
> A pattern that we use is the following.
> You introduce a new name and let the old one as an empty subclass. Like
> that you can migrate and still be backward compatible.
>
> For the method level refactoring we have a gorgeous mechanism that
> automatically rewrite client codeâ¦.
>
> http://www.jot.fm/issues/issue_2022_01/article1.pdf
>
> S
>
>
>
March 27, 2022
Re: [Esug-list] [PDFtalk] Porting to non-namespace Smalltalks
by stephane ducasse
BTW about porting from VW, you see a friend of mine wanted to see how to help porting Siren to Pharo.
Now this is not possible because he could not get a personal VW license.
So even if people want to help pointing to a store database is equivalent to /dev/null for most people.
For example I cannot (and also does not for legal reason) run VW on my machine.
Not talking about the new M1 I will get.
S
> On 27 Mar 2022, at 22:12, seasidebook <seasidebook(a)free.fr> wrote:
>
> Hi christian
>
> I took the squeakValues60 becau se I thought that this is what you wanted that we do.
> I should continue but Iâm busy
>
>
> ahhh I did not know that you already did it.
> Do you need help to package your changes?
> Because you can fork my repo and load your changes.
>
> I got lost with the explanation of OrderedDictionary below because Iâm dead :) - worked too mcuh today.
> But what we can do is to package the one that is working for you under http://github.com/pharo-container <http://github.com/pharo-container>
> and update the baseline to load it.
> Alternatively we could see what is wrong in the pharoâs one.
>
> Now my brain decided to shut down :) so I need to sleep.
>
> S
>
>> Hi Stef,
>>
>> Great! Thank you for your work.
>> Good example for the tonel format.
>>
>> Which sources were you using?
>> How did you generate this?
>> Do you use VW to create the output?
>>
>>
>> For the last ESUG (2.5 years ago â sigh), I already did the transformation for Values for Pharo. Thanks to you, I revised them and published the result on GitHub (https://github.com/PortingPDFtalk/PharoValues <https://github.com/PortingPDFtalk/PharoValues>) and added a Pharo porting page to the wiki (https://wiki.pdftalk.de/doku.php?id=pharoport <https://wiki.pdftalk.de/doku.php?id=pharoport>). Please have a look.
>>
>> The fileouts are for Pharo versions 6.1, 7.0, 8.0 and 9.0 (7.0 to 9.0 have identical sources). The sources load without errors or warnings and all 27 tests pass.
>>
>>
>> Some of the problems in your code have to do with OrderedDictionary as superclass of Valuemap. When I did my first round on the port, I had a class OrderedDictionary in my Values implementation. Unfortunately, OrderedDictionary does not work as I expected.
>>
>> (OrderedDictionary with: #a -> 1 with: #b -> 2) = (OrderedDictionary with: #b -> 2 with: #a -> 1)
>>
>> answers true, although the order is different. Therefore, it cannot be used as value.
>>
>> Instead of raising this issue on a Pharo list (sorry), I decided to use a new name: Valuemap.
>> A Valuemap is an OrderedDictionary where the order is relevant for comparisons.
>> Squeak had the same problem where it was considered a bug and fixed.
>> While I subclass Dictionary for Valuemap in Pharo, I can use OrderedDictionary in Squeak. This removes a lot of methods from the fileout.
>>
>>
>> A remark about the renamings you propose in your commit comment.
>> Thank you for the suggestions, but I decline for two reasons:
>> Names for classes, methods and variables are very important to me. Naming is part of the creative expression of the code author. I do think much about the right names and therefore, I claim the liberty and right to name things according to my feeling.
>
> Yes now you may want to read an excellent book that just came out: http://books.pharo.org <http://books.pharo.org/> Pharo with Styles.
> If you want to have future contributors this is good to follow good practices
> Else Iâm quite sure that you would not like a French Pharo :)
>
>> Maybe my names are a bit influenced by German, where we tend to have longer names. Therefore, my names are not so heavily camel-cased J. In contrast, Pharo has quite a different style with a love for camel-casing J (#timeStamp, #nanoSeconds etc.).
>> From a practical view, it would be a lot of work to rename all references to the items in this basic systems library. There is a lot of code out there using it. Of course, if there is a good reason for a renaming (like a spelling mistake or misleading name), it should be done and I am appreciating any suggestions.
>
> A pattern that we use is the following.
> You introduce a new name and let the old one as an empty subclass. Like that you can migrate and still be backward compatible.
>
> For the method level refactoring we have a gorgeous mechanism that automatically rewrite client codeâ¦.
>
> http://www.jot.fm/issues/issue_2022_01/article1.pdf <http://www.jot.fm/issues/issue_2022_01/article1.pdf>
>
> S
March 27, 2022
Re: [Esug-list] [PDFtalk] Porting to non-namespace Smalltalks
by christian.haider@smalltalked-visuals.com
Hi Stef,
Great! Thank you for your work.
Good example for the tonel format.
Which sources were you using?
How did you generate this?
Do you use VW to create the output?
For the last ESUG (2.5 years ago  sigh), I already did the transformation
for Values for Pharo. Thanks to you, I revised them and published the result
on GitHub (https://github.com/PortingPDFtalk/PharoValues) and added a Pharo
porting page to the wiki (https://wiki.pdftalk.de/doku.php?id=pharoport)
Please have a look.
The fileouts are for Pharo versions 6.1, 7.0, 8.0 and 9.0 (7.0 to 9.0 have
identical sources). The sources load without errors or warnings and all 27
tests pass.
Some of the problems in your code have to do with OrderedDictionary as
superclass of Valuemap. When I did my first round on the port, I had a class
OrderedDictionary in my Values implementation. Unfortunately,
OrderedDictionary does not work as I expected.
(OrderedDictionary with: #a -> 1 with: #b -> 2) =
(OrderedDictionary with: #b -> 2 with: #a -> 1)
answers true, although the order is different. Therefore, it cannot be used
as value.
Instead of raising this issue on a Pharo list (sorry), I decided to use a
new name: Valuemap.
A Valuemap is an OrderedDictionary where the order is relevant for
comparisons.
Squeak had the same problem where it was considered a bug and fixed.
While I subclass Dictionary for Valuemap in Pharo, I can use
OrderedDictionary in Squeak. This removes a lot of methods from the fileout.
A remark about the renamings you propose in your commit comment.
Thank you for the suggestions, but I decline for two reasons:
1. Names for classes, methods and variables are very important to me.
Naming is part of the creative expression of the code author. I do think
much about the right names and therefore, I claim the liberty and right to
name things according to my feeling. Maybe my names are a bit influenced by
German, where we tend to have longer names. Therefore, my names are not so
heavily camel-cased :). In contrast, Pharo has quite a different style with
a love for camel-casing :) (#timeStamp, #nanoSeconds etc.).
2. From a practical view, it would be a lot of work to rename all
references to the items in this basic systems library. There is a lot of
code out there using it. Of course, if there is a good reason for a renaming
(like a spelling mistake or misleading name), it should be done and I am
appreciating any suggestions.
Happy hacking,
Christian
Von: seasidebook <seasidebook(a)free.fr>
Gesendet: Donnerstag, 24. März 2022 21:04
An: Any question about pharo is welcome <pharo-users(a)lists.pharo.org>; Pharo
Development List <pharo-dev(a)lists.pharo.org>
Cc: christian.haider(a)smalltalked-visuals.com
Betreff: Re: [Esug-list] [PDFtalk] Porting to non-namespace Smalltalks
Hi guys
I started to port Values to Pharo.
If you want to give an hand my current effort is here.
<https://github.com/Ducasse/PharoValues>
https://github.com/Ducasse/PharoValues
should migrate license and other stuff too.
S
On 1 Mar 2022, at 19:08, <mailto:christian.haider@smalltalked-visuals.com>
christian.haider(a)smalltalked-visuals.com wrote:
Hi all,
PDFtalk is a PDF library for VisualWorks[1]. The library has been ported
successfully to Gemstone[2].
Now, there is interest from companies in a port to Squeak and VA Smalltalk.
The project[3] has started and we are making good progress.
The first step: porting the Values package.
This is easy, because there are no namespace issues.
The next step is to implement class renamings so that namespaced classes can
be renamed to global prefixed names.
Then PDFtalk with all its components, except for the UI, can be ported.
The porting approach is different to the traditional way of loading and
fixing.
The import files for other Smalltalks are generated from VisualWorks where
the code is transformed by declarative rules.
The approach is documented in [4].
I set up a GitHub organization for this project[5]. There, the fileouts for
each dialect are published (Gemstone, Squeak and VA Smalltalk so far), so
that people without VisualWorks can work with the code in their Smalltalk.
Also, I record and explain all steps of the porting process for Squeak in
great detail[6], so that people can follow it.
I would like to invite Smalltalkers from all dialects to take part in this
project.
The code transformations for Squeak will be quite similar to the ones needed
for Pharo and Cuis.
Therefore, each port to one Smalltalk will help the port to other
Smalltalks.
Any takers?
Happy hacking,
Christian
[1] <https://wiki.pdftalk.de/doku.php?id=start>
https://wiki.pdftalk.de/doku.php?id=start
[2] <https://wiki.pdftalk.de/doku.php?id=pdftalk4gemstone>
https://wiki.pdftalk.de/doku.php?id=pdftalk4gemstone
[3] <https://wiki.pdftalk.de/doku.php?id=pdftalknonnamespacefileout>
https://wiki.pdftalk.de/doku.php?id=pdftalknonnamespacefileout
[4] <https://wiki.pdftalk.de/doku.php?id=smalltalktransform>
https://wiki.pdftalk.de/doku.php?id=smalltalktransform
[5] <https://github.com/PortingPDFtalk> https://github.com/PortingPDFtalk
[6] <https://wiki.pdftalk.de/doku.php?id=valuesportinglog>
https://wiki.pdftalk.de/doku.php?id=valuesportinglog
_______________________________________________
Esug-list mailing list -- <mailto:esug-list@lists.esug.org>
esug-list(a)lists.esug.org
To unsubscribe send an email to <mailto:esug-list-leave@lists.esug.org>
esug-list-leave(a)lists.esug.org
March 27, 2022
How can I use Pharo as an app development space (+ question about jobs)?
by lucasrodriguesoficial5@gmail.com
I'm starting my career as a systems designer and analyst, and for my first project I've decided to make an app/executable in Smalltalk with the bold goal of vanquishing bureaucracy in any public-person interactions which need paper documentation to go through, such as immigration, social programs, housing, or even legal matters. The idea is to find someone to implement it on a national scale somewhere, then spread to the world; or at least land myself a job overseas with the idea as a portfolio. Any kind of job would do, though a outsourcing/freelancing one would be the best.
Problem is, Pharo doesn't have an effective framework for deployable desktop/phone applications, from what the users of its dedicated Discord server said. What toolkit, tutorial or assisting language (could I use to make standalone protoypes for enterprises? I already have the class behavior of the project done, the UI interaction is whatâs lacking. If there really isnât any, should I really start again with a brand new programming language and only use Pharo as a reference?
What also concerns me not only in Pharo but in programming in general is how nothing ever seems to be enough to work for an enterprise, more so as an immigrant. My fear is that, even after the project is finished, I wonât be able to meet the requirements of anyone interested in hiring (my qualifications are a degree in Game Design and few months of an internship experience). People always say that the important thing is to solve problems regardless of whether you know one or many programming languages, but how can that be true when supposedly the most powerful OO language canât deploy a product? How are things ever⦠done in the industry? What knowledge is a staple to anyone willing to work on Systems Design and Analysis field?
March 26, 2022
UK Smalltalk User Group Meeting - Wednesday, March 30th
by Giovanni Corriga
The next meeting of the UK Smalltalk User Group will be held on Wednesday,
March 30th 2022.
Come to hear news about Glamorous Toolkit, the moldable development
environment. We were busy over the past year: beside everything else, GT
also became a multi-language notebook + programmable knowledge management
platform. By this we unify the flows of programming, data science and
knowledge management. And there might be a couple of other surprises, too.
Tudor Gîrba is a software environmentalist and CEO of feenk.com where he
works with an amazing team to make the inside of systems explainable. Much
of the work is embodied in Glamorous Toolkit (gtoolkit.com) a novel
environment that enables Moldable Development.
This will be an online meeting from home.
If you'd like to join us, please sign up in advance on the meeting's Meetup
page to receive the meeting details. Donât forget to bring your laptop and
drinks!
March 22, 2022
Re: Null Object Pattern
by Esteban Maringolo
Being able to proxy to another object is such an important feature,
that even in ES6 (aka "Javascript") there is a Proxy object [1] that
allows you to intercept/redefine operations for that object.
In the case of Smalltalk, and coming back to the original topic of
this thread, that is even more powerful because you have first class
messages that can be resolved via DNU handling. If anything, I would
like to give the receiver of a message more control of the handling of
such a message rather than having a DNU as the last resort, or worse,
some messages that are written to be sent, but then are inlined during
execution.
Regards,
[1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Ob…
Esteban A. Maringolo
On Mon, Mar 21, 2022 at 5:47 PM Tim Mackinnon <tim(a)testit.works> wrote:
>
> This has been an interesting thread to read on the side, and I appreciate the thought provoking conversion.
>
> On Sun, 20 Mar 2022, at 6:11 AM, Richard O'Keefe wrote:
>
> An override of #doesNotUnderstand: *is* (an instance of) the problem.
> What part of "you may think you know what to forward now, but just
> wait a couple of months or install an additional package and there
> will be *more* selectors you needed to think about but didn't" is
> hard to understand?
>
>
> However I am confused by the above - as in Pharo and Dolphin (and I suspect other Smalltalks) - you don't have to make your proxy a subclass of Object right? If you want to forward as much behaviour as possible - you can subclass ProtoObject (or equivalent). The width of methods on that is much reduced (59 from a quick glance), and loading other packages doesn't tend to extend at that level, so keeping things much more stable. The downside, is that such objects are tricky to view in an inspector etc. There is a mocking framework in Pharo called Ghost that leverages this quite well from memory.
>
> So I think that some of the side arguments on downsides might not be quite as bad as indicated.
>
> Tim
>
>
March 21, 2022
Re: Null Object Pattern
by Tim Mackinnon
This has been an interesting thread to read on the side, and I appreciate the thought provoking conversion.
On Sun, 20 Mar 2022, at 6:11 AM, Richard O'Keefe wrote:
> An override of #doesNotUnderstand: *is* (an instance of) the problem.
> What part of "you may think you know what to forward now, but just
> wait a couple of months or install an additional package and there
> will be *more* selectors you needed to think about but didn't" is
> hard to understand?
However I am confused by the above - as in Pharo and Dolphin (and I suspect other Smalltalks) - you don't have to make your proxy a subclass of Object right? If you want to forward as much behaviour as possible - you can subclass ProtoObject (or equivalent). The width of methods on that is much reduced (59 from a quick glance), and loading other packages doesn't tend to extend at that level, so keeping things much more stable. The downside, is that such objects are tricky to view in an inspector etc. There is a mocking framework in Pharo called Ghost that leverages this quite well from memory.
So I think that some of the side arguments on downsides might not be quite as bad as indicated.
Tim
March 21, 2022
Re: Null Object Pattern
by James Foster
Richard,
My primary reference for the Proxy Pattern is the classic "Design Patterns, Elements of Reusable Object-Oriented Software" by Gamma, Helm, Johnson, and Vlissides (Addison-Wesley 1995). In describing how to implement the pattern the âGang of Four (or GOF)" advise âusing doesNotUnderstand in Smalltalkâ (p. 212). Furthermore, as to typing, they say that âProxy doesnât always have to know the type of real subjectâ (213).
The GOF anticipated the problem with inlined selectors and caution that âa few special messages ... are handled directly by the virtual machine [and] do not cause the usual method look-upâ (p. 212). So, I think it is reasonable, in the context of a discussion of the Proxy Pattern, to suggest that the Proxy Pattern would be more effective with fewer inlined selectors.
As to where the Proxy Pattern was developed, the GOF describe âKnown Usesâ including remote objects in NEXTSTEP (1994) and in Smalltalk (1987). In the remote object context, a Proxy has no need to know the type of the target, it just needs to know how to forward messages and return results. While there is typically a way to find out if something is a proxy or not (e.g., #â_isProxyâ) the beauty of the Proxy Pattern is that you donât have to rewrite the entire application and use something like #âapparentClassâ or #âapparentlyNilâ. Only the parts of the application that care if you have a proxy (which will typically not be the main domain code) need to look more deeply (with special selectors or reflection).
It appears that you believe that a untyped proxy to a remote object is bad and that all the code in an application should be written to be aware of the possible âremotenessâ of certain objects. It is my understanding that a transparent untyped proxy to a remote object is well-accepted, extremely useful, and can be implemented reliably.
I donât think I can contribute much more to the conversation than that so Iâll leave it there.
Regards,
James
> On Mar 20, 2022, at 4:55 PM, Richard O'Keefe <raoknz(a)gmail.com> wrote:
>
> Never forget that the Proxy pattern was developed in the context of a TYPED programming
> language. So "Clients can't tell whether they work with a subject or its proxyâ means WITH REFERENCE
> TO A STATED PROTOCOL. Doing this in Ada or Java is fine, because you define an interface type, and that
> makes it safe. Here is a sentence from a typical description of the pattern: "Since the proxy implements the
> INTERFACE as the original class, it can be passed to any client that expects a real service object." Having
> a specified and *enforced* smallish interface prevents the maintenance issues that plague attempts to use
> this pattern in Smalltalk.
>
> Remote objects and local objects have different semantics because remote messages and local messages
> have different semantics. Local messages cannot be lost, duplicated, or reordered, nor can communication
> with a local object drop out for no local reason. Version skew is a much bigger problem with distributed
> systems than local ones, so once again, it is proxying WITH REFERENCE TO A STATED PROTOCOL (and
> that not a large one!) that counts. There is no such thing as a 100% transparent remote proxy. So it is
> very useful to know what an object really is as well as what it pretends to be. That is,
> #class #apparentClass
> #isNil #apparentlyNil
> are *different*,
>
> So the argument thus far is
> - a selector should not be inlined if it might need to be overridden
> - such as in an application of the Proxy pattern
> - but well-designed Proxies are such WITH REFERENCE TO STATED PROTOCOLS
> - meaning that selectors that are NOT in such protocols are fair game for inlining.
>
March 21, 2022
Re: Another question about Spec2 and SpTablePresenter
by Mark O'Donoghue
Hi Esteban
Many thanks for your help on this.
A. I managed to get it working with a small change â which looks like it was due to issue 1263 as you indicated
And this technique was successful my main application too.
Next, I will load the latest merge for Spec2 and do it properly.
âTest class>>esteban <example>
| items |
items := { #one -> 'one'. #two -> 'two' }.
table := SpTablePresenter new
addColumn: (SpStringTableColumn title: 'Key' evaluated: #key);
addColumn: (SpStringTableColumn new
title: 'Value';
evaluated: #value;
beEditable;
onAcceptEdition: [ :item :newValue | item value: (newValue getText string) ];
yourself).
table items: items.
table openWithSpec .â
B. Do you think there is any merit in using a notifications design approach in this example? (e.g. using âmodel changedâ)?
(That was my first instinctâ¦but I couldnât see how to do it.)
If you think that makes sense, does Spec2 have the hooks required to do it this way?
C. My comment on documentation was a good hearted grumble - and is not about the source code...
I think the community urgently needs guides like the âAn Introduction to user interface
building with Spec 2.0â â this one is still WIP after many months.
The trial and error learning curve for all the part timers like me is very inefficient and frustrating.
I understand manpower and time are seriously limiting factors, but more good learning resources would really help wider adoption of Pharo IMHO.
Thatâs just useful feedback I hope⦠ð
Again, many thanks for your help.
Cheers
Mark, Perth WA
From: Esteban Lorenzano <estebanlm(a)netc.eu>
Sent: Sunday, 20 March 2022 10:15 PM
To: Any question about pharo is welcome <pharo-users(a)lists.pharo.org>
Cc: pharo-users(a)lists.pharo.org
Subject: [Pharo-users] Re: Another question about Spec2 and SpTablePresenter
Hi,
well, the incomplete documentation of Spec states clearly that you will be receiving two parameters:
onAcceptEdition: aBlock
"Set the block to execute when cell edition is accepted.
`aBlock` receives two arguments:
- the element of the table (See `SpAbstractListPresenter>>#items:`
- the string entered while editing"
acceptAction := aBlock
So, when you set beEditable to your column, you can do something like this:
items := { #one -> 'one'. #two -> 'two' }.
table := SpTablePresenter new
addColumn: (SpStringTableColumn title: 'Key' evaluated: #key);
addColumn: (SpStringTableColumn new
title: 'Value';
evaluated: #value;
beEditable;
onAcceptEdition: [ :item :newValue | item value: newValue ];
yourself);
items: items;
open.
and then you can edit whatever you want and update your item.
Now, since this is a mechanism that has not been used a lot yet in morphic backend, I just discovered and fixed a bug (not in editable tables, but that affects it: https://github.com/pharo-spec/Spec/issues/1263) so if you want to actually use the functionality, you will need to wait until is merged (tomorrow).
Esteban
On Mar 20 2022, at 10:26 am, Mark O'Donoghue <mark.odonoghue.2010(a)gmail.com <mailto:mark.odonoghue.2010@gmail.com> > wrote:
Howdy all
I am making progress with quite a large application which relies heavily on Spec2
( but Spec2 is such a big learning curve for me â especially given the incomplete documentation⦠ð)
I am currently struggling with the following issue:
I have a SpTablePresenter which shows a collection of domain objects (subclassed from Model).
The domain object are instances of âAssetâ which is a relatively simple class.
The table works fine.
Now, I need to be able to update some columns , but I donât think I want to build a separate form for doing classic CRUD operations.
(There is no need for create or delete functionality â so an in-situ update seems desirableâ¦).
Iâve made a start using SpStringTableColumn >> beEditable and #onAcceptEdition:
But I canât see how to work out what row and column has changed, and how I can update the corresponding Asset instance(s).
It thought it would be handled using #whenModelChanged: but there are models in many places (and at several levels in the Spec hierarchy)â¦
Iâve tried following it all the way down to the adapters and morphs but I canât see how the freshly edited cell interacts with the model or announcements.
(BTW - It doesnât look like the âselected itemâ features are appropriate since you can do edits in other rows regardless of what row is/isnât selected.)
Is there a correct and/or elegant way to detect these cell changes in a SpTablePresenter and apply them to my domain objects�
Cheers
Mark
From: Mark O'Donoghue <mark.odonoghue.2010(a)gmail.com <mailto:mark.odonoghue.2010@gmail.com> >
Sent: Sunday, 4 July 2021 5:26 PM
To: pharo-users(a)lists.pharo.org <mailto:pharo-users@lists.pharo.org>
Subject: Question about Spec2 and SpTablePresenter
Howdy all
Iâve got stuck trying to manage Tables â over 12 hours now and Iâm out of ideas!. â¹
Any observations / suggestions are most welcomeâ¦
Iâve been loading small external files of transactions using NeoCSV into Spec2 tables.
I am trying to use Fuel to persist the table contents so that my application will re-load the working state from where I finished in the last session.
(Iâve opted for Fuel as a simple alternative to having to do the whole object relational mapping thing.)
The idea is that transactions (and potentially some manual adjustments) will be processed over time.
(This is preferable to having to reload all files from the beginning evert time I run the applicationâ¦)
The Spec2 tables have been working well until I tried to persist them.
I canât seem to fully re-load them to a previously saved state.
For example - I can restore the essential contents of my table in most circumstances using:
restoreObjects
âfilePresenter1 is a SpTablePresenterâ
| objects savedEntry |
objects := CpPersist restoreObjectsFromFileNamed: 'E:\Me\zzzST-Test\demo.fuel'.
recentFileList := objects at: 1.
currFileFilter := objects at: 2.
savedEntry := objects at: 3.
self updateFilterButton: currFileFilter.
filteredFileList := self filterFilesUsing: currFileFilter.
filePresenter1 items: filteredFileList.
savedEntry
ifNotNil: [filePresenter1 selectItem: savedEntry ].
However, if any of the table columns are re-sorted , the re-load operation gets confused and I canât get the saved a saved selected item to become selected again.
(It seems to be confusing the index numbers of the sorted and unsorted lists â even when I match by contents rather than index.)
(I also created an equality test to ensure equivalent entries are recognised by the #= operation in the list of the underlying model ).
This all works fine - unless I sort a column!
Since this approach was going to be used on several screens Iâd really like to find a solution.
Cheers
Mark
Perth, Western Australia
March 21, 2022
Re: Null Object Pattern
by Richard O'Keefe
Never forget that the Proxy pattern was developed in the context of a TYPED
programming
language. So "Clients can't tell whether they work with a subject or its
proxyâ means WITH REFERENCE
TO A STATED PROTOCOL. Doing this in Ada or Java is fine, because you
define an interface type, and that
makes it safe. Here is a sentence from a typical description of the
pattern: "Since the proxy implements the
INTERFACE as the original class, it can be passed to any client that
expects a real service object." Having
a specified and *enforced* smallish interface prevents the maintenance
issues that plague attempts to use
this pattern in Smalltalk.
Remote objects and local objects have different semantics because remote
messages and local messages
have different semantics. Local messages cannot be lost, duplicated, or
reordered, nor can communication
with a local object drop out for no local reason. Version skew is a much
bigger problem with distributed
systems than local ones, so once again, it is proxying WITH REFERENCE TO A
STATED PROTOCOL (and
that not a large one!) that counts. There is no such thing as a 100%
transparent remote proxy. So it is
very useful to know what an object really is as well as what it pretends to
be. That is,
#class #apparentClass
#isNil #apparentlyNil
are *different*,
So the argument thus far is
- a selector should not be inlined if it might need to be overridden
- such as in an application of the Proxy pattern
- but well-designed Proxies are such WITH REFERENCE TO STATED PROTOCOLS
- meaning that selectors that are NOT in such protocols are fair game for
inlining.
March 20, 2022
Re: Null Object Pattern
by James Foster
Hello Richard,
> What part of ⦠is hard to understand?
Did you mean for this to come off as condescending? Or are you are honestly wondering how effectively you are communicating? In either case, all of it is hard for me to understand since it doesnât describe the Proxy Pattern which requires that "Clients can't tell whether they work with a subject or its proxyâ (https://en.wikipedia.org/wiki/Proxy_pattern <https://en.wikipedia.org/wiki/Proxy_pattern>). My understanding of a proxy is that it will rarely/never happen that "there will be *more* selectors you needed to think about but didnât." So, far from being (an instance of) the problem, an override of #âdoesNotUnderstand:â is the elegant solution.
> I wanted something that was like an OrderedCollection but could only hold elements of a specific class.
It seems what you want is not a Proxy but a Facade (https://en.wikipedia.org/wiki/Facade_pattern <https://en.wikipedia.org/wiki/Facade_pattern>) in which you "may perform additional functionality [such as type checking] before ... forwarding a requestâ (https://en.wikipedia.org/wiki/Facade_pattern <https://en.wikipedia.org/wiki/Facade_pattern>).
> I *could* make a proxy by going through #doesNotUnderstand: but I am not going to.
Thatâs fine, and a proxy is probably inappropriate for the things you do. But there are a few usage scenarios <https://en.wikipedia.org/wiki/Proxy_pattern#Possible_usage_scenarios> where they are appropriate. My primary experience with them is with distributed object communication <https://en.wikipedia.org/wiki/Distributed_object_communication> where they are appropriate.
> I *could* make a batch of ricin and store it in my granddaughter's bedroom, but I'm not going to.
Iâm glad to hear it. To take a more realistic example, I could try to fly a 747 but Iâm not going to (since my commercial pilotâs license doesnât include that rating). That doesnât mean that no one should fly a 747 (or implement a Proxyâthe people who make GemBuilder for Smalltalk <https://gemtalksystems.com/products/gbs-vw/> should certainly use proxies). I remember hearing a joke about Kent Beck holding a sign saying âWill override #doesNotUnderstand: for foodâ! I took it as not saying that only a genius can understand DNU but that you should think carefully about how it will be used (and in many cases something else would be appropriate). Everything else about Kent Beckâs work makes it clear that leaving behind clear maintainable code is a top priority.
James
> On Mar 19, 2022, at 11:11 PM, Richard O'Keefe <raoknz(a)gmail.com> wrote:
>
> An override of #doesNotUnderstand: *is* (an instance of) the problem.
> What part of "you may think you know what to forward now, but just
> wait a couple of months or install an additional package and there
> will be *more* selectors you needed to think about but didn't" is
> hard to understand?
>
> Proxies done right are proxies *relative to a specified protocol*.
>
> Let me give you a personal example.
> I wanted something that was like an OrderedCollection but
> could only hold elements of a specific class.
> No worries, just make a proxy. Make a bare-bones object,
> define all the #add... methods to check their argument,
> and use #doesNotUnderstand to forward everything else to
> the underlying OrderedCollection.
>
> The first problem is the selectors that the bare-bones
> object *does* understand by virtue of being an object.
> (Remember there are *hundreds* of these selectors in
> Squeak, Pharo, VisualWorks, even in gst there are more
> than 120). You must, for example, ensure that #instVarAt:
> is forwarded, not handled locally, BUT you must also
> ensure that #instVarAt:put: is handled locally, not forwarded.
> And then one day you find that your program has broken,
> because mutable collections now have
> aMutableCollection inPlaceCollect: collectBlock
> and that can put unacceptable results in the collection
> *without* going through any #add... method.
>
> Eventually you realise "handing out a wrapper for this
> collection constrained to only allow adding certain things"
> is the wrong way to do it, and you do something like
>
> constrainedAdder: constraint
> ^[:x | (constraint value: x)
> ifTrue: [self add: x]
> ifFalse: [DomainError receiver: self selector: #add:]]
>
> or you do something else entirely, like handing out a wrapper with
> a *narrow* interface that doesn't make the slightest pretence of
> *being* the other object.
>
> I *could* make a batch of ricin and store it in my
> granddaughter's bedroom, but I'm not going to.
> I *could* make a proxy by going through #doesNotUnderstand:
> but I am not going to. That would be a textbook example of
> maxim 38: "Just because it's easy for you doesn't mean it
> can't be hard on your clients."
>
>
>
>
>
>
> On Sun, 20 Mar 2022 at 15:18, James Foster <smalltalk(a)jgfoster.net <mailto:smalltalk@jgfoster.net>> wrote:
> I donât understand. Wouldnât an override of #'doesNotUnderstand:â solve this problem? The proxies Iâve seen subclass from nil or ProtoObject and forward almost everything to the target. Itâs really very easy.
>
>> On Mar 19, 2022, at 3:14 AM, Richard O'Keefe <raoknz(a)gmail.com <mailto:raoknz@gmail.com>> wrote:
>>
>> An object should be a Proxy or Stub only with reference to a specific protocol, which should be kept narrow.
>>
>> Being a Proxy is a form of coupling. Proxying a wide
>> interface creates maintenance problems:
>> Squeak 5.3 : Object selectors size => 485
>> Pharo 9.0 : Object selectors size => 435
>> astc : Object selectors size => 325
>> VW 8.3PUL : Object selectors size => 304
>>
>> The interface of Object is HUGE. You want to bet that
>> your Proxy got *all* of the methods right? This
>> interface didn't get that way all at once; it grew.
>> The number was 78 in Smalltalk-80. At a minimum, then,
>> Smalltalk systems have accreted one extra Object method
>> every two months.
>>
>> So you set up your proxy to *flawlesly* mirror Object,
>> and then, WHOOPS, upgrade Smalltalk and now there is a
>> method that Object has and your Proxy either lacks (if
>> it descends from ProtoObject but not Object) or inherits
>> an inappropriate version of (if it descends from Object).
>>
>> What this means is that nobody ever *does* flawlessly
>> mock everything in the public interface of an object
>> they are Proxying. They proxy a *limited* protocol.
>> Because that is all they *can* do.
>>
>> Look, I know that people who have been trained to work
>> with the stuff can use C4 as cooking fuel. But I haven't
>> had that training, so I won't touch the stuff. In the
>> same way, I dare say there are things *you* can safely
>> do in Smalltalk that fumblefingers here would be burnt
>> badly by. There are many things that *can* be done that
>> I *won't* do. In a chemistry lab, I would not work with
>> ClF3 let alone O2F2. In Smalltalk, I don't monkey with
>> #isNil.
>>
>> On Fri, 18 Mar 2022 at 03:52, James Foster <smalltalk(a)jgfoster.net <mailto:smalltalk@jgfoster.net>> wrote:
>> Richard,
>>
>> I very much admire Dijkstraâs admonition regarding âThe Humble Programmerâ and was pointing a student to that article just this week.
>>
>> In any case, I think youâve demonstrated that you now comprehend the argument against inliningâyou just donât agree. Thatâs fair and I think the discussion has been clarified. Would it be fair to say that you have an âideological objectionâ to allowing a Proxy or Stub to transparently stand in for another object (say, in a two-object-space environment such as Pharo and GemStone)? That is, a domain object canât be replaced by a Proxy or Stub without a wholesale rewrite of the rest of the application? I respect that as a reasonable position (demanding perfect clarity), but I see a cost to that position as well.
>>
>> Of course, if you really want to avoid allowing the receiver to chose its response to a message, you can use other messages. So if you want to find out if an object is identical to nil you should use `nil == myObject` to ensure that there was not an override of #âisNilâ or #â==â by the objectâs class.
>>
>> James
>>
>>> On Mar 17, 2022, at 2:27 AM, Richard O'Keefe <raoknz(a)gmail.com <mailto:raoknz@gmail.com>> wrote:
>>>
>>> My chief concern is that I am a bear of very little brain,
>>> and if you change the meaning of #isNil to anything at all
>>> other than "is the receiver identical to nil" you *WILL*
>>> (not may) confuse me. This extends to things that happen
>>> not to be inlined: if even a god-like Smalltalker like
>>> Andres Valloud overloads #, to something other than "combine
>>> the collection that is the receiver with the collection that
>>> is the argument to yield a new collection" than I *WILL*
>>> most certainly be confused and find the code unmaintainable.
>>> Smalltalk being Smalltalk, if you admit an inconsistent
>>> overload anywhere, I can no longer understand sends of that
>>> selector anywhere. One of the things to like about Traits
>>> is that you can say "this class doesn't just *happen* to
>>> have selectors x and y, it has them *because* it has this
>>> whole consistent bundle of selectors."
>>>
>>> There are more annotations documented for my Smalltalk
>>> compiler than are actually implemented. One that *is*
>>> implemented is <doNotOverride>, and it has caught more
>>> mistakes than I care to admit to. It's particularly
>>> important for a bundle of methods with varying arguments
>>> that are meant to be routed through a single method,
>>> which *is* meant to be overridden. It makes sure that
>>> I override the *right* method. (Take #= and #~= as an
>>> obvious example.)
>>>
>>> Once you start down the path of lying about things like #isNil
>>> you find that EITHER you have to go very far down that path
>>> and override #== and #instVarAt: and a whole lot of other
>>> things OR you are working with a semantically incoherent system.
>>>
>>> "How should a proxy (https://en.wikipedia.org/wiki/Proxy_pattern <https://en.wikipedia.org/wiki/Proxy_pattern>) to nil respond to the #âisNilâ message?"
>>>
>>> It SHOULD NOT LIE. A proxy *isn't* nil, and it doesn't *behave* like nil,
>>> even if it is a proxy for nil. A proxy, qua proxy, can do things that nil
>>> cannot. Use another selector, #isEffectivelyNil, or whatever reveals your
>>> intentions, and give it what semantics you find useful.
>>>
>>> "How should the Null Object Pattern (https://en.wikipedia.org/wiki/Null_object_pattern <https://en.wikipedia.org/wiki/Null_object_pattern>) respond to #âisNilâ?"
>>>
>>> It should answer false. Period. No ifs, buts, quibbles, or maybes.
>>> The whole *point* of the Null Object Pattern is to return something
>>> that *isn't* nil, that has quite a different protocol. If you call
>>> something that is supposed to return either a Foo or a NullFoo, and
>>> it gives you nil instead, there is a BUG in what you just called so
>>> the sooner you find out the better. What you want is
>>>
>>> Foo >> isNullFoo ^false
>>> NullFoo >> isNullFoo ^true
>>> and no other class defines #isNullFoo.
>>>
>>> That way, when you ask "tripeWorks grobblingMill lastPallet isNullPallet"
>>> (a) you make it clear to someone reading your code what you are expecting
>>> (b) if you DON'T get what you are expecting, Smalltalk will tell you.
>>>
>>> I must admit that on the few occasions when I've used Null Object
>>> I've used an all-purpose #isMissing instead of a task-appropriate
>>> #isNullFoo, but then I figured out what I was doing wrong. You
>>> look at the code, you say "there's *something* off here, but I don't
>>> know what." But when you ask "what, exactly, does this method MEAN?"
>>> you realise "oh, THAT'S what I was doing wrong." #isMissing told me
>>> it was a NullPerson or a NullAddress or a NullPartsList or ... but
>>> in this case I needed to know whether it was a NullSummary.
>>>
>>> And of course you run into E.F.Codd's lesson: "one NULL is never
>>> enough, information can be missing for more than one reason".
>>> Take the familiar example of a phone number:
>>> - I know that Fred's phone number is X
>>> - I know that Fred has a phone but I don't know what the number is
>>> - I don't know whether Fred has a phone or not
>>> - I know that Fred has no phone
>>> There's room for three *different* null objects there.
>>> Should we have UnknownNumberOfActualPhone to answer false to #isnil
>>> and NonNumberOfNonexistentPhone to answer true? Or what?
>>>
>>> By the way, you may have misunderstood my benchmark.
>>> It wasn't that #isNil or even _ ifNotNil: speeded up by
>>> 10%, it was the *whole* matrix-munching benchmark that
>>> speeded up. Certainly not a big deal, but it's not
>>> something I'd be happy to give up in order to get less
>>> maintainable code.
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>> On Thu, 17 Mar 2022 at 18:21, James Foster <smalltalk(a)jgfoster.net <mailto:smalltalk@jgfoster.net>> wrote:
>>> Richard,
>>>
>>> My _concern_ with inlining is that since it is designed to short-circuit dynamic method lookup, it is impossible to call a _different_ implementation. That is, you lose the opportunity to have the _receiver_ decide how to respond to the message. You may think of it as a message, but the caller is deciding how the receiver will respondâwhich largely defeats the purpose and role of it being a message. Yes, at the machine code level you are performing a branch instruction, but when comparing OOP to Procedural Programming we typically make a distinction between âmessagesâ and "procedure calls." The distinction is that the receiver gets to decide how to respond to a message. In C++ this is the distinction between a âvirtual" and "non-virtual" function. By inlining, you are converting the function from a virtual function to a non-virtual function, and this can make a difference (which is why virtual functions exist).
>>>
>>> How should a proxy (https://en.wikipedia.org/wiki/Proxy_pattern <https://en.wikipedia.org/wiki/Proxy_pattern>) to nil respond to the #âisNilâ message? How should the Null Object Pattern (https://en.wikipedia.org/wiki/Null_object_pattern <https://en.wikipedia.org/wiki/Null_object_pattern>) respond to #âisNilâ?
>>>
>>> And, yes, Iâm sure you can come up with benchmarks that show a measurable difference, but what is the impact in realistic code? When someone asked about inlining #âyourselfâ in GemStone I believe I measured the performance as taking 2 nanoseconds per call (on a 2012 machine). A 10% speedup would make it 1.8 nanoseconds. Is that worth it? Maybe, maybe not.
>>>
>>> Note that I described my position as a âconcern,â not an ideological objection. Mostly Iâm giving a rationale for something that doesnât seem to be explained very well for you. I accept that there may be a time for inlining, but I can âcomprehend" another side to the issue.
>>>
>>> James
>>>
>>>> On Mar 16, 2022, at 9:42 PM, Richard O'Keefe <raoknz(a)gmail.com <mailto:raoknz@gmail.com>> wrote:
>>>>
>>>> We're still not on the same page.
>>>> You seem to have some ideological objection to inlining that
>>>> I am completely failing to comprehend.
>>>> Just because a procedure call (message send) is inlined doesn't
>>>> in the least mean it *isn't* a procedure call (message send),
>>>> just as compiling a procedure call (message send) as a jump
>>>> (last-call optimisation) doesn't mean it *isn't* a procedure
>>>> call (message send).
>>>> By the way, forget about "40 years ago".
>>>> I just did an experiment in Pharo 9, and found that
>>>> using "_ ifNotNil: " instead of "_ izNil ifFalse: "
>>>> -- where izNil is a non-inlined self == nil --
>>>> gave a 10% speedup, in a test code where real work was going
>>>> on as well.
>>>> As for turning off all inlining, what do you think that would
>>>> do to #ifFalse:ifTrue: and its relatives?
>>>>
>>>>
>>>> On Thu, 17 Mar 2022 at 08:34, <sean(a)clipperadams.com <mailto:sean@clipperadams.com>> wrote:
>>>>
>>>>
>>>> To start with, why do you CARE whether a particular method is inlined or not?
>>>>
>>>> I care because it makes âeverything is a messageâ a lie! And I suspect (no proof and could be wrong) itâs an optimization that only made sense with the hardware constraints of 40+ years ago. Arguing against premature optimization is hardly something I just made up ;-)
>>>>
>>>> This makes absolutely no sense to me. What makes you think that the combination "_ isNil ifFalse: [_]" will NOT be inlined?
>>>>
>>>> I may have been unclear. My intent was to communicate: âIâd like to stop ALL* inlining of messages by default if possibleâ
>>>>
>>>> *or as many as practical
>>>>
>>>> The thing that rings loud alarm bells for me is there being "long chains" in the first place.
>>>>
>>>> I agree that it is in general a smell, but long chains was tangential to the intention above
>>>>
>>>> Can you give an example?
>>>>
>>>> I donât know if I can think of one thatâs not contrived⦠Wrapping something external? Squeakâs AppleScript support used to mirror the underlying AS, which is pretty much exactly that.
>>>>
>>>> In my own programming, I've generally found that nils turning up in the middle of a chain indicates a serious design error somewhere.
>>>>
>>>> Agreed. See smell comment above.
>>>>
>>>
>>
>
March 20, 2022
Re: Another question about Spec2 and SpTablePresenter
by Esteban Lorenzano
uh, for some reason my mail client eat the formatting... but you get the idea ;)
On Mar 20 2022, at 3:14 pm, Esteban Lorenzano <estebanlm(a)netc.eu> wrote:
> Hi,
>
> well, the incomplete documentation of Spec states clearly that you will be receiving two parameters:
> onAcceptEdition: aBlock
> "Set the block to execute when cell edition is accepted.
> `aBlock` receives two arguments:
> - the element of the table (See `SpAbstractListPresenter>>#items:`
> - the string entered while editing"
> acceptAction := aBlock
>
> So, when you set beEditable to your column, you can do something like this:
> items := { #one -> 'one'. #two -> 'two' }.
> table := SpTablePresenter new
> addColumn: (SpStringTableColumn title: 'Key' evaluated: #key);
> addColumn: (SpStringTableColumn new
> title: 'Value';
> evaluated: #value;
> beEditable;
> onAcceptEdition: [ :item :newValue | item value: newValue ];
> yourself);
> items: items;
> open.
> and then you can edit whatever you want and update your item.
>
> Now, since this is a mechanism that has not been used a lot yet in morphic backend, I just discovered and fixed a bug (not in editable tables, but that affects it: https://github.com/pharo-spec/Spec/issues/1263) so if you want to actually use the functionality, you will need to wait until is merged (tomorrow).
> Esteban
>
> On Mar 20 2022, at 10:26 am, Mark O'Donoghue <mark.odonoghue.2010(a)gmail.com> wrote:
> > Howdy all
> >
> >
> > I am making progress with quite a large application which relies heavily on Spec2
> > ( but Spec2 is such a big learning curve for me â especially given the incomplete documentation⦠ð)
> >
> > I am currently struggling with the following issue:
> > I have a SpTablePresenter which shows a collection of domain objects (subclassed from Model).
> > The domain object are instances of âAssetâ which is a relatively simple class.
> > The table works fine.
> >
> > Now, I need to be able to update some columns , but I donât think I want to build a separate form for doing classic CRUD operations.
> > (There is no need for create or delete functionality â so an in-situ update seems desirableâ¦).
> >
> > Iâve made a start using SpStringTableColumn >> beEditable and #onAcceptEdition:
> >
> > But I canât see how to work out what row and column has changed, and how I can update the corresponding Asset instance(s).
> > It thought it would be handled using #whenModelChanged: but there are models in many places (and at several levels in the Spec hierarchy)â¦
> > Iâve tried following it all the way down to the adapters and morphs but I canât see how the freshly edited cell interacts with the model or announcements.
> >
> > (BTW - It doesnât look like the âselected itemâ features are appropriate since you can do edits in other rows regardless of what row is/isnât selected.)
> >
> > Is there a correct and/or elegant way to detect these cell changes in a SpTablePresenter and apply them to my domain objects�
> >
> > Cheers
> > Mark
> >
> >
> >
> >
> > From: Mark O'Donoghue <mark.odonoghue.2010(a)gmail.com>
> > Sent: Sunday, 4 July 2021 5:26 PM
> > To: pharo-users(a)lists.pharo.org
> > Subject: Question about Spec2 and SpTablePresenter
> >
> >
> >
> >
> >
> > Howdy all
> >
> > Iâve got stuck trying to manage Tables â over 12 hours now and Iâm out of ideas!. â¹
> >
> > Any observations / suggestions are most welcomeâ¦
> >
> > Iâve been loading small external files of transactions using NeoCSV into Spec2 tables.
> > I am trying to use Fuel to persist the table contents so that my application will re-load the working state from where I finished in the last session.
> > (Iâve opted for Fuel as a simple alternative to having to do the whole object relational mapping thing.)
> >
> > The idea is that transactions (and potentially some manual adjustments) will be processed over time.
> > (This is preferable to having to reload all files from the beginning evert time I run the applicationâ¦)
> >
> > The Spec2 tables have been working well until I tried to persist them.
> > I canât seem to fully re-load them to a previously saved state.
> >
> > For example - I can restore the essential contents of my table in most circumstances using:
> >
> > restoreObjects
> >
> > âfilePresenter1 is a SpTablePresenterâ
> >
> > | objects savedEntry |
> >
> > objects := CpPersist restoreObjectsFromFileNamed: 'E:\Me\zzzST-Test\demo.fuel'.
> >
> > recentFileList := objects at: 1.
> > currFileFilter := objects at: 2.
> > savedEntry := objects at: 3.
> >
> > self updateFilterButton: currFileFilter.
> >
> > filteredFileList := self filterFilesUsing: currFileFilter.
> >
> > filePresenter1 items: filteredFileList.
> >
> > savedEntry
> > ifNotNil: [filePresenter1 selectItem: savedEntry ].
> >
> >
> > However, if any of the table columns are re-sorted , the re-load operation gets confused and I canât get the saved a saved selected item to become selected again.
> >
> > (It seems to be confusing the index numbers of the sorted and unsorted lists â even when I match by contents rather than index.)
> > (I also created an equality test to ensure equivalent entries are recognised by the #= operation in the list of the underlying model ).
> >
> > This all works fine - unless I sort a column!
> >
> > Since this approach was going to be used on several screens Iâd really like to find a solution.
> >
> > Cheers
> > Mark
> > Perth, Western Australia
March 20, 2022
Re: Another question about Spec2 and SpTablePresenter
by Esteban Lorenzano
Hi,
well, the incomplete documentation of Spec states clearly that you will be receiving two parameters:
onAcceptEdition: aBlock
"Set the block to execute when cell edition is accepted.
`aBlock` receives two arguments:
- the element of the table (See `SpAbstractListPresenter>>#items:`
- the string entered while editing"
acceptAction := aBlock
So, when you set beEditable to your column, you can do something like this:
items := { #one -> 'one'. #two -> 'two' }.
table := SpTablePresenter new
addColumn: (SpStringTableColumn title: 'Key' evaluated: #key);
addColumn: (SpStringTableColumn new
title: 'Value';
evaluated: #value;
beEditable;
onAcceptEdition: [ :item :newValue | item value: newValue ];
yourself);
items: items;
open.
and then you can edit whatever you want and update your item.
Now, since this is a mechanism that has not been used a lot yet in morphic backend, I just discovered and fixed a bug (not in editable tables, but that affects it: https://github.com/pharo-spec/Spec/issues/1263) so if you want to actually use the functionality, you will need to wait until is merged (tomorrow).
Esteban
On Mar 20 2022, at 10:26 am, Mark O'Donoghue <mark.odonoghue.2010(a)gmail.com> wrote:
> Howdy all
>
>
> I am making progress with quite a large application which relies heavily on Spec2
> ( but Spec2 is such a big learning curve for me â especially given the incomplete documentation⦠ð)
>
> I am currently struggling with the following issue:
> I have a SpTablePresenter which shows a collection of domain objects (subclassed from Model).
> The domain object are instances of âAssetâ which is a relatively simple class.
> The table works fine.
>
> Now, I need to be able to update some columns , but I donât think I want to build a separate form for doing classic CRUD operations.
> (There is no need for create or delete functionality â so an in-situ update seems desirableâ¦).
>
> Iâve made a start using SpStringTableColumn >> beEditable and #onAcceptEdition:
>
> But I canât see how to work out what row and column has changed, and how I can update the corresponding Asset instance(s).
> It thought it would be handled using #whenModelChanged: but there are models in many places (and at several levels in the Spec hierarchy)â¦
> Iâve tried following it all the way down to the adapters and morphs but I canât see how the freshly edited cell interacts with the model or announcements.
>
> (BTW - It doesnât look like the âselected itemâ features are appropriate since you can do edits in other rows regardless of what row is/isnât selected.)
>
> Is there a correct and/or elegant way to detect these cell changes in a SpTablePresenter and apply them to my domain objects�
>
> Cheers
> Mark
>
>
>
>
> From: Mark O'Donoghue <mark.odonoghue.2010(a)gmail.com>
> Sent: Sunday, 4 July 2021 5:26 PM
> To: pharo-users(a)lists.pharo.org
> Subject: Question about Spec2 and SpTablePresenter
>
>
>
>
>
> Howdy all
>
> Iâve got stuck trying to manage Tables â over 12 hours now and Iâm out of ideas!. â¹
>
> Any observations / suggestions are most welcomeâ¦
>
> Iâve been loading small external files of transactions using NeoCSV into Spec2 tables.
> I am trying to use Fuel to persist the table contents so that my application will re-load the working state from where I finished in the last session.
> (Iâve opted for Fuel as a simple alternative to having to do the whole object relational mapping thing.)
>
> The idea is that transactions (and potentially some manual adjustments) will be processed over time.
> (This is preferable to having to reload all files from the beginning evert time I run the applicationâ¦)
>
> The Spec2 tables have been working well until I tried to persist them.
> I canât seem to fully re-load them to a previously saved state.
>
> For example - I can restore the essential contents of my table in most circumstances using:
>
> restoreObjects
>
> âfilePresenter1 is a SpTablePresenterâ
>
> | objects savedEntry |
>
> objects := CpPersist restoreObjectsFromFileNamed: 'E:\Me\zzzST-Test\demo.fuel'.
>
> recentFileList := objects at: 1.
> currFileFilter := objects at: 2.
> savedEntry := objects at: 3.
>
> self updateFilterButton: currFileFilter.
>
> filteredFileList := self filterFilesUsing: currFileFilter.
>
> filePresenter1 items: filteredFileList.
>
> savedEntry
> ifNotNil: [filePresenter1 selectItem: savedEntry ].
>
>
> However, if any of the table columns are re-sorted , the re-load operation gets confused and I canât get the saved a saved selected item to become selected again.
>
> (It seems to be confusing the index numbers of the sorted and unsorted lists â even when I match by contents rather than index.)
> (I also created an equality test to ensure equivalent entries are recognised by the #= operation in the list of the underlying model ).
>
> This all works fine - unless I sort a column!
>
> Since this approach was going to be used on several screens Iâd really like to find a solution.
>
> Cheers
> Mark
> Perth, Western Australia
March 20, 2022
Another question about Spec2 and SpTablePresenter
by Mark O'Donoghue
Howdy all
I am making progress with quite a large application which relies heavily on Spec2
( but Spec2 is such a big learning curve for me â especially given the incomplete documentation⦠ð)
I am currently struggling with the following issue:
I have a SpTablePresenter which shows a collection of domain objects (subclassed from Model).
The domain object are instances of âAssetâ which is a relatively simple class.
The table works fine.
Now, I need to be able to update some columns , but I donât think I want to build a separate form for doing classic CRUD operations.
(There is no need for create or delete functionality â so an in-situ update seems desirableâ¦).
Iâve made a start using SpStringTableColumn >> beEditable and #onAcceptEdition:
But I canât see how to work out what row and column has changed, and how I can update the corresponding Asset instance(s).
It thought it would be handled using #whenModelChanged: but there are models in many places (and at several levels in the Spec hierarchy)â¦
Iâve tried following it all the way down to the adapters and morphs but I canât see how the freshly edited cell interacts with the model or announcements.
(BTW - It doesnât look like the âselected itemâ features are appropriate since you can do edits in other rows regardless of what row is/isnât selected.)
Is there a correct and/or elegant way to detect these cell changes in a SpTablePresenter and apply them to my domain objects�
Cheers
Mark
From: Mark O'Donoghue <mark.odonoghue.2010(a)gmail.com>
Sent: Sunday, 4 July 2021 5:26 PM
To: pharo-users(a)lists.pharo.org
Subject: Question about Spec2 and SpTablePresenter
Howdy all
Iâve got stuck trying to manage Tables â over 12 hours now and Iâm out of ideas!. â¹
Any observations / suggestions are most welcomeâ¦
Iâve been loading small external files of transactions using NeoCSV into Spec2 tables.
I am trying to use Fuel to persist the table contents so that my application will re-load the working state from where I finished in the last session.
(Iâve opted for Fuel as a simple alternative to having to do the whole object relational mapping thing.)
The idea is that transactions (and potentially some manual adjustments) will be processed over time.
(This is preferable to having to reload all files from the beginning evert time I run the applicationâ¦)
The Spec2 tables have been working well until I tried to persist them.
I canât seem to fully re-load them to a previously saved state.
For example - I can restore the essential contents of my table in most circumstances using:
restoreObjects
âfilePresenter1 is a SpTablePresenterâ
| objects savedEntry |
objects := CpPersist restoreObjectsFromFileNamed: 'E:\Me\zzzST-Test\demo.fuel'.
recentFileList := objects at: 1.
currFileFilter := objects at: 2.
savedEntry := objects at: 3.
self updateFilterButton: currFileFilter.
filteredFileList := self filterFilesUsing: currFileFilter.
filePresenter1 items: filteredFileList.
savedEntry
ifNotNil: [filePresenter1 selectItem: savedEntry ].
However, if any of the table columns are re-sorted , the re-load operation gets confused and I canât get the saved a saved selected item to become selected again.
(It seems to be confusing the index numbers of the sorted and unsorted lists â even when I match by contents rather than index.)
(I also created an equality test to ensure equivalent entries are recognised by the #= operation in the list of the underlying model ).
This all works fine - unless I sort a column!
Since this approach was going to be used on several screens Iâd really like to find a solution.
Cheers
Mark
Perth, Western Australia
March 20, 2022
Re: Null Object Pattern
by Richard O'Keefe
An override of #doesNotUnderstand: *is* (an instance of) the problem.
What part of "you may think you know what to forward now, but just
wait a couple of months or install an additional package and there
will be *more* selectors you needed to think about but didn't" is
hard to understand?
Proxies done right are proxies *relative to a specified protocol*.
Let me give you a personal example.
I wanted something that was like an OrderedCollection but
could only hold elements of a specific class.
No worries, just make a proxy. Make a bare-bones object,
define all the #add... methods to check their argument,
and use #doesNotUnderstand to forward everything else to
the underlying OrderedCollection.
The first problem is the selectors that the bare-bones
object *does* understand by virtue of being an object.
(Remember there are *hundreds* of these selectors in
Squeak, Pharo, VisualWorks, even in gst there are more
than 120). You must, for example, ensure that #instVarAt:
is forwarded, not handled locally, BUT you must also
ensure that #instVarAt:put: is handled locally, not forwarded.
And then one day you find that your program has broken,
because mutable collections now have
aMutableCollection inPlaceCollect: collectBlock
and that can put unacceptable results in the collection
*without* going through any #add... method.
Eventually you realise "handing out a wrapper for this
collection constrained to only allow adding certain things"
is the wrong way to do it, and you do something like
constrainedAdder: constraint
^[:x | (constraint value: x)
ifTrue: [self add: x]
ifFalse: [DomainError receiver: self selector: #add:]]
or you do something else entirely, like handing out a wrapper with
a *narrow* interface that doesn't make the slightest pretence of
*being* the other object.
I *could* make a batch of ricin and store it in my
granddaughter's bedroom, but I'm not going to.
I *could* make a proxy by going through #doesNotUnderstand:
but I am not going to. That would be a textbook example of
maxim 38: "Just because it's easy for you doesn't mean it
can't be hard on your clients."
On Sun, 20 Mar 2022 at 15:18, James Foster <smalltalk(a)jgfoster.net> wrote:
> I donât understand. Wouldnât an override of #'doesNotUnderstand:â solve
> this problem? The proxies Iâve seen subclass from nil or ProtoObject and
> forward almost everything to the target. Itâs really very easy.
>
> On Mar 19, 2022, at 3:14 AM, Richard O'Keefe <raoknz(a)gmail.com> wrote:
>
> An object should be a Proxy or Stub only with reference to a specific
> protocol, which should be kept narrow.
>
> Being a Proxy is a form of coupling. Proxying a wide
> interface creates maintenance problems:
> Squeak 5.3 : Object selectors size => 485
> Pharo 9.0 : Object selectors size => 435
> astc : Object selectors size => 325
> VW 8.3PUL : Object selectors size => 304
>
> The interface of Object is HUGE. You want to bet that
> your Proxy got *all* of the methods right? This
> interface didn't get that way all at once; it grew.
> The number was 78 in Smalltalk-80. At a minimum, then,
> Smalltalk systems have accreted one extra Object method
> every two months.
>
> So you set up your proxy to *flawlesly* mirror Object,
> and then, WHOOPS, upgrade Smalltalk and now there is a
> method that Object has and your Proxy either lacks (if
> it descends from ProtoObject but not Object) or inherits
> an inappropriate version of (if it descends from Object).
>
> What this means is that nobody ever *does* flawlessly
> mock everything in the public interface of an object
> they are Proxying. They proxy a *limited* protocol.
> Because that is all they *can* do.
>
> Look, I know that people who have been trained to work
> with the stuff can use C4 as cooking fuel. But I haven't
> had that training, so I won't touch the stuff. In the
> same way, I dare say there are things *you* can safely
> do in Smalltalk that fumblefingers here would be burnt
> badly by. There are many things that *can* be done that
> I *won't* do. In a chemistry lab, I would not work with
> ClF3 let alone O2F2. In Smalltalk, I don't monkey with
> #isNil.
>
> On Fri, 18 Mar 2022 at 03:52, James Foster <smalltalk(a)jgfoster.net> wrote:
>
>> Richard,
>>
>> I very much admire Dijkstraâs admonition regarding âThe Humble
>> Programmerâ and was pointing a student to that article just this week.
>>
>> In any case, I think youâve demonstrated that you now comprehend the
>> argument against inliningâyou just donât agree. Thatâs fair and I think the
>> discussion has been clarified. Would it be fair to say that you have an
>> âideological objectionâ to allowing a Proxy or Stub to transparently stand
>> in for another object (say, in a two-object-space environment such as Pharo
>> and GemStone)? That is, a domain object canât be replaced by a Proxy or
>> Stub without a wholesale rewrite of the rest of the application? I respect
>> that as a reasonable position (demanding perfect clarity), but I see a cost
>> to that position as well.
>>
>> Of course, if you really want to avoid allowing the receiver to chose its
>> response to a message, you can use other messages. So if you want to find
>> out if an object is identical to nil you should use `nil == myObject` to
>> ensure that there was not an override of #âisNilâ or #â==â by the objectâs
>> class.
>>
>> James
>>
>> On Mar 17, 2022, at 2:27 AM, Richard O'Keefe <raoknz(a)gmail.com> wrote:
>>
>> My chief concern is that I am a bear of very little brain,
>> and if you change the meaning of #isNil to anything at all
>> other than "is the receiver identical to nil" you *WILL*
>> (not may) confuse me. This extends to things that happen
>> not to be inlined: if even a god-like Smalltalker like
>> Andres Valloud overloads #, to something other than "combine
>> the collection that is the receiver with the collection that
>> is the argument to yield a new collection" than I *WILL*
>> most certainly be confused and find the code unmaintainable.
>> Smalltalk being Smalltalk, if you admit an inconsistent
>> overload anywhere, I can no longer understand sends of that
>> selector anywhere. One of the things to like about Traits
>> is that you can say "this class doesn't just *happen* to
>> have selectors x and y, it has them *because* it has this
>> whole consistent bundle of selectors."
>>
>> There are more annotations documented for my Smalltalk
>> compiler than are actually implemented. One that *is*
>> implemented is <doNotOverride>, and it has caught more
>> mistakes than I care to admit to. It's particularly
>> important for a bundle of methods with varying arguments
>> that are meant to be routed through a single method,
>> which *is* meant to be overridden. It makes sure that
>> I override the *right* method. (Take #= and #~= as an
>> obvious example.)
>>
>> Once you start down the path of lying about things like #isNil
>> you find that EITHER you have to go very far down that path
>> and override #== and #instVarAt: and a whole lot of other
>> things OR you are working with a semantically incoherent system.
>>
>> "How should a proxy (https://en.wikipedia.org/wiki/Proxy_pattern) to nil
>> respond to the #âisNilâ message?"
>>
>> It SHOULD NOT LIE. A proxy *isn't* nil, and it doesn't *behave* like nil,
>> even if it is a proxy for nil. A proxy, qua proxy, can do things that nil
>> cannot. Use another selector, #isEffectivelyNil, or whatever reveals your
>> intentions, and give it what semantics you find useful.
>>
>> "How should the Null Object Pattern (
>> https://en.wikipedia.org/wiki/Null_object_pattern) respond to #âisNilâ?"
>>
>> It should answer false. Period. No ifs, buts, quibbles, or maybes.
>> The whole *point* of the Null Object Pattern is to return something
>> that *isn't* nil, that has quite a different protocol. If you call
>> something that is supposed to return either a Foo or a NullFoo, and
>> it gives you nil instead, there is a BUG in what you just called so
>> the sooner you find out the better. What you want is
>>
>> Foo >> isNullFoo ^false
>> NullFoo >> isNullFoo ^true
>> and no other class defines #isNullFoo.
>>
>> That way, when you ask "tripeWorks grobblingMill lastPallet isNullPallet"
>> (a) you make it clear to someone reading your code what you are expecting
>> (b) if you DON'T get what you are expecting, Smalltalk will tell you.
>>
>> I must admit that on the few occasions when I've used Null Object
>> I've used an all-purpose #isMissing instead of a task-appropriate
>> #isNullFoo, but then I figured out what I was doing wrong. You
>> look at the code, you say "there's *something* off here, but I don't
>> know what." But when you ask "what, exactly, does this method MEAN?"
>> you realise "oh, THAT'S what I was doing wrong." #isMissing told me
>> it was a NullPerson or a NullAddress or a NullPartsList or ... but
>> in this case I needed to know whether it was a NullSummary.
>>
>> And of course you run into E.F.Codd's lesson: "one NULL is never
>> enough, information can be missing for more than one reason".
>> Take the familiar example of a phone number:
>> - I know that Fred's phone number is X
>> - I know that Fred has a phone but I don't know what the number is
>> - I don't know whether Fred has a phone or not
>> - I know that Fred has no phone
>> There's room for three *different* null objects there.
>> Should we have UnknownNumberOfActualPhone to answer false to #isnil
>> and NonNumberOfNonexistentPhone to answer true? Or what?
>>
>> By the way, you may have misunderstood my benchmark.
>> It wasn't that #isNil or even _ ifNotNil: speeded up by
>> 10%, it was the *whole* matrix-munching benchmark that
>> speeded up. Certainly not a big deal, but it's not
>> something I'd be happy to give up in order to get less
>> maintainable code.
>>
>>
>>
>>
>>
>>
>>
>>
>> On Thu, 17 Mar 2022 at 18:21, James Foster <smalltalk(a)jgfoster.net>
>> wrote:
>>
>>> Richard,
>>>
>>> My _concern_ with inlining is that since it is designed to short-circuit
>>> dynamic method lookup, it is impossible to call a _different_
>>> implementation. That is, you lose the opportunity to have the _receiver_
>>> decide how to respond to the message. You may think of it as a message, but
>>> the caller is deciding how the receiver will respondâwhich largely defeats
>>> the purpose and role of it being a message. Yes, at the machine code level
>>> you are performing a branch instruction, but when comparing OOP to
>>> Procedural Programming we typically make a distinction between âmessagesâ
>>> and "procedure calls." The distinction is that the receiver gets to decide
>>> how to respond to a message. In C++ this is the distinction between a
>>> âvirtual" and "non-virtual" function. By inlining, you are converting the
>>> function from a virtual function to a non-virtual function, and this can
>>> make a difference (which is why virtual functions exist).
>>>
>>> How should a proxy (https://en.wikipedia.org/wiki/Proxy_pattern) to nil
>>> respond to the #âisNilâ message? How should the Null Object Pattern (
>>> https://en.wikipedia.org/wiki/Null_object_pattern) respond to #âisNilâ?
>>>
>>> And, yes, Iâm sure you can come up with benchmarks that show a
>>> measurable difference, but what is the impact in realistic code? When
>>> someone asked about inlining #âyourselfâ in GemStone I believe I measured
>>> the performance as taking 2 nanoseconds per call (on a 2012 machine). A 10%
>>> speedup would make it 1.8 nanoseconds. Is that worth it? Maybe, maybe not.
>>>
>>> Note that I described my position as a âconcern,â not an ideological
>>> objection. Mostly Iâm giving a rationale for something that doesnât seem to
>>> be explained very well for you. I accept that there may be a time for
>>> inlining, but I can âcomprehend" another side to the issue.
>>>
>>> James
>>>
>>> On Mar 16, 2022, at 9:42 PM, Richard O'Keefe <raoknz(a)gmail.com> wrote:
>>>
>>> We're still not on the same page.
>>> You seem to have some ideological objection to inlining that
>>> I am completely failing to comprehend.
>>> Just because a procedure call (message send) is inlined doesn't
>>> in the least mean it *isn't* a procedure call (message send),
>>> just as compiling a procedure call (message send) as a jump
>>> (last-call optimisation) doesn't mean it *isn't* a procedure
>>> call (message send).
>>> By the way, forget about "40 years ago".
>>> I just did an experiment in Pharo 9, and found that
>>> using "_ ifNotNil: " instead of "_ izNil ifFalse: "
>>> -- where izNil is a non-inlined self == nil --
>>> gave a 10% speedup, in a test code where real work was going
>>> on as well.
>>> As for turning off all inlining, what do you think that would
>>> do to #ifFalse:ifTrue: and its relatives?
>>>
>>>
>>> On Thu, 17 Mar 2022 at 08:34, <sean(a)clipperadams.com> wrote:
>>>
>>>>
>>>> To start with, why do you CARE whether a particular method is inlined
>>>> or not?
>>>>
>>>> I care because it makes âeverything is a messageâ a lie! And I suspect
>>>> (no proof and could be wrong) itâs an optimization that only made sense
>>>> with the hardware constraints of 40+ years ago. Arguing against premature
>>>> optimization is hardly something I just made up ;-)
>>>>
>>>> This makes absolutely no sense to me. What makes you think that the
>>>> combination "_ isNil ifFalse: [_]" will NOT be inlined?
>>>>
>>>> I may have been unclear. My intent was to communicate: âIâd like to
>>>> stop ALL* inlining of messages by default if possibleâ
>>>>
>>>> *or as many as practical
>>>>
>>>> The thing that rings loud alarm bells for me is there being "long
>>>> chains" in the first place.
>>>>
>>>> I agree that it is in general a smell, but long chains was tangential
>>>> to the intention above
>>>>
>>>> Can you give an example?
>>>>
>>>> I donât know if I can think of one thatâs not contrived⦠Wrapping
>>>> something external? Squeakâs AppleScript support used to mirror the
>>>> underlying AS, which is pretty much exactly that.
>>>>
>>>> In my own programming, I've generally found that nils turning up in the
>>>> middle of a chain indicates a serious design error somewhere.
>>>>
>>>> Agreed. See smell comment above.
>>>>
>>>
>>>
>>
>
March 20, 2022
Re: Null Object Pattern
by James Foster
I donât understand. Wouldnât an override of #'doesNotUnderstand:â solve this problem? The proxies Iâve seen subclass from nil or ProtoObject and forward almost everything to the target. Itâs really very easy.
> On Mar 19, 2022, at 3:14 AM, Richard O'Keefe <raoknz(a)gmail.com> wrote:
>
> An object should be a Proxy or Stub only with reference to a specific protocol, which should be kept narrow.
>
> Being a Proxy is a form of coupling. Proxying a wide
> interface creates maintenance problems:
> Squeak 5.3 : Object selectors size => 485
> Pharo 9.0 : Object selectors size => 435
> astc : Object selectors size => 325
> VW 8.3PUL : Object selectors size => 304
>
> The interface of Object is HUGE. You want to bet that
> your Proxy got *all* of the methods right? This
> interface didn't get that way all at once; it grew.
> The number was 78 in Smalltalk-80. At a minimum, then,
> Smalltalk systems have accreted one extra Object method
> every two months.
>
> So you set up your proxy to *flawlesly* mirror Object,
> and then, WHOOPS, upgrade Smalltalk and now there is a
> method that Object has and your Proxy either lacks (if
> it descends from ProtoObject but not Object) or inherits
> an inappropriate version of (if it descends from Object).
>
> What this means is that nobody ever *does* flawlessly
> mock everything in the public interface of an object
> they are Proxying. They proxy a *limited* protocol.
> Because that is all they *can* do.
>
> Look, I know that people who have been trained to work
> with the stuff can use C4 as cooking fuel. But I haven't
> had that training, so I won't touch the stuff. In the
> same way, I dare say there are things *you* can safely
> do in Smalltalk that fumblefingers here would be burnt
> badly by. There are many things that *can* be done that
> I *won't* do. In a chemistry lab, I would not work with
> ClF3 let alone O2F2. In Smalltalk, I don't monkey with
> #isNil.
>
> On Fri, 18 Mar 2022 at 03:52, James Foster <smalltalk(a)jgfoster.net <mailto:smalltalk@jgfoster.net>> wrote:
> Richard,
>
> I very much admire Dijkstraâs admonition regarding âThe Humble Programmerâ and was pointing a student to that article just this week.
>
> In any case, I think youâve demonstrated that you now comprehend the argument against inliningâyou just donât agree. Thatâs fair and I think the discussion has been clarified. Would it be fair to say that you have an âideological objectionâ to allowing a Proxy or Stub to transparently stand in for another object (say, in a two-object-space environment such as Pharo and GemStone)? That is, a domain object canât be replaced by a Proxy or Stub without a wholesale rewrite of the rest of the application? I respect that as a reasonable position (demanding perfect clarity), but I see a cost to that position as well.
>
> Of course, if you really want to avoid allowing the receiver to chose its response to a message, you can use other messages. So if you want to find out if an object is identical to nil you should use `nil == myObject` to ensure that there was not an override of #âisNilâ or #â==â by the objectâs class.
>
> James
>
>> On Mar 17, 2022, at 2:27 AM, Richard O'Keefe <raoknz(a)gmail.com <mailto:raoknz@gmail.com>> wrote:
>>
>> My chief concern is that I am a bear of very little brain,
>> and if you change the meaning of #isNil to anything at all
>> other than "is the receiver identical to nil" you *WILL*
>> (not may) confuse me. This extends to things that happen
>> not to be inlined: if even a god-like Smalltalker like
>> Andres Valloud overloads #, to something other than "combine
>> the collection that is the receiver with the collection that
>> is the argument to yield a new collection" than I *WILL*
>> most certainly be confused and find the code unmaintainable.
>> Smalltalk being Smalltalk, if you admit an inconsistent
>> overload anywhere, I can no longer understand sends of that
>> selector anywhere. One of the things to like about Traits
>> is that you can say "this class doesn't just *happen* to
>> have selectors x and y, it has them *because* it has this
>> whole consistent bundle of selectors."
>>
>> There are more annotations documented for my Smalltalk
>> compiler than are actually implemented. One that *is*
>> implemented is <doNotOverride>, and it has caught more
>> mistakes than I care to admit to. It's particularly
>> important for a bundle of methods with varying arguments
>> that are meant to be routed through a single method,
>> which *is* meant to be overridden. It makes sure that
>> I override the *right* method. (Take #= and #~= as an
>> obvious example.)
>>
>> Once you start down the path of lying about things like #isNil
>> you find that EITHER you have to go very far down that path
>> and override #== and #instVarAt: and a whole lot of other
>> things OR you are working with a semantically incoherent system.
>>
>> "How should a proxy (https://en.wikipedia.org/wiki/Proxy_pattern <https://en.wikipedia.org/wiki/Proxy_pattern>) to nil respond to the #âisNilâ message?"
>>
>> It SHOULD NOT LIE. A proxy *isn't* nil, and it doesn't *behave* like nil,
>> even if it is a proxy for nil. A proxy, qua proxy, can do things that nil
>> cannot. Use another selector, #isEffectivelyNil, or whatever reveals your
>> intentions, and give it what semantics you find useful.
>>
>> "How should the Null Object Pattern (https://en.wikipedia.org/wiki/Null_object_pattern <https://en.wikipedia.org/wiki/Null_object_pattern>) respond to #âisNilâ?"
>>
>> It should answer false. Period. No ifs, buts, quibbles, or maybes.
>> The whole *point* of the Null Object Pattern is to return something
>> that *isn't* nil, that has quite a different protocol. If you call
>> something that is supposed to return either a Foo or a NullFoo, and
>> it gives you nil instead, there is a BUG in what you just called so
>> the sooner you find out the better. What you want is
>>
>> Foo >> isNullFoo ^false
>> NullFoo >> isNullFoo ^true
>> and no other class defines #isNullFoo.
>>
>> That way, when you ask "tripeWorks grobblingMill lastPallet isNullPallet"
>> (a) you make it clear to someone reading your code what you are expecting
>> (b) if you DON'T get what you are expecting, Smalltalk will tell you.
>>
>> I must admit that on the few occasions when I've used Null Object
>> I've used an all-purpose #isMissing instead of a task-appropriate
>> #isNullFoo, but then I figured out what I was doing wrong. You
>> look at the code, you say "there's *something* off here, but I don't
>> know what." But when you ask "what, exactly, does this method MEAN?"
>> you realise "oh, THAT'S what I was doing wrong." #isMissing told me
>> it was a NullPerson or a NullAddress or a NullPartsList or ... but
>> in this case I needed to know whether it was a NullSummary.
>>
>> And of course you run into E.F.Codd's lesson: "one NULL is never
>> enough, information can be missing for more than one reason".
>> Take the familiar example of a phone number:
>> - I know that Fred's phone number is X
>> - I know that Fred has a phone but I don't know what the number is
>> - I don't know whether Fred has a phone or not
>> - I know that Fred has no phone
>> There's room for three *different* null objects there.
>> Should we have UnknownNumberOfActualPhone to answer false to #isnil
>> and NonNumberOfNonexistentPhone to answer true? Or what?
>>
>> By the way, you may have misunderstood my benchmark.
>> It wasn't that #isNil or even _ ifNotNil: speeded up by
>> 10%, it was the *whole* matrix-munching benchmark that
>> speeded up. Certainly not a big deal, but it's not
>> something I'd be happy to give up in order to get less
>> maintainable code.
>>
>>
>>
>>
>>
>>
>>
>>
>> On Thu, 17 Mar 2022 at 18:21, James Foster <smalltalk(a)jgfoster.net <mailto:smalltalk@jgfoster.net>> wrote:
>> Richard,
>>
>> My _concern_ with inlining is that since it is designed to short-circuit dynamic method lookup, it is impossible to call a _different_ implementation. That is, you lose the opportunity to have the _receiver_ decide how to respond to the message. You may think of it as a message, but the caller is deciding how the receiver will respondâwhich largely defeats the purpose and role of it being a message. Yes, at the machine code level you are performing a branch instruction, but when comparing OOP to Procedural Programming we typically make a distinction between âmessagesâ and "procedure calls." The distinction is that the receiver gets to decide how to respond to a message. In C++ this is the distinction between a âvirtual" and "non-virtual" function. By inlining, you are converting the function from a virtual function to a non-virtual function, and this can make a difference (which is why virtual functions exist).
>>
>> How should a proxy (https://en.wikipedia.org/wiki/Proxy_pattern <https://en.wikipedia.org/wiki/Proxy_pattern>) to nil respond to the #âisNilâ message? How should the Null Object Pattern (https://en.wikipedia.org/wiki/Null_object_pattern <https://en.wikipedia.org/wiki/Null_object_pattern>) respond to #âisNilâ?
>>
>> And, yes, Iâm sure you can come up with benchmarks that show a measurable difference, but what is the impact in realistic code? When someone asked about inlining #âyourselfâ in GemStone I believe I measured the performance as taking 2 nanoseconds per call (on a 2012 machine). A 10% speedup would make it 1.8 nanoseconds. Is that worth it? Maybe, maybe not.
>>
>> Note that I described my position as a âconcern,â not an ideological objection. Mostly Iâm giving a rationale for something that doesnât seem to be explained very well for you. I accept that there may be a time for inlining, but I can âcomprehend" another side to the issue.
>>
>> James
>>
>>> On Mar 16, 2022, at 9:42 PM, Richard O'Keefe <raoknz(a)gmail.com <mailto:raoknz@gmail.com>> wrote:
>>>
>>> We're still not on the same page.
>>> You seem to have some ideological objection to inlining that
>>> I am completely failing to comprehend.
>>> Just because a procedure call (message send) is inlined doesn't
>>> in the least mean it *isn't* a procedure call (message send),
>>> just as compiling a procedure call (message send) as a jump
>>> (last-call optimisation) doesn't mean it *isn't* a procedure
>>> call (message send).
>>> By the way, forget about "40 years ago".
>>> I just did an experiment in Pharo 9, and found that
>>> using "_ ifNotNil: " instead of "_ izNil ifFalse: "
>>> -- where izNil is a non-inlined self == nil --
>>> gave a 10% speedup, in a test code where real work was going
>>> on as well.
>>> As for turning off all inlining, what do you think that would
>>> do to #ifFalse:ifTrue: and its relatives?
>>>
>>>
>>> On Thu, 17 Mar 2022 at 08:34, <sean(a)clipperadams.com <mailto:sean@clipperadams.com>> wrote:
>>>
>>>
>>> To start with, why do you CARE whether a particular method is inlined or not?
>>>
>>> I care because it makes âeverything is a messageâ a lie! And I suspect (no proof and could be wrong) itâs an optimization that only made sense with the hardware constraints of 40+ years ago. Arguing against premature optimization is hardly something I just made up ;-)
>>>
>>> This makes absolutely no sense to me. What makes you think that the combination "_ isNil ifFalse: [_]" will NOT be inlined?
>>>
>>> I may have been unclear. My intent was to communicate: âIâd like to stop ALL* inlining of messages by default if possibleâ
>>>
>>> *or as many as practical
>>>
>>> The thing that rings loud alarm bells for me is there being "long chains" in the first place.
>>>
>>> I agree that it is in general a smell, but long chains was tangential to the intention above
>>>
>>> Can you give an example?
>>>
>>> I donât know if I can think of one thatâs not contrived⦠Wrapping something external? Squeakâs AppleScript support used to mirror the underlying AS, which is pretty much exactly that.
>>>
>>> In my own programming, I've generally found that nils turning up in the middle of a chain indicates a serious design error somewhere.
>>>
>>> Agreed. See smell comment above.
>>>
>>
>
March 20, 2022
Re: Null Object Pattern
by Richard O'Keefe
An object should be a Proxy or Stub only with reference to a specific
protocol, which should be kept narrow.
Being a Proxy is a form of coupling. Proxying a wide
interface creates maintenance problems:
Squeak 5.3 : Object selectors size => 485
Pharo 9.0 : Object selectors size => 435
astc : Object selectors size => 325
VW 8.3PUL : Object selectors size => 304
The interface of Object is HUGE. You want to bet that
your Proxy got *all* of the methods right? This
interface didn't get that way all at once; it grew.
The number was 78 in Smalltalk-80. At a minimum, then,
Smalltalk systems have accreted one extra Object method
every two months.
So you set up your proxy to *flawlesly* mirror Object,
and then, WHOOPS, upgrade Smalltalk and now there is a
method that Object has and your Proxy either lacks (if
it descends from ProtoObject but not Object) or inherits
an inappropriate version of (if it descends from Object).
What this means is that nobody ever *does* flawlessly
mock everything in the public interface of an object
they are Proxying. They proxy a *limited* protocol.
Because that is all they *can* do.
Look, I know that people who have been trained to work
with the stuff can use C4 as cooking fuel. But I haven't
had that training, so I won't touch the stuff. In the
same way, I dare say there are things *you* can safely
do in Smalltalk that fumblefingers here would be burnt
badly by. There are many things that *can* be done that
I *won't* do. In a chemistry lab, I would not work with
ClF3 let alone O2F2. In Smalltalk, I don't monkey with
#isNil.
On Fri, 18 Mar 2022 at 03:52, James Foster <smalltalk(a)jgfoster.net> wrote:
> Richard,
>
> I very much admire Dijkstraâs admonition regarding âThe Humble Programmerâ
> and was pointing a student to that article just this week.
>
> In any case, I think youâve demonstrated that you now comprehend the
> argument against inliningâyou just donât agree. Thatâs fair and I think the
> discussion has been clarified. Would it be fair to say that you have an
> âideological objectionâ to allowing a Proxy or Stub to transparently stand
> in for another object (say, in a two-object-space environment such as Pharo
> and GemStone)? That is, a domain object canât be replaced by a Proxy or
> Stub without a wholesale rewrite of the rest of the application? I respect
> that as a reasonable position (demanding perfect clarity), but I see a cost
> to that position as well.
>
> Of course, if you really want to avoid allowing the receiver to chose its
> response to a message, you can use other messages. So if you want to find
> out if an object is identical to nil you should use `nil == myObject` to
> ensure that there was not an override of #âisNilâ or #â==â by the objectâs
> class.
>
> James
>
> On Mar 17, 2022, at 2:27 AM, Richard O'Keefe <raoknz(a)gmail.com> wrote:
>
> My chief concern is that I am a bear of very little brain,
> and if you change the meaning of #isNil to anything at all
> other than "is the receiver identical to nil" you *WILL*
> (not may) confuse me. This extends to things that happen
> not to be inlined: if even a god-like Smalltalker like
> Andres Valloud overloads #, to something other than "combine
> the collection that is the receiver with the collection that
> is the argument to yield a new collection" than I *WILL*
> most certainly be confused and find the code unmaintainable.
> Smalltalk being Smalltalk, if you admit an inconsistent
> overload anywhere, I can no longer understand sends of that
> selector anywhere. One of the things to like about Traits
> is that you can say "this class doesn't just *happen* to
> have selectors x and y, it has them *because* it has this
> whole consistent bundle of selectors."
>
> There are more annotations documented for my Smalltalk
> compiler than are actually implemented. One that *is*
> implemented is <doNotOverride>, and it has caught more
> mistakes than I care to admit to. It's particularly
> important for a bundle of methods with varying arguments
> that are meant to be routed through a single method,
> which *is* meant to be overridden. It makes sure that
> I override the *right* method. (Take #= and #~= as an
> obvious example.)
>
> Once you start down the path of lying about things like #isNil
> you find that EITHER you have to go very far down that path
> and override #== and #instVarAt: and a whole lot of other
> things OR you are working with a semantically incoherent system.
>
> "How should a proxy (https://en.wikipedia.org/wiki/Proxy_pattern) to nil
> respond to the #âisNilâ message?"
>
> It SHOULD NOT LIE. A proxy *isn't* nil, and it doesn't *behave* like nil,
> even if it is a proxy for nil. A proxy, qua proxy, can do things that nil
> cannot. Use another selector, #isEffectivelyNil, or whatever reveals your
> intentions, and give it what semantics you find useful.
>
> "How should the Null Object Pattern (
> https://en.wikipedia.org/wiki/Null_object_pattern) respond to #âisNilâ?"
>
> It should answer false. Period. No ifs, buts, quibbles, or maybes.
> The whole *point* of the Null Object Pattern is to return something
> that *isn't* nil, that has quite a different protocol. If you call
> something that is supposed to return either a Foo or a NullFoo, and
> it gives you nil instead, there is a BUG in what you just called so
> the sooner you find out the better. What you want is
>
> Foo >> isNullFoo ^false
> NullFoo >> isNullFoo ^true
> and no other class defines #isNullFoo.
>
> That way, when you ask "tripeWorks grobblingMill lastPallet isNullPallet"
> (a) you make it clear to someone reading your code what you are expecting
> (b) if you DON'T get what you are expecting, Smalltalk will tell you.
>
> I must admit that on the few occasions when I've used Null Object
> I've used an all-purpose #isMissing instead of a task-appropriate
> #isNullFoo, but then I figured out what I was doing wrong. You
> look at the code, you say "there's *something* off here, but I don't
> know what." But when you ask "what, exactly, does this method MEAN?"
> you realise "oh, THAT'S what I was doing wrong." #isMissing told me
> it was a NullPerson or a NullAddress or a NullPartsList or ... but
> in this case I needed to know whether it was a NullSummary.
>
> And of course you run into E.F.Codd's lesson: "one NULL is never
> enough, information can be missing for more than one reason".
> Take the familiar example of a phone number:
> - I know that Fred's phone number is X
> - I know that Fred has a phone but I don't know what the number is
> - I don't know whether Fred has a phone or not
> - I know that Fred has no phone
> There's room for three *different* null objects there.
> Should we have UnknownNumberOfActualPhone to answer false to #isnil
> and NonNumberOfNonexistentPhone to answer true? Or what?
>
> By the way, you may have misunderstood my benchmark.
> It wasn't that #isNil or even _ ifNotNil: speeded up by
> 10%, it was the *whole* matrix-munching benchmark that
> speeded up. Certainly not a big deal, but it's not
> something I'd be happy to give up in order to get less
> maintainable code.
>
>
>
>
>
>
>
>
> On Thu, 17 Mar 2022 at 18:21, James Foster <smalltalk(a)jgfoster.net> wrote:
>
>> Richard,
>>
>> My _concern_ with inlining is that since it is designed to short-circuit
>> dynamic method lookup, it is impossible to call a _different_
>> implementation. That is, you lose the opportunity to have the _receiver_
>> decide how to respond to the message. You may think of it as a message, but
>> the caller is deciding how the receiver will respondâwhich largely defeats
>> the purpose and role of it being a message. Yes, at the machine code level
>> you are performing a branch instruction, but when comparing OOP to
>> Procedural Programming we typically make a distinction between âmessagesâ
>> and "procedure calls." The distinction is that the receiver gets to decide
>> how to respond to a message. In C++ this is the distinction between a
>> âvirtual" and "non-virtual" function. By inlining, you are converting the
>> function from a virtual function to a non-virtual function, and this can
>> make a difference (which is why virtual functions exist).
>>
>> How should a proxy (https://en.wikipedia.org/wiki/Proxy_pattern) to nil
>> respond to the #âisNilâ message? How should the Null Object Pattern (
>> https://en.wikipedia.org/wiki/Null_object_pattern) respond to #âisNilâ?
>>
>> And, yes, Iâm sure you can come up with benchmarks that show a measurable
>> difference, but what is the impact in realistic code? When someone asked
>> about inlining #âyourselfâ in GemStone I believe I measured the performance
>> as taking 2 nanoseconds per call (on a 2012 machine). A 10% speedup would
>> make it 1.8 nanoseconds. Is that worth it? Maybe, maybe not.
>>
>> Note that I described my position as a âconcern,â not an ideological
>> objection. Mostly Iâm giving a rationale for something that doesnât seem to
>> be explained very well for you. I accept that there may be a time for
>> inlining, but I can âcomprehend" another side to the issue.
>>
>> James
>>
>> On Mar 16, 2022, at 9:42 PM, Richard O'Keefe <raoknz(a)gmail.com> wrote:
>>
>> We're still not on the same page.
>> You seem to have some ideological objection to inlining that
>> I am completely failing to comprehend.
>> Just because a procedure call (message send) is inlined doesn't
>> in the least mean it *isn't* a procedure call (message send),
>> just as compiling a procedure call (message send) as a jump
>> (last-call optimisation) doesn't mean it *isn't* a procedure
>> call (message send).
>> By the way, forget about "40 years ago".
>> I just did an experiment in Pharo 9, and found that
>> using "_ ifNotNil: " instead of "_ izNil ifFalse: "
>> -- where izNil is a non-inlined self == nil --
>> gave a 10% speedup, in a test code where real work was going
>> on as well.
>> As for turning off all inlining, what do you think that would
>> do to #ifFalse:ifTrue: and its relatives?
>>
>>
>> On Thu, 17 Mar 2022 at 08:34, <sean(a)clipperadams.com> wrote:
>>
>>>
>>> To start with, why do you CARE whether a particular method is inlined or
>>> not?
>>>
>>> I care because it makes âeverything is a messageâ a lie! And I suspect
>>> (no proof and could be wrong) itâs an optimization that only made sense
>>> with the hardware constraints of 40+ years ago. Arguing against premature
>>> optimization is hardly something I just made up ;-)
>>>
>>> This makes absolutely no sense to me. What makes you think that the
>>> combination "_ isNil ifFalse: [_]" will NOT be inlined?
>>>
>>> I may have been unclear. My intent was to communicate: âIâd like to stop
>>> ALL* inlining of messages by default if possibleâ
>>>
>>> *or as many as practical
>>>
>>> The thing that rings loud alarm bells for me is there being "long
>>> chains" in the first place.
>>>
>>> I agree that it is in general a smell, but long chains was tangential to
>>> the intention above
>>>
>>> Can you give an example?
>>>
>>> I donât know if I can think of one thatâs not contrived⦠Wrapping
>>> something external? Squeakâs AppleScript support used to mirror the
>>> underlying AS, which is pretty much exactly that.
>>>
>>> In my own programming, I've generally found that nils turning up in the
>>> middle of a chain indicates a serious design error somewhere.
>>>
>>> Agreed. See smell comment above.
>>>
>>
>>
>
March 19, 2022
Re: Null Object Pattern
by Todd Blanchard
> On Mar 18, 2022, at 11:39 AM, Esteban Maringolo <emaringolo(a)gmail.com> wrote:
>
> You say that Smalltalk is not so hot for system developments because
> it's extremely malleable? What are you measuring it against?
Lots of things but to keep things simple lets go with Objective C since it is quite similar in concept and style but the library classes are closed to modification without extraordinary effort (you can replace a method but you're gonna have to work to do it because you don't have the source code for the core classes).
>
> It is still easy to break almost anything, without having to resort to
> compiler pragmas. :-)
Yeah, that's kind of my point. I have junked a lot of images in my wake.
>> If anything, I would like to see more immutable structure in the core classes. Add methods? Always. Casually override anything? There be dragons there.
>
> Something like "final" classes and "const" globals or not being able
> to extend classes such as [Proto]Object?
IDK exactly. Yeah, maybe a pragma that was part of the core library that would prevent an override of a key method that say, the browser, depends on.
Smalltalk is great for building things, but unlike when I build, say, a car, I don't have to drag around the entire factory I used to build the car behind it everywhere.
Toying with the idea of using one image to host remote developer tools that we do not change and using it to operate on a second image that has minimal dev tools but will be the production version of my app. That would provide the separation that would keep me from destroying toolkit by accident while trying to tweak the app.
Just musing here. I've become kind of dissatisfied with Pharo development of late. Hard to build anything that lasts very long.
>
>
>
>>
>> On Mar 18, 2022, at 11:06 AM, sean(a)clipperadams.com wrote:
>>
>> I feel like youâve latched onto something that is genuinely a non problemâ¦
>>
>> I wouldnât call complexity and lack of consistency a ânon problemâ, but it sounds like for you the practical implications outweigh my seemingly-somewhat-ideological/niche concerns. Is that a fair summary? In any case, I appreciate your perspective.
>>
>>
March 18, 2022
Re: Null Object Pattern
by Esteban Maringolo
On Fri, Mar 18, 2022 at 3:24 PM Todd Blanchard via Pharo-users
<pharo-users(a)lists.pharo.org> wrote:
>
> What, exactly, is inconsistent about a key message isNil being allowed to be overridden?
Overrides are not the issue here.
> There is a VERY simple solution to your problem that does not involve disrupting the platform.
No, it's not a simple solution.
> But you'd rather change the platform.
I'd bet that the change to inline those message sends came after the
implementation of the message sending.
> Part of the reason Smalltalk has not been the greatest platform to build software on is its extreme malleability. It is a double edged sword for sure. It is great for research. Not so hot for actual systems development.
You say that Smalltalk is not so hot for system developments because
it's extremely malleable? What are you measuring it against?
> "The key in making great and growable systems is much more to design how its modules communicate rather than what their internal properties and behaviors should be. <trim>" -Alan Kay
That's exactly the point of this conversion, a user might want the
modules to communicate by means of sending messages between them,
so writes the code with that expectation and then an external thing (the
compiler) decides to do something else that involves not actually
sending the message, because it focuses on the "internal properties
and behaviors".
> The inlined methods implement key operations that I believe *should* be immutable. Because the system is implemented in terms of itself, it is not very hard to completely destroy an image and render it unusable by overriding the wrong message in the wrong class (try overriding #environment at the class level and let me know how long before your image completely packs up under a torrent of walkbacks).
It is still easy to break almost anything, without having to resort to
compiler pragmas. :-)
> If anything, I would like to see more immutable structure in the core classes. Add methods? Always. Casually override anything? There be dragons there.
Something like "final" classes and "const" globals or not being able
to extend classes such as [Proto]Object?
In any case, I think the options for this inlining thing were laid on
the table, and there is a partial solution for these looking for
"semantic optimization" (as in true message sends) rather than
performance optimization (as in inlining).
Regards!
Esteban A. Maringolo
>
> On Mar 18, 2022, at 11:06 AM, sean(a)clipperadams.com wrote:
>
> I feel like youâve latched onto something that is genuinely a non problemâ¦
>
> I wouldnât call complexity and lack of consistency a ânon problemâ, but it sounds like for you the practical implications outweigh my seemingly-somewhat-ideological/niche concerns. Is that a fair summary? In any case, I appreciate your perspective.
>
>
March 18, 2022
Re: Null Object Pattern
by Todd Blanchard
What, exactly, is inconsistent about a key message isNil being allowed to be overridden?
There is a VERY simple solution to your problem that does not involve disrupting the platform.
But you'd rather change the platform.
Part of the reason Smalltalk has not been the greatest platform to build software on is its extreme malleability. It is a double edged sword for sure. It is great for research. Not so hot for actual systems development.
"The key in making great and growable systems is much more to design how its modules communicate rather than what their internal properties and behaviors should be. Think of the internet â to live, it (a) has to allow many different kinds of ideas and realizations that are beyond any single standard and (b) to allow varying degrees of safe interoperability between these ideas." -Alan Kay
The inlined methods implement key operations that I believe *should* be immutable. Because the system is implemented in terms of itself, it is not very hard to completely destroy an image and render it unusable by overriding the wrong message in the wrong class (try overriding #environment at the class level and let me know how long before your image completely packs up under a torrent of walkbacks).
If anything, I would like to see more immutable structure in the core classes. Add methods? Always. Casually override anything? There be dragons there.
> On Mar 18, 2022, at 11:06 AM, sean(a)clipperadams.com wrote:
>
> I feel like youâve latched onto something that is genuinely a non problemâ¦
>
> I wouldnât call complexity and lack of consistency a ânon problemâ, but it sounds like for you the practical implications outweigh my seemingly-somewhat-ideological/niche concerns. Is that a fair summary? In any case, I appreciate your perspective.
>
March 18, 2022