Pharo-users
By thread
pharo-users@lists.pharo.org
By month
Messages by month
- ----- 2026 -----
- 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
April 2022
- 40 participants
- 123 messages
Re: Intended behaviour of flatten and flatCollect:
by Richard O'Keefe
PS: *Neither* #flattened nor #flatCollect: can be blamed on
40 years of history. #flatten(ed) arrived in Squeak back in
2015, at which time #flatCollect: did not exist. In fact
there is *still* no #flatCollect: in Squeak, although Squeak
does have #gather:, since 2002.
#flatCollect: was added to Pharo more recently still,
as a new name for the tolerably well established #gather:,
apparently in the belief that it was a better name.
Given #flattened, it is not. #gather: is not all that
helpful, but #flatCollect: is just wrong. Even if
#flattened did not exist, the result of #flatCollect:
is generally not in any sense flat.
I repeat: NONE of this can be blamed on Smalltalk history.
#flattened was born crufty in 2015 and #flatCollect: is
a recent addition to Pharo.
On Thu, 14 Apr 2022 at 02:03, Richard O'Keefe <raoknz(a)gmail.com> wrote:
> It would help to know which version of Pharo you are using.
> #(1 2 3) flatten
> raises an exception in Pharo 9 because there is no #flatten
> in Array's protocol.
> Collection has
> #flatCollect:
> -- #gather: was not a terribly helpful name,
> -- but #flatCollect: is horribly misleading.
> #flatCollect:as:
> -- A misplaced method, should be
> -- Collection class >> withAll: aCollection gather: aBlock
> #flatCollectAsSet:
> -- a trivial special case of #flatCollect:as:,
> -- not clear why this special case exists.
> #flattenOn:
> -- aStream nextPutAll: self flattened
> -- but without creating the intermediate data structure
> #flattened
> -- a curiously twisted "flatten" that does not work
> -- at all for non-collections.
>
> #(1 2 3) flattened => #(1 2 3)
> 1 flattened => BOOM!
>
> By the way, we cannot blame the cruftiness of #flattened on
> 40 years of history. #flatten/#flattened only entered Squeak
> about 7 years ago and it was BORN crufty. I mistakenly thought
> Squeak and Pharo agreed on what it meant. They do not.
> Squeak: puts it on SequenceableCollection and Stream.
> Pharo : puts it on Collection (more general) and not Stream (less so).
> Squeak: treats stream elements like nested collections.
> Pharo : doesn't.
> So my earlier claim bears repeating: of the Smalltalk systems that
> have some kind of flattening, no two agree on what it means.
>
> The one use I have ever had for flattening is to build up a
> large string by accumulating characters, strings, symbols,
> and sequences of the same in a sequence and then flattening
> the tree into a single string, which is something that
> Squeak and Pharo flatly refuse to do.
>
> One improvement I would like to see in Pharo 11 is for these
> methods to be deleted.
>
>
April 13, 2022
Re: Intended behaviour of flatten and flatCollect:
by Richard O'Keefe
It would help to know which version of Pharo you are using.
#(1 2 3) flatten
raises an exception in Pharo 9 because there is no #flatten
in Array's protocol.
Collection has
#flatCollect:
-- #gather: was not a terribly helpful name,
-- but #flatCollect: is horribly misleading.
#flatCollect:as:
-- A misplaced method, should be
-- Collection class >> withAll: aCollection gather: aBlock
#flatCollectAsSet:
-- a trivial special case of #flatCollect:as:,
-- not clear why this special case exists.
#flattenOn:
-- aStream nextPutAll: self flattened
-- but without creating the intermediate data structure
#flattened
-- a curiously twisted "flatten" that does not work
-- at all for non-collections.
#(1 2 3) flattened => #(1 2 3)
1 flattened => BOOM!
By the way, we cannot blame the cruftiness of #flattened on
40 years of history. #flatten/#flattened only entered Squeak
about 7 years ago and it was BORN crufty. I mistakenly thought
Squeak and Pharo agreed on what it meant. They do not.
Squeak: puts it on SequenceableCollection and Stream.
Pharo : puts it on Collection (more general) and not Stream (less so).
Squeak: treats stream elements like nested collections.
Pharo : doesn't.
So my earlier claim bears repeating: of the Smalltalk systems that
have some kind of flattening, no two agree on what it means.
The one use I have ever had for flattening is to build up a
large string by accumulating characters, strings, symbols,
and sequences of the same in a sequence and then flattening
the tree into a single string, which is something that
Squeak and Pharo flatly refuse to do.
One improvement I would like to see in Pharo 11 is for these
methods to be deleted.
April 13, 2022
Re: Intended behaviour of flatten and flatCollect:
by Richard O'Keefe
"Flattening" is problematic in every programming language I know
that has something like it in its library. It was born
problematic in Lisp and it has continued problematic ever since.
(I am aware of several Smalltalk systems offering it. With the
exception of Squeak and Pharo, no two of them agree.)
The fundamental problem is that which containers (if any)
should be treated as leaves and which should not is not
something that the language can define. It is problem-specific.
Your best bet is to figure out what YOU need for YOUR problem
and implement exactly that.
I was about to include some code I wrote while trying to make
sense of "flattening", but no. There is no substitute for writing
something that works for precisely the objects you want it to work
and for no others.
April 13, 2022
Re: WebDav and CalDav in Pharo ?
by jonathan@objectguild.com
Hi Udo,
I hope you are well. Would like to hear more about the updates you mentioned back in November 2019 on your FileSystemNetwork library and WebDAV specifically.
We are looking to work with WebDAV/CalDAV using your FileSystemNetwork library for a customer application. As a first step, we have migrated your SmalltalkHub project to a GitHub repo here:Â https://github.com/objectguild/FileSystemNetwork
After some modifications to the code for Pharo 8, all unit tests are showing green (we're using a test server URL created using https://www.webdavserver.com) However, there seem to be some issues handling the actual (binary) file contents. I'm not familiar with the FileSystem classes and I'm having some trouble understanding the technical design, so I'm sure to have made mistakes.
Are you willing (and able) to take a look and help out? Perhaps you can show me in the right direction :-) FYI, we have to work in Pharo 8 because of technical contraints.
Hope to hear from you!
Best,
Jonathan van Alteren
Guild Member | Object Guild B.V. \
Software that works âwithâ you
[jonathan@objectguild.com](mailto:jonathan@objectguild.com)
April 13, 2022
Re: ReStore and storing mixed dictionaries
by John Aspinall
Hi Offray,
There isnât currently a formal way to do the automatic transformation you describe (it would be a nice enhancement though). What I have done in similar situations is to carry out the transformation in inst var accessors, e.g.
userPictureURL
^userPictureURL ifNotNil: [ZnUrl fromString: userPictureURL]
userPictureURL: aZnUrl
userPictureURL := aZnUrl pathPrintString ânot sure if this is the correct conversion but you get the ideaâ
You then define: #userPictureUrl as: String. This works because ReStore accesses instance variables directly via instVarAt:[put:], but obviously depends on your own code using accessors rather than direct references.
Hope this helps.
John
> On 12 Apr 2022, at 18:32, Offray Vladimir Luna Cárdenas <offray.luna(a)mutabit.com> wrote:
>
> Hi John,
>
> Thanks. With the improved error message I was able to pin the cause of error better.
> The issue was that I was declaring the user picture URL as a ZnURL instead of as a string in the reStoreDefinition, but I was not telling ReStore how to store ZnUrl objects. So I made the returning method to give me a string instead of a ZnUrl, which is kind of counterintuitive for the my model, but returned something that ReStore knew how to serialize.
>
> I wonder if there is a way, maybe using something like derived keys, to tell reStoreDefinition: execute this block instead of calling the current method to store the value in the database. So, the #profileImageUrl returns a ZnUrl object inside the image model, but is stored as a string in the database without adding more reStoreDefinition for particular objects (like a ZnUrl). Could be this possible in someway? Am I missing something?
>
> The objects storing is advancing now and hopefully we will have results soon to share, instead of troubleshooting (but we'll share both anyway ;-P).
>
> Cheers,
>
> Offray
> On 7/04/22 16:19, John Aspinall wrote:
>> Hi Offray - could you try modifying SSWReStore>>createProxyForNewObject: as follows:
>>
>> ...
>> table := self tableForClass: anObject class.
>> "Add this ->â table isNil ifTrue: [ self error: 'cannot find table for ', anObject class name ].
>> id := table idDataField ifNotNil: [ :idDataField | idDataField accessor valueIn: anObject].
>> â¦
>>
>> This should change the error message to show the class of object which doesnât have a valid table.
>>
>> Thanks.
>>
>> John
>>
>>
>>> On 7 Apr 2022, at 20:29, Offray Vladimir Luna Cárdenas <offray.luna(a)mutabit.com <mailto:offray.luna@mutabit.com>> wrote:
>>>
>>> Hi John,
>>>
>>> Effectively ReStore didn't was storing the table object for the Nitter class. But after following your advice, i'm now able to debug both the TwitterUser and the NitterUser and obtain the same result (which makes sense as the later is inherited from the former). I think that my error was related with the definition of the synchronized tables, as I was not including explicitly the NitterUser (as I thought it would suffice with the TwitterUser one). Now it looks like this:
>>>
>>> ===
>>> ReStore connection: (SSWSQLite3Connection on: privateDatabase fullName);
>>> connect;
>>> addClasses: { Tweet. "TwitterUser." NitterUser };
>>> synchronizeAllClasses.
>>> ===
>>> Now I can get a non nil idDataField that has the same shape when #tableForClass: and "reStoreDefinition asTableIn: ReStore" are send to TwitterUser and NitterUser. Despite of that I still get the pre-commit error: "#idDataField was send to nil". Here is a screenshot of the trace of the error and the idDataFiled seems right (or at least equal to the same field in the TwitterUser):
>>> https://i.imgur.com/F3UDC93.png <https://i.imgur.com/F3UDC93.png>
>>> For the moment, I'm planing to use an extra/temporal TwitterStoreHelper object that stores via ReStore/SQLite the objects I'm unable to store so far, but as dictionaries of key/value helper objects, where the value is just the STON serialization of the object (with the inconveniences of not being able to query it properly). For example, a 'profiles' dictionary in TwitterStoreHelper would have a Twitter/Nitter user id as a key and its Ston representation as a value. It's a temporal workaround, while I debug the above error further.
>>> I'll keep you posted on the advances and regarding the booklet, I answered you in a direct message.
>>>
>>> Cheers,
>>>
>>> Offray
>>> On 7/04/22 2:59, John Aspinall wrote:
>>>> Hi Offray,
>>>>
>>>> Regarding the error, Iâm guessing that ReStore doesnât have a table object for your NitterUser class for some reason. Could you try:
>>>>
>>>> myReStore tableForClass: NitterUser
>>>>
>>>> â¦and check if this is returning nil? If so thereâs an issue with creating the table for the class; you could try stepping through
>>>>
>>>> NitterUser reStoreDefinition asTableIn: myReStore
>>>>
>>>> ...to get an idea of whatâs wrong.
>>>>
>>>> If this isnât the issue please let me know.
>>>>
>>>> Regarding the manual, Iâll send this to you by mail.
>>>>
>>>> Cheers.
>>>>
>>>> John
>>>>
>>>>
>>>>
>>>>> On 6 Apr 2022, at 19:48, Offray Vladimir Luna Cárdenas <offray.luna(a)mutabit.com <mailto:offray.luna@mutabit.com>> wrote:
>>>>>
>>>>> Thanks Jhon, it definitively helps.
>>>>>
>>>>> What I did was to extract some important metadata as slots of the Tweet object and made explicit the authorId, which allows me to trace tweets authorship:
>>>>>
>>>>> ===
>>>>> Tweet>>class #reStoreDefinition
>>>>> ^ super reStoreDefinition
>>>>> defineAsID: #id;
>>>>> define: #text as: String;
>>>>> define: #created as: String;
>>>>> define: #authorId as: String;
>>>>> define: #timelines as: (Dictionary of: String -> String); yourself
>>>>>
>>>>> ===
>>>>> Also I'm going to put in the radar the idea of storing STON strings for metadata residues.
>>>>>
>>>>> On a related matter, I'm still unable to store properly the NitterUser, which inherits from TwitterUser into SQLite and always get a pre-commit error: "#idDataField was send to nil" when I ran "myNitterUser store". Here is my TwitterUser storing definition:
>>>>>
>>>>> ===
>>>>> TwitterUser>>class #reStoreDefinition
>>>>> ^ super reStoreDefinition
>>>>> defineAsID: #id;
>>>>> define: #userName as: String;
>>>>> define: #profileImageUrl as: String;
>>>>> define: #profileBio as: String;
>>>>> "define: #createdAt as: String;"
>>>>> yourself.
>>>>>
>>>>> ===
>>>>>
>>>>> What I'm missing? And more importantly: how can I debug the message, so I can asign the proper non nil object as receiver of #idDataField ?
>>>>>
>>>>> Finally (for now ;-) ), the ReStore manual has been and important learning resource. Are you the author? And if so, would you be so kind to upload the Word source code to the Documentation/ folder in the repository under a permissive license that allow at least some format changes? We would like to add some table of contents and translate it to other formats, as we have done before with other free/libre cultural works (see [1] [2]).
>>>>>
>>>>> [1] https://mutabit.com/repos.fossil/datafem <https://mutabit.com/repos.fossil/datafem>
>>>>> [2] https://mutabit.com/repos.fossil/mapeda/ <https://mutabit.com/repos.fossil/mapeda/>
>>>>>
>>>>> Thanks,
>>>>>
>>>>> Offray
>>>>> On 6/04/22 2:52, John Aspinall wrote:
>>>>>> Hi Offray,
>>>>>>
>>>>>> Youâre correct that ReStore canât store that kind of mixed dictionary directly. You could store the entire STON text as one string and reify it on read, though that would mean you canât easily query on the metadata.
>>>>>>
>>>>>> A compromise solution would be to define objects and slots for the key data youâd need to query on and a STON string for the residue. This could be a better solution anyway as excessive/complex Dictionaries can be a sign that you need to define a new class/classes. For your particular project this would depend on how similar the metadata is between tweets - if thereâs not much commonality then a Dictionary approach may be more appropriate.
>>>>>>
>>>>>> Hope this helps,
>>>>>>
>>>>>> John
>>>>>>
>>>>>>
>>>>>>
>>>>>>> On 5 Apr 2022, at 20:07, Offray Vladimir Luna Cárdenas <offray.luna(a)mutabit.com <mailto:offray.luna@mutabit.com>> wrote:
>>>>>>>
>>>>>>> Hi all,
>>>>>>>
>>>>>>> First of all, despite of being on a non-directly related matter with my question, congrats of Pharo 10.
>>>>>>>
>>>>>>> We (as now we have 2 active Smalltalkers in my country... Yay!) are creating a civic tech project with Pharo/Lepiter and we would like to store some Tweet metadata coming from Nitter[1]. As we're dealing with the differences between the official Twitter API and the unofficial Nitter one, we put the metadata we need in a dictionary that has several kinds of objects, from ordered collections to other dictionaries.
>>>>>>> [1] https://nitter.net/about <https://nitter.net/about>
>>>>>>> Currently if we serialize a Tweet object in STON, we get this:
>>>>>>>
>>>>>>> Tweet { #created : 'Tue, 05 Apr 2022 12:37:56 GMT', #text : '
>>>>>>>
>>>>>>> [ANN] Pharo 10 Released: pharo.org/news/pharo10-relea⦠<https://pharo.org/news/pharo10-released>\n', #id : '1511322244353597443', #user : NitterUser { #userName : 'pharoproject', #profileImageUrl : URL [ 'http://nitter.42l.fr/pic/pbs.twimg.com/profile_images/541743734/icone-pharo… <http://nitter.42l.fr/pic/pbs.twimg.com/profile_images/541743734/icone-pharo…>' ] }, #metadata : { 'queries' : OrderedCollection [ { 'date' : DateAndTime [ '2022-04-05T13:36:58.546011-05:00' ], 'parameters' : 'https://nitter.42l.fr/pharoproject <https://nitter.42l.fr/pharoproject>' } ], 'timelines' : { 'pharoproject' : '1511048498703126529' } } }
>>>>>>> As you can see, the metadata slot contains a dictionary with mixed classes of objects. But I read in the ReStore manual[2] (pg 14):
>>>>>>>
>>>>>>> """
>>>>>>>
>>>>>>> Like other collections, the class of elements for both key and value can be any other
>>>>>>> persistent class, and will be the same for all elements of that collection (except in the case of
>>>>>>> inheritance).
>>>>>>> """
>>>>>>> So, is ReStore unable to store metadata dictionaries like the one described in the previous STON code? if this is possible, how can I define it in the Tweet class>>reStoreDefinition?
>>>>>>> For the moment, I'm going to create a explicit "timelines" slot to store what was being stored at the #timelines key of the metadata dictionary. But, as metadata increases, instead of moving variables previously inside of a dictionary as explicit slots of an object, I think that having a explicit way of storing dictionaries with different kinds of objects, in contrast with only uniform ones, would be needed (but I don't know if this is in the design scope of ReStore).
>>>>>>>
>>>>>>> BTW, Lepiter has allow us to build a pretty fluent interface to browser Twitter/Nitter profiles and messages. Here it is how such UI looks for browsing last @pharoproject tweets:
>>>>>>>
>>>>>>> https://i.imgur.com/bxFze1g.png <https://i.imgur.com/bxFze1g.png>
>>>>>>> Any help on how to use ReStore in storing mixed dictionaries is appreciated.
>>>>>>>
>>>>>>> Thanks,
>>>>>>>
>>>>>>> Offray
>>>>>>
>>>>
>>
April 13, 2022
Re: ReStore and storing mixed dictionaries
by Offray Vladimir Luna Cárdenas
Hi John,
Thanks. With the improved error message I was able to pin the cause of
error better.
The issue was that I was declaring the user picture URL as a ZnURL
instead of as a string in the reStoreDefinition, but I was not telling
ReStore how to store ZnUrl objects. So I made the returning method to
give me a string instead of a ZnUrl, which is kind of counterintuitive
for the my model, but returned something that ReStore knew how to serialize.
I wonder if there is a way, maybe using something like derived keys, to
tell reStoreDefinition: execute this block instead of calling the
current method to store the value in the database. So, the
#profileImageUrl returns a ZnUrl object inside the image model, but is
stored as a string in the database without adding more reStoreDefinition
for particular objects (like a ZnUrl). Could be this possible in
someway? Am I missing something?
The objects storing is advancing now and hopefully we will have results
soon to share, instead of troubleshooting (but we'll share both anyway ;-P).
Cheers,
Offray
On 7/04/22 16:19, John Aspinall wrote:
> Hi Offray - could you try modifying
> SSWReStore>>createProxyForNewObject: as follows:
>
> ...
> Â Â Â table := self tableForClass: anObject class.
> "Add this ->â Â table isNil ifTrue: [ self error: 'cannot find table
> for ', anObject class name ].
> Â Â Â id := table idDataField ifNotNil: [ :idDataField | idDataField
> accessor valueIn: anObject].
>    â¦
>
> This should change the error message to show the class of object which
> doesnât have a valid table.
>
> Thanks.
>
> John
>
>
>> On 7 Apr 2022, at 20:29, Offray Vladimir Luna Cárdenas
>> <offray.luna(a)mutabit.com> wrote:
>>
>> Hi John,
>>
>> Effectively ReStore didn't was storing the table object for the
>> Nitter class. But after following your advice, i'm now able to debug
>> both the TwitterUser and the NitterUser and obtain the same result
>> (which makes sense as the later is inherited from the former). I
>> think that my error was related with the definition of the
>> synchronized tables, as I was not including explicitly the
>> NitterUser (as I thought it would suffice with the TwitterUser one).
>> Now it looks like this:
>>
>> ===
>> ReStore connection: (SSWSQLite3Connection on: privateDatabase fullName);
>> Â Â Â connect;
>> Â Â Â addClasses: { Tweet. "TwitterUser." NitterUser };
>> Â Â Â synchronizeAllClasses.
>> ===
>>
>> Now I can get a non nil idDataField that has the same shape when
>> #tableForClass: and "reStoreDefinition asTableIn: ReStore" are send
>> to TwitterUser and NitterUser. Despite of that I still get the
>> pre-commit error: "#idDataField was send to nil". Here is a
>> screenshot of the trace of the error and the idDataFiled seems right
>> (or at least equal to the same field in the TwitterUser):
>>
>> https://i.imgur.com/F3UDC93.png
>>
>> For the moment, I'm planing to use an extra/temporal
>> TwitterStoreHelper object that stores via ReStore/SQLite the objects
>> I'm unable to store so far, but as dictionaries of key/value helper
>> objects, where the value is just the STON serialization of the object
>> (with the inconveniences of not being able to query it properly). For
>> example, a 'profiles' dictionary in TwitterStoreHelper would have a
>> Twitter/Nitter user id as a key and its Ston representation as a
>> value. It's a temporal workaround, while I debug the above error further.
>>
>> I'll keep you posted on the advances and regarding the booklet, I
>> answered you in a direct message.
>>
>> Cheers,
>>
>> Offray
>>
>> On 7/04/22 2:59, John Aspinall wrote:
>>> Hi Offray,
>>>
>>> Regarding the error, Iâm guessing that ReStore doesnât have a table
>>> object for your NitterUser class for some reason. Could you try:
>>>
>>> Â Â myReStore tableForClass: NitterUser
>>>
>>> â¦and check if this is returning nil? If so thereâs an issue with
>>> creating the table for the class; you could try stepping through
>>>
>>> Â Â NitterUser reStoreDefinition asTableIn: myReStore
>>>
>>> ...to get an idea of whatâs wrong.
>>>
>>> If this isnât the issue please let me know.
>>>
>>> Regarding the manual, Iâll send this to you by mail.
>>>
>>> Cheers.
>>>
>>> John
>>>
>>>
>>>
>>>> On 6 Apr 2022, at 19:48, Offray Vladimir Luna Cárdenas
>>>> <offray.luna(a)mutabit.com> wrote:
>>>>
>>>> Thanks Jhon, it definitively helps.
>>>>
>>>> What I did was to extract some important metadata as slots of the
>>>> Tweet object and made explicit the authorId, which allows me to
>>>> trace tweets authorship:
>>>>
>>>> ===
>>>> Tweet>>class #reStoreDefinition
>>>> ^ super reStoreDefinition
>>>> Â Â Â defineAsID: #id;
>>>> Â Â Â define: #text as: String;
>>>> Â Â Â define: #created as: String;
>>>> Â Â Â define: #authorId as: String;
>>>> Â Â Â define: #timelines as: (Dictionary of: String -> String); yourself
>>>>
>>>> ===
>>>>
>>>> Also I'm going to put in the radar the idea of storing STON strings
>>>> for metadata residues.
>>>>
>>>> On a related matter, I'm still unable to store properly the
>>>> NitterUser, which inherits from TwitterUser into SQLite and always
>>>> get a pre-commit error: "#idDataField was send to nil" when I ran
>>>> "myNitterUser store". Here is my TwitterUser storing definition:
>>>>
>>>> ===
>>>> TwitterUser>>class #reStoreDefinition
>>>>
>>>> Â Â Â ^ super reStoreDefinition
>>>> Â Â Â Â Â Â Â Â Â defineAsID: #id;
>>>> Â Â Â Â Â Â Â Â Â define: #userName as: String;
>>>> Â Â Â Â Â Â Â Â Â define: #profileImageUrl as: String;
>>>> Â Â Â Â Â Â Â Â Â define: #profileBio as: String;
>>>> Â Â Â Â Â Â Â Â Â "define: #createdAt as: String;"
>>>> Â Â Â Â Â Â Â Â Â yourself.
>>>>
>>>> ===
>>>>
>>>> What I'm missing? And more importantly: how can I debug the
>>>> message, so I can asign the proper non nil object as receiver of
>>>> #idDataField ?
>>>>
>>>> Finally (for now ;-) ), the ReStore manual has been and important
>>>> learning resource. Are you the author? And if so, would you be so
>>>> kind to upload the Word source code to the Documentation/ folder in
>>>> the repository under a permissive license that allow at least some
>>>> format changes? We would like to add some table of contents and
>>>> translate it to other formats, as we have done before with other
>>>> free/libre cultural works (see [1] [2]).
>>>>
>>>> [1] https://mutabit.com/repos.fossil/datafem
>>>> [2] https://mutabit.com/repos.fossil/mapeda/
>>>>
>>>> Thanks,
>>>>
>>>> Offray
>>>>
>>>> On 6/04/22 2:52, John Aspinall wrote:
>>>>> Hi Offray,
>>>>>
>>>>> Youâre correct that ReStore canât store that kind of mixed
>>>>> dictionary directly. You could store the entire STON text as one
>>>>> string and reify it on read, though that would mean you canât
>>>>> easily query on the metadata.
>>>>>
>>>>> A compromise solution would be to define objects and slots for the
>>>>> key data youâd need to query on and a STON string for the residue.
>>>>> This could be a better solution anyway as excessive/complex
>>>>> Dictionaries can be a sign that you need to define a new
>>>>> class/classes. For your particular project this would depend on
>>>>> how similar the metadata is between tweets - if thereâs not much
>>>>> commonality then a Dictionary approach may be more appropriate.
>>>>>
>>>>> Hope this helps,
>>>>>
>>>>> John
>>>>>
>>>>>
>>>>>
>>>>>> On 5 Apr 2022, at 20:07, Offray Vladimir Luna Cárdenas
>>>>>> <offray.luna(a)mutabit.com> wrote:
>>>>>>
>>>>>> Hi all,
>>>>>>
>>>>>> First of all, despite of being on a non-directly related matter
>>>>>> with my question, congrats of Pharo 10.
>>>>>>
>>>>>> We (as now we have 2 active Smalltalkers in my country... Yay!)
>>>>>> are creating a civic tech project with Pharo/Lepiter and we would
>>>>>> like to store some Tweet metadata coming from Nitter[1]. As we're
>>>>>> dealing with the differences between the official Twitter API and
>>>>>> the unofficial Nitter one, we put the metadata we need in a
>>>>>> dictionary that has several kinds of objects, from ordered
>>>>>> collections to other dictionaries.
>>>>>>
>>>>>> [1] https://nitter.net/about
>>>>>>
>>>>>> Currently if we serialize a Tweet object in STON, we get this:
>>>>>>
>>>>>> Tweet { #created : 'Tue, 05 Apr 2022 12:37:56 GMT', #text : '
>>>>>>
>>>>>> [ANN] Pharo 10 Released: pharo.org/news/pharo10-releaâ¦
>>>>>> <https://pharo.org/news/pharo10-released>
>>>>>>
>>>>>> \n', #id : '1511322244353597443', #user : NitterUser { #userName
>>>>>> : 'pharoproject', #profileImageUrl : URL [
>>>>>> 'http://nitter.42l.fr/pic/pbs.twimg.com/profile_images/541743734/icone-pharo…'
>>>>>> ] }, #metadata : { 'queries' : OrderedCollection [ { 'date' :
>>>>>> DateAndTime [ '2022-04-05T13:36:58.546011-05:00' ], 'parameters'
>>>>>> : 'https://nitter.42l.fr/pharoproject' } ], 'timelines' : {
>>>>>> 'pharoproject' : '1511048498703126529' } } }
>>>>>>
>>>>>> As you can see, the metadata slot contains a dictionary with
>>>>>> mixed classes of objects. But I read in the ReStore manual[2] (pg
>>>>>> 14):
>>>>>>
>>>>>> """
>>>>>>
>>>>>> Like other collections, the class of elements for both key and
>>>>>> value can be any other
>>>>>> persistent class, and will be the same for all elements of that
>>>>>> collection (except in the case of
>>>>>> inheritance).
>>>>>>
>>>>>> """
>>>>>>
>>>>>> So, is ReStore unable to store metadata dictionaries like the one
>>>>>> described in the previous STON code? if this is possible, how can
>>>>>> I define it in the Tweet class>>reStoreDefinition?
>>>>>>
>>>>>> For the moment, I'm going to create a explicit "timelines" slot
>>>>>> to store what was being stored at the #timelines key of the
>>>>>> metadata dictionary. But, as metadata increases, instead of
>>>>>> moving variables previously inside of a dictionary as explicit
>>>>>> slots of an object, I think that having a explicit way of storing
>>>>>> dictionaries with different kinds of objects, in contrast with
>>>>>> only uniform ones, would be needed (but I don't know if this is
>>>>>> in the design scope of ReStore).
>>>>>>
>>>>>> BTW, Lepiter has allow us to build a pretty fluent interface to
>>>>>> browser Twitter/Nitter profiles and messages. Here it is how such
>>>>>> UI looks for browsing last @pharoproject tweets:
>>>>>>
>>>>>> https://i.imgur.com/bxFze1g.png
>>>>>>
>>>>>> Any help on how to use ReStore in storing mixed dictionaries is
>>>>>> appreciated.
>>>>>>
>>>>>> Thanks,
>>>>>>
>>>>>> Offray
>>>>>>
>>>>>
>>>
>
April 12, 2022
Re: Intended behaviour of flatten and flatCollect:
by Konrad Hinsen
Hi Kasper,
Thanks for your reply!
> Sorry, but which version of Pharo are we talking about.
Sorry, I forgot to say that I am still using Pharo 9.
> I just tried with Pharo 10, which has no flatten method for arrays at
Interesting. So I double-checked - and found that the "flatten" in my
image actually comes from an add-on package called CollectionExtensions
(https://github.com/pharo-contributions/CollectionExtensions/blob/master/src…) So
I will complain there :-)
> I am not going to comment on naming of such core api methods - they tend to have
> a 40 year history of forgotten arguments and random âclean upsâ.
I agree, I didn't expect any level of homogeneous naming. Just an
agreement between code and documentation.
Cheers,
Konrad
April 12, 2022
Re: Intended behaviour of flatten and flatCollect:
by Kasper Osterbye
Hi Konrad
Sorry, but which version of Pharo are we talking about. I just tried with Pharo 10,
which has no flatten method for arrays at all, somewhere along the version I believe
the method was renamed to flattened.
#(1 #(2 #(a b) 3) 4) flattened >>> #(1 2 #a #b 3 4) as one would expect.
flatCollect: does not flatten the collection it is called on, but the result produced by the block
#(1 3) flatCollect: [ :e | {e. e * 10} ] >>> #(1 10 3 30), and
#(1 #(2 3 #(4 5)) 6) flatCollect: [ :e | {e. e * 10} ] >>> #(1 10 #(2 3 #(4 5)) #(20 30 #(40 50)) 6 60)
I am not going to comment on naming of such core api methods - they tend to have
a 40 year history of forgotten arguments and random âclean upsâ.
Best,
Kasper
> On 12 Apr 2022, at 11.51, Konrad Hinsen <konrad.hinsen(a)fastmail.net> wrote:
>
> Hi everyone,
>
> I am getting surprising results trying to flatten nested arrays. So I
> read the docstrings. And now I understand even less how flatten and
> flatCollect are supposed to work.
>
> flatten says:
>
> "Recursively collect each non-collection element of the receiver and
> its descendant collections. Please note, this implementation
> assumes that strings are to be treated as objects rather than as
> collection."
>
> That suggests that
>
> #(1 2 3) flatten
>
> should yield #(1 2 3). But it raises an exception, trying to send do: to
> an integer.
>
> A quick look at the code shows that flatten is just flatCollect: [
> :each | each ]. flatCollect: says:
>
> "Evaluate aBlock for each of the receiver's elements and answer the
> list of all resulting values flatten one level. Assumes that aBlock
> returns some kind of collection for each element. Equivalent to the
> lisp's mapcan"
>
> "Flatten one level" is different from flatten's "recursively". The
> assumption that aBlock returns a collection is also incompatible with
> what flatten is supposed to do (and explains my exception).
>
> I don't find the reference to a Lisp function very helpful. Assuming
> "Lisp" means "Common Lisp", this confirms the docstring of flatCollect:,
> this confirms the assumption of aBlock returning a collection, and that
> only one level of nesting is flattened.
>
> Since flatCollect does what it says, the problem seems to be in
> flatten. Either its docstring or its implementation are wrong.
>
> Or is it me misunderstanding something?
>
> Cheers,
> Konrad
April 12, 2022