On Mon, Nov 9, 2020 at 8:29 AM Thiede, Christoph <[hidden email]> wrote:
If the doesNotUnderstand: is not visible externally then who cares? Isn't the contract (o respondsTo: m) ifFalse: [self should: [o m] raise: MessageNotUnderstood]], or respondsTo: not implies MNU ?
_,,,^..^,,,_ best, Eliot |
In reply to this post by Eliot Miranda-2
> And canUnderstand: ? Or is that being too picky? Ah, right. On the class level, it would be like Levente inferred from my suggestion. I only thought of #respondsTo: to answer "true" only for the simple setter/getters that have keys present in the actual dictionary instance. Hmmm..... I would like to keep the JSON library as simple as possible. Wer are just talking about syntactic sugar here, right? Best, Marcel
|
Hi all, for importing Matlab struct, I create classes on the fly and generate the getter setter on demand (via doesNotUnderstand:) See MatFileReader package in http://www.squeaksource.com/STEM.html Le mar. 10 nov. 2020 à 09:06, Marcel Taeumel <[hidden email]> a écrit :
|
> and generate the getter setter on demand (via doesNotUnderstand:) That's what I opted for, too, in: https://github.com/hpi-swa/MessageSendRecorder 's MessageSendRecordExtension. Best. Marcel
|
Hi all,
> And canUnderstand: ? Or is that being too picky?
> If the doesNotUnderstand: is not visible externally then who cares? Isn't the contract (o respondsTo: m) ifFalse: [self should: [o m] raise: MessageNotUnderstood]], or respondsTo: not implies MNU ? Well, my conception of the general contract would be exactly the following:
(o class canUnderstand: m) ifTrue: [
self assert: [o respondsTo: m]].
(o respondsTo: m) ifFalse: [
self deny: [o class canUnderstand: m]].
(o respondsTo: m) ifTrue: [
self shouldnt: [o m] raise: MessageNotUnderstood].
[o m] on: MessageNotUnderstood do: [
self deny: [o respondsTo: m]].
But I would *not* require the other direction of the implication - for #canUnderstand:, this is simply not possible for dynamic forwarding (unless we make false promises on the class side), and in my opinion, the
current discussion shows that the same argument applies for the second statement, too.
> I would like to keep the JSON library as simple as possible. Wer are just talking about syntactic sugar here, right?
IMHO, this goes beyond syntactic sugar. :-) As I tried to explain below, a proper implementation of #respondsTo: could be an essential prerequisite for using JsonObjects polymorphically with first-class object instances. In my use case, this is a crucial
feature and if my proposal is discarded, I will have to subclass JsonObject ...
Best,
Christoph
Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel
Gesendet: Dienstag, 10. November 2020 09:34:49 An: squeak-dev Betreff: Re: [squeak-dev] I'd like to contribute to the JSON project
> and generate the getter setter on demand (via doesNotUnderstand:)
That's what I opted for, too, in: https://github.com/hpi-swa/MessageSendRecorder 's
MessageSendRecordExtension.
Best.
Marcel
Carpe Squeak!
|
Hi all. I am in favor of adding JsonDynamicObject (or similar) which has those extra features. I would avoid putting that stuff into JsonObject. When parsing a JSON file, the dictionary class can be configured anyway. Best, Marcel
|
Hi Marcel,
so do you propose to remove the existing implementation of dynamic forwarding from JsonObject, too (or more precisely, pull it down into DynamicJsonObject)? If yes, I would worry about compatibility problems. If no, I do not quite understand why one should override #doesNotUnderstand: but not #respondsTo: in a class. It seems a reasonable pattern for me to override them only together. :-)
Best, Christoph Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel
Gesendet: Donnerstag, 12. November 2020 10:07:28 An: squeak-dev Betreff: Re: [squeak-dev] I'd like to contribute to the JSON project
Hi all.
I am in favor of adding JsonDynamicObject (or similar) which has those extra features. I would avoid putting that stuff into JsonObject. When parsing a JSON file, the dictionary class can be configured anyway.
Best,
Marcel
Carpe Squeak!
|
(Depending on how this discussion will end, this reparented mcz file might be relevant to prevent further merging issues.)
Von: Thiede, Christoph
Gesendet: Montag, 16. November 2020 16:22:01 An: squeak-dev Betreff: AW: [squeak-dev] I'd like to contribute to the JSON project Hi Marcel,
so do you propose to remove the existing implementation of dynamic forwarding from JsonObject, too (or more precisely, pull it down into DynamicJsonObject)? If yes, I would worry about compatibility problems. If no, I do not quite understand why one should override #doesNotUnderstand: but not #respondsTo: in a class. It seems a reasonable pattern for me to override them only together. :-)
Best, Christoph Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel
Gesendet: Donnerstag, 12. November 2020 10:07:28 An: squeak-dev Betreff: Re: [squeak-dev] I'd like to contribute to the JSON project
Hi all.
I am in favor of adding JsonDynamicObject (or similar) which has those extra features. I would avoid putting that stuff into JsonObject. When parsing a JSON file, the dictionary class can be configured anyway.
Best,
Marcel
JSON-ct.56.mcz (35K) Download Attachment
Carpe Squeak!
|
Hi All,
Since most (every?) practical use of #respondsTo: is to check whether it's safe to send the message or not, I think, contrary to what was mentioned in this thread, that #respondsTo: does not have to return true when sending the message would not result in an MNU. So, I suggest adding the following implementation to expose the dynamic nature of JsonObject: JsonObject >> #respondsTo: aSymbol | precedence | (super respondsTo: aSymbol) ifTrue: [ ^true ]. (precedence := aSymbol precedence) = 1 ifTrue: [ ^self includesKey: aSymbol ]. (precedence = 3 and: [ (aSymbol indexOf: $:) = aSymbol size ]) ifTrue: [ ^self includesKey: aSymbol allButLast ]. ^false Levente On Sun, 22 Nov 2020, Thiede, Christoph wrote: > (Depending on how this discussion will end, this reparented mcz file might be relevant to prevent further merging issues.) > > _________________________________________________________________________________________________________________________________________________________________________________________________________________________________ > Von: Thiede, Christoph > Gesendet: Montag, 16. November 2020 16:22:01 > An: squeak-dev > Betreff: AW: [squeak-dev] I'd like to contribute to the JSON project > > Hi Marcel, > > > so do you propose to remove the existing implementation of dynamic forwarding from JsonObject, too (or more precisely, pull it down into DynamicJsonObject)? If yes, I would worry about compatibility problems. If no, I do not > quite understand why one should override #doesNotUnderstand: but not #respondsTo: in a class. It seems a reasonable pattern for me to override them only together. :-) > > > Best, > > Christoph > > _________________________________________________________________________________________________________________________________________________________________________________________________________________________________ > Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel > Gesendet: Donnerstag, 12. November 2020 10:07:28 > An: squeak-dev > Betreff: Re: [squeak-dev] I'd like to contribute to the JSON project > Hi all. > I am in favor of adding JsonDynamicObject (or similar) which has those extra features. I would avoid putting that stuff into JsonObject. When parsing a JSON file, the dictionary class can be configured anyway. > > Best, > Marcel > > Am 10.11.2020 10:16:50 schrieb Thiede, Christoph <[hidden email]>: > > Hi all, > > > > And canUnderstand: ? Or is that being too picky? > > > > If the doesNotUnderstand: is not visible externally then who cares? Isn't the contract (o respondsTo: m) ifFalse: [self should: [o m] raise: MessageNotUnderstood]], or respondsTo: not implies MNU ? > > > Well, my conception of the general contract would be exactly the following: > > (o class canUnderstand: m) ifTrue: [ > self assert: [o respondsTo: m]]. > (o respondsTo: m) ifFalse: [ > self deny: [o class canUnderstand: m]]. > (o respondsTo: m) ifTrue: [ > self shouldnt: [o m] raise: MessageNotUnderstood]. > [o m] on: MessageNotUnderstood do: [ > self deny: [o respondsTo: m]]. > > But I would *not* require the other direction of the implication - for #canUnderstand:, this is simply not possible for dynamic forwarding (unless we make false promises on the class side), and in my opinion, the > current discussion shows that the same argument applies for the second statement, too. > > > I would like to keep the JSON library as simple as possible. Wer are just talking about syntactic sugar here, right? > IMHO, this goes beyond syntactic sugar. :-) As I tried to explain below, a proper implementation of #respondsTo: could be an essential prerequisite for using JsonObjects polymorphically with first-class object > instances. In my use case, this is a crucial feature and if my proposal is discarded, I will have to subclass JsonObject ... > > Best, > Christoph > > _________________________________________________________________________________________________________________________________________________________________________________________________________________________________ > Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel > Gesendet: Dienstag, 10. November 2020 09:34:49 > An: squeak-dev > Betreff: Re: [squeak-dev] I'd like to contribute to the JSON project > > and generate the getter setter on demand (via doesNotUnderstand:) > That's what I opted for, too, in: https://github.com/hpi-swa/MessageSendRecorder 's MessageSendRecordExtension. > > Best. > Marcel > > Am 10.11.2020 09:32:07 schrieb Nicolas Cellier <[hidden email]>: > > Hi all, > for importing Matlab struct, I create classes on the fly and generate the getter setter on demand (via doesNotUnderstand:) > See MatFileReader package in http://www.squeaksource.com/STEM.html > > Le mar. 10 nov. 2020 à 09:06, Marcel Taeumel <[hidden email]> a écrit : > > And canUnderstand: ? Or is that being too picky? > Ah, right. On the class level, it would be like Levente inferred from my suggestion. I only thought of #respondsTo: to answer "true" only for the simple setter/getters that have keys present in the actual > dictionary instance. Hmmm..... > > I would like to keep the JSON library as simple as possible. Wer are just talking about syntactic sugar here, right? > > Best, > Marcel > > Am 09.11.2020 21:08:14 schrieb Eliot Miranda <[hidden email]>: > > > > On Sun, Nov 8, 2020 at 11:04 PM Marcel Taeumel <[hidden email]> wrote: > Hi Levente. > Sounds right. If an object can answer to some extra messages via #doesNotUnderstand:, one should also override #respondsTo:. It is like #= and #hash. > > > And canUnderstand: ? Or is that being too picky? > > > I did not know about #dictionaryClass:. That's a powerful hook. > > Best, > Marcel > > Am 09.11.2020 03:07:54 schrieb Levente Uzonyi <[hidden email]>: > > Hi Christoph, > > On Sun, 8 Nov 2020, Christoph Thiede wrote: > > > Hi Levente, > > > > would you mind to merge JSON-ct.41 (#respondsTo:) as well? This would be > > great because I depend on this functionality in another project and > > currently require your JSON fork in my baseline. :-) > > I cannot merge it because that would bring back long removed methods, and > MC wouldn't allow me to reject those. > But I can add the changes manually. > If I'm not mistaken, it's just a single method JsonObject >> #respondsTo:. > > What is the purpose of that method? > I'm asking because it has got no comment, so I'm not sure its > implementation is correct. > For example, should > > JsonObject new respondsTo: #foo: > > return false? > What should the following return? > > JsonObject new > foo: 1; > respondsTo: #foo: > > Another question is whether it is generally useful or not? > If it's not, you can still have the desired behavior by creating a > subclass. E.g.: > > JsonObject subclass: #PseudoObject > instanceVariableNames: '' > classVariableNames: '' > poolDictionaries: '' > category: 'PseudoObject' > > > PseudoObject >> respondsTo: aSymbol > > ^ (super respondsTo: aSymbol) > or: [self includesKey: aSymbol] > > > (Json new > dictionaryClass: PseudoObject; > readFrom: '{"foo": 42}' readStream) > respondsTo: #foo > "==> true" > > > Levente > > > > > Best, > > Christoph > > > > > > > > -- > > Sent from: http://forum.world.st/Squeak-Dev-f45488.html > > > > > -- > _,,,^..^,,,_ > best, Eliot > > > > |
> On 22. Nov 2020, at 17:46, Levente Uzonyi <[hidden email]> wrote: > > Hi All, > > Since most (every?) practical use of #respondsTo: is to check whether it's safe to send the message or not, I think, contrary to what was mentioned in this thread, that #respondsTo: does not have to return true when sending the message would not result in an MNU. > So, I suggest adding the following implementation to expose the dynamic nature of JsonObject: > > JsonObject >> #respondsTo: aSymbol > > | precedence | > (super respondsTo: aSymbol) ifTrue: [ ^true ]. > (precedence := aSymbol precedence) = 1 ifTrue: [ > ^self includesKey: aSymbol ]. > (precedence = 3 and: [ (aSymbol indexOf: $:) = aSymbol size ]) ifTrue: [ > ^self includesKey: aSymbol allButLast ]. > ^false That's nice! but why not make it simpler? JsonObject >> #respondsTo: aSymbol | precedence | (super respondsTo: aSymbol) ifTrue: [ ^true ]. aSymbol isSimpleGetter ifTrue: [^self includesKey: aSymbol]. aSymbol isSimpleSetter ifTrue: [^self includesKey: aSymbol asSimpleGetter]. ^false -Tobias > > > Levente > > On Sun, 22 Nov 2020, Thiede, Christoph wrote: > >> (Depending on how this discussion will end, this reparented mcz file might be relevant to prevent further merging issues.) >> _________________________________________________________________________________________________________________________________________________________________________________________________________________________________ >> Von: Thiede, Christoph >> Gesendet: Montag, 16. November 2020 16:22:01 >> An: squeak-dev >> Betreff: AW: [squeak-dev] I'd like to contribute to the JSON project >> Hi Marcel, >> so do you propose to remove the existing implementation of dynamic forwarding from JsonObject, too (or more precisely, pull it down into DynamicJsonObject)? If yes, I would worry about compatibility problems. If no, I do not >> quite understand why one should override #doesNotUnderstand: but not #respondsTo: in a class. It seems a reasonable pattern for me to override them only together. :-) >> Best, >> Christoph >> _________________________________________________________________________________________________________________________________________________________________________________________________________________________________ >> Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel >> Gesendet: Donnerstag, 12. November 2020 10:07:28 >> An: squeak-dev >> Betreff: Re: [squeak-dev] I'd like to contribute to the JSON project >> Hi all. >> I am in favor of adding JsonDynamicObject (or similar) which has those extra features. I would avoid putting that stuff into JsonObject. When parsing a JSON file, the dictionary class can be configured anyway. >> Best, >> Marcel >> >> Am 10.11.2020 10:16:50 schrieb Thiede, Christoph <[hidden email]>: >> >> Hi all, >> >> > And canUnderstand: ? Or is that being too picky? >> >> > If the doesNotUnderstand: is not visible externally then who cares? Isn't the contract (o respondsTo: m) ifFalse: [self should: [o m] raise: MessageNotUnderstood]], or respondsTo: not implies MNU ? >> Well, my conception of the general contract would be exactly the following: >> (o class canUnderstand: m) ifTrue: [ >> self assert: [o respondsTo: m]]. >> (o respondsTo: m) ifFalse: [ >> self deny: [o class canUnderstand: m]]. >> (o respondsTo: m) ifTrue: [ >> self shouldnt: [o m] raise: MessageNotUnderstood]. >> [o m] on: MessageNotUnderstood do: [ >> self deny: [o respondsTo: m]]. >> But I would *not* require the other direction of the implication - for #canUnderstand:, this is simply not possible for dynamic forwarding (unless we make false promises on the class side), and in my opinion, the >> current discussion shows that the same argument applies for the second statement, too. >> > I would like to keep the JSON library as simple as possible. Wer are just talking about syntactic sugar here, right? >> IMHO, this goes beyond syntactic sugar. :-) As I tried to explain below, a proper implementation of #respondsTo: could be an essential prerequisite for using JsonObjects polymorphically with first-class object >> instances. In my use case, this is a crucial feature and if my proposal is discarded, I will have to subclass JsonObject ... >> Best, >> Christoph >> _________________________________________________________________________________________________________________________________________________________________________________________________________________________________ >> Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel >> Gesendet: Dienstag, 10. November 2020 09:34:49 >> An: squeak-dev >> Betreff: Re: [squeak-dev] I'd like to contribute to the JSON project >> > and generate the getter setter on demand (via doesNotUnderstand:) >> That's what I opted for, too, in: https://github.com/hpi-swa/MessageSendRecorder 's MessageSendRecordExtension. >> Best. >> Marcel >> >> Am 10.11.2020 09:32:07 schrieb Nicolas Cellier <[hidden email]>: >> >> Hi all, >> for importing Matlab struct, I create classes on the fly and generate the getter setter on demand (via doesNotUnderstand:) >> See MatFileReader package in http://www.squeaksource.com/STEM.html >> Le mar. 10 nov. 2020 à 09:06, Marcel Taeumel <[hidden email]> a écrit : >> > And canUnderstand: ? Or is that being too picky? >> Ah, right. On the class level, it would be like Levente inferred from my suggestion. I only thought of #respondsTo: to answer "true" only for the simple setter/getters that have keys present in the actual >> dictionary instance. Hmmm..... >> I would like to keep the JSON library as simple as possible. Wer are just talking about syntactic sugar here, right? >> Best, >> Marcel >> >> Am 09.11.2020 21:08:14 schrieb Eliot Miranda <[hidden email]>: >> On Sun, Nov 8, 2020 at 11:04 PM Marcel Taeumel <[hidden email]> wrote: >> Hi Levente. >> Sounds right. If an object can answer to some extra messages via #doesNotUnderstand:, one should also override #respondsTo:. It is like #= and #hash. >> And canUnderstand: ? Or is that being too picky? >> I did not know about #dictionaryClass:. That's a powerful hook. >> Best, >> Marcel >> >> Am 09.11.2020 03:07:54 schrieb Levente Uzonyi <[hidden email]>: >> >> Hi Christoph, >> >> On Sun, 8 Nov 2020, Christoph Thiede wrote: >> >> > Hi Levente, >> > >> > would you mind to merge JSON-ct.41 (#respondsTo:) as well? This would be >> > great because I depend on this functionality in another project and >> > currently require your JSON fork in my baseline. :-) >> >> I cannot merge it because that would bring back long removed methods, and >> MC wouldn't allow me to reject those. >> But I can add the changes manually. >> If I'm not mistaken, it's just a single method JsonObject >> #respondsTo:. >> >> What is the purpose of that method? >> I'm asking because it has got no comment, so I'm not sure its >> implementation is correct. >> For example, should >> >> JsonObject new respondsTo: #foo: >> >> return false? >> What should the following return? >> >> JsonObject new >> foo: 1; >> respondsTo: #foo: >> >> Another question is whether it is generally useful or not? >> If it's not, you can still have the desired behavior by creating a >> subclass. E.g.: >> >> JsonObject subclass: #PseudoObject >> instanceVariableNames: '' >> classVariableNames: '' >> poolDictionaries: '' >> category: 'PseudoObject' >> >> PseudoObject >> respondsTo: aSymbol >> >> ^ (super respondsTo: aSymbol) >> or: [self includesKey: aSymbol] >> >> (Json new >> dictionaryClass: PseudoObject; >> readFrom: '{"foo": 42}' readStream) >> respondsTo: #foo >> "==> true" >> >> Levente >> >> > >> > Best, >> > Christoph >> > >> > >> > >> > -- >> > Sent from: http://forum.world.st/Squeak-Dev-f45488.html >> -- >> _,,,^..^,,,_ >> best, Eliot > |
+1 for Levente's implementation proposal, and +1 for Tobias's refactoring proposal (it might be a few byte steps longer, but readability first ;-)).
Best, Christoph Von: Squeak-dev <[hidden email]> im Auftrag von Tobias Pape <[hidden email]>
Gesendet: Sonntag, 22. November 2020 18:03:35 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] I'd like to contribute to the JSON project > On 22. Nov 2020, at 17:46, Levente Uzonyi <[hidden email]> wrote: > > Hi All, > > Since most (every?) practical use of #respondsTo: is to check whether it's safe to send the message or not, I think, contrary to what was mentioned in this thread, that #respondsTo: does not have to return true when sending the message would not result in an MNU. > So, I suggest adding the following implementation to expose the dynamic nature of JsonObject: > > JsonObject >> #respondsTo: aSymbol > > | precedence | > (super respondsTo: aSymbol) ifTrue: [ ^true ]. > (precedence := aSymbol precedence) = 1 ifTrue: [ > ^self includesKey: aSymbol ]. > (precedence = 3 and: [ (aSymbol indexOf: $:) = aSymbol size ]) ifTrue: [ > ^self includesKey: aSymbol allButLast ]. > ^false That's nice! but why not make it simpler? JsonObject >> #respondsTo: aSymbol | precedence | (super respondsTo: aSymbol) ifTrue: [ ^true ]. aSymbol isSimpleGetter ifTrue: [^self includesKey: aSymbol]. aSymbol isSimpleSetter ifTrue: [^self includesKey: aSymbol asSimpleGetter]. ^false -Tobias > > > Levente > > On Sun, 22 Nov 2020, Thiede, Christoph wrote: > >> (Depending on how this discussion will end, this reparented mcz file might be relevant to prevent further merging issues.) >> _________________________________________________________________________________________________________________________________________________________________________________________________________________________________ >> Von: Thiede, Christoph >> Gesendet: Montag, 16. November 2020 16:22:01 >> An: squeak-dev >> Betreff: AW: [squeak-dev] I'd like to contribute to the JSON project >> Hi Marcel, >> so do you propose to remove the existing implementation of dynamic forwarding from JsonObject, too (or more precisely, pull it down into DynamicJsonObject)? If yes, I would worry about compatibility problems. If no, I do not >> quite understand why one should override #doesNotUnderstand: but not #respondsTo: in a class. It seems a reasonable pattern for me to override them only together. :-) >> Best, >> Christoph >> _________________________________________________________________________________________________________________________________________________________________________________________________________________________________ >> Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel >> Gesendet: Donnerstag, 12. November 2020 10:07:28 >> An: squeak-dev >> Betreff: Re: [squeak-dev] I'd like to contribute to the JSON project >> Hi all. >> I am in favor of adding JsonDynamicObject (or similar) which has those extra features. I would avoid putting that stuff into JsonObject. When parsing a JSON file, the dictionary class can be configured anyway. >> Best, >> Marcel >> >> Am 10.11.2020 10:16:50 schrieb Thiede, Christoph <[hidden email]>: >> >> Hi all, >> >> > And canUnderstand: ? Or is that being too picky? >> >> > If the doesNotUnderstand: is not visible externally then who cares? Isn't the contract (o respondsTo: m) ifFalse: [self should: [o m] raise: MessageNotUnderstood]], or respondsTo: not implies MNU ? >> Well, my conception of the general contract would be exactly the following: >> (o class canUnderstand: m) ifTrue: [ >> self assert: [o respondsTo: m]]. >> (o respondsTo: m) ifFalse: [ >> self deny: [o class canUnderstand: m]]. >> (o respondsTo: m) ifTrue: [ >> self shouldnt: [o m] raise: MessageNotUnderstood]. >> [o m] on: MessageNotUnderstood do: [ >> self deny: [o respondsTo: m]]. >> But I would *not* require the other direction of the implication - for #canUnderstand:, this is simply not possible for dynamic forwarding (unless we make false promises on the class side), and in my opinion, the >> current discussion shows that the same argument applies for the second statement, too. >> > I would like to keep the JSON library as simple as possible. Wer are just talking about syntactic sugar here, right? >> IMHO, this goes beyond syntactic sugar. :-) As I tried to explain below, a proper implementation of #respondsTo: could be an essential prerequisite for using JsonObjects polymorphically with first-class object >> instances. In my use case, this is a crucial feature and if my proposal is discarded, I will have to subclass JsonObject ... >> Best, >> Christoph >> _________________________________________________________________________________________________________________________________________________________________________________________________________________________________ >> Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel >> Gesendet: Dienstag, 10. November 2020 09:34:49 >> An: squeak-dev >> Betreff: Re: [squeak-dev] I'd like to contribute to the JSON project >> > and generate the getter setter on demand (via doesNotUnderstand:) >> That's what I opted for, too, in: https://github.com/hpi-swa/MessageSendRecorder 's MessageSendRecordExtension. >> Best. >> Marcel >> >> Am 10.11.2020 09:32:07 schrieb Nicolas Cellier <[hidden email]>: >> >> Hi all, >> for importing Matlab struct, I create classes on the fly and generate the getter setter on demand (via doesNotUnderstand:) >> See MatFileReader package in http://www.squeaksource.com/STEM.html >> Le mar. 10 nov. 2020 à 09:06, Marcel Taeumel <[hidden email]> a écrit : >> > And canUnderstand: ? Or is that being too picky? >> Ah, right. On the class level, it would be like Levente inferred from my suggestion. I only thought of #respondsTo: to answer "true" only for the simple setter/getters that have keys present in the actual >> dictionary instance. Hmmm..... >> I would like to keep the JSON library as simple as possible. Wer are just talking about syntactic sugar here, right? >> Best, >> Marcel >> >> Am 09.11.2020 21:08:14 schrieb Eliot Miranda <[hidden email]>: >> On Sun, Nov 8, 2020 at 11:04 PM Marcel Taeumel <[hidden email]> wrote: >> Hi Levente. >> Sounds right. If an object can answer to some extra messages via #doesNotUnderstand:, one should also override #respondsTo:. It is like #= and #hash. >> And canUnderstand: ? Or is that being too picky? >> I did not know about #dictionaryClass:. That's a powerful hook. >> Best, >> Marcel >> >> Am 09.11.2020 03:07:54 schrieb Levente Uzonyi <[hidden email]>: >> >> Hi Christoph, >> >> On Sun, 8 Nov 2020, Christoph Thiede wrote: >> >> > Hi Levente, >> > >> > would you mind to merge JSON-ct.41 (#respondsTo:) as well? This would be >> > great because I depend on this functionality in another project and >> > currently require your JSON fork in my baseline. :-) >> >> I cannot merge it because that would bring back long removed methods, and >> MC wouldn't allow me to reject those. >> But I can add the changes manually. >> If I'm not mistaken, it's just a single method JsonObject >> #respondsTo:. >> >> What is the purpose of that method? >> I'm asking because it has got no comment, so I'm not sure its >> implementation is correct. >> For example, should >> >> JsonObject new respondsTo: #foo: >> >> return false? >> What should the following return? >> >> JsonObject new >> foo: 1; >> respondsTo: #foo: >> >> Another question is whether it is generally useful or not? >> If it's not, you can still have the desired behavior by creating a >> subclass. E.g.: >> >> JsonObject subclass: #PseudoObject >> instanceVariableNames: '' >> classVariableNames: '' >> poolDictionaries: '' >> category: 'PseudoObject' >> >> PseudoObject >> respondsTo: aSymbol >> >> ^ (super respondsTo: aSymbol) >> or: [self includesKey: aSymbol] >> >> (Json new >> dictionaryClass: PseudoObject; >> readFrom: '{"foo": 42}' readStream) >> respondsTo: #foo >> "==> true" >> >> Levente >> >> > >> > Best, >> > Christoph >> > >> > >> > >> > -- >> > Sent from: http://forum.world.st/Squeak-Dev-f45488.html >> -- >> _,,,^..^,,,_ >> best, Eliot >
Carpe Squeak!
|
In reply to this post by Tobias Pape
Hi Tobias,
On Sun, 22 Nov 2020, Tobias Pape wrote: > > >> On 22. Nov 2020, at 17:46, Levente Uzonyi <[hidden email]> wrote: >> >> Hi All, >> >> Since most (every?) practical use of #respondsTo: is to check whether it's safe to send the message or not, I think, contrary to what was mentioned in this thread, that #respondsTo: does not have to return true when sending the message would not result in an MNU. >> So, I suggest adding the following implementation to expose the dynamic nature of JsonObject: >> >> JsonObject >> #respondsTo: aSymbol >> >> | precedence | >> (super respondsTo: aSymbol) ifTrue: [ ^true ]. >> (precedence := aSymbol precedence) = 1 ifTrue: [ >> ^self includesKey: aSymbol ]. >> (precedence = 3 and: [ (aSymbol indexOf: $:) = aSymbol size ]) ifTrue: [ >> ^self includesKey: aSymbol allButLast ]. >> ^false > > That's nice! but why not make it simpler? > > JsonObject >> #respondsTo: aSymbol > > | precedence | > (super respondsTo: aSymbol) ifTrue: [ ^true ]. > aSymbol isSimpleGetter ifTrue: [^self includesKey: aSymbol]. > aSymbol isSimpleSetter ifTrue: [^self includesKey: aSymbol asSimpleGetter]. > ^false 1. performance | j s | Smalltalk garbageCollect. j := JsonObject new foo: 1; bar: 2; baz: 3; yourself. s := Symbol allSymbols. { [ s do: [ :each | ] ] bench. [ s do: [ :each | j respondsTo: each ] ] bench. [ s do: [ :each | j respondsTo2: each ] ] bench. "Your suggested implementation" } #( '1,630 per second. 613 microseconds per run. 0 % GC time.' '19 per second. 52.7 milliseconds per run. 0.09992 % GC time.' '1.18 per second. 850 milliseconds per run. 32.81709 % GC time.' ) Okay, that may not be too a realistic workload. The reason of the extreme slowdown and high GC time is rapid interning and GCing of Symbols created by #asSimpleGetter. If you change s to a handcrafted array that avoids Symbol creation, like s := #(yourself foo foo: bar bar: baz baz: foobar foobar: name name:) the numbers get better but still not as good as my suggestion: #( '4,970,000 per second. 201 nanoseconds per run. 38.02 % GC time.' '147,000 per second. 6.82 microseconds per run. 1.74 % GC time.' '92,300 per second. 10.8 microseconds per run. 1.09978 % GC time.') 2. backwards compatibility #isSimpleSetter and #isSimpleGetter are available since Squeak 5.3. I use this code in 5.1 and 5.2 images as well. 3. to use the same mechanism as #doesNotUnderstand: Have a look at that method. Levente > > -Tobias > >> >> >> Levente >> >> On Sun, 22 Nov 2020, Thiede, Christoph wrote: >> >>> (Depending on how this discussion will end, this reparented mcz file might be relevant to prevent further merging issues.) >>> _________________________________________________________________________________________________________________________________________________________________________________________________________________________________ >>> Von: Thiede, Christoph >>> Gesendet: Montag, 16. November 2020 16:22:01 >>> An: squeak-dev >>> Betreff: AW: [squeak-dev] I'd like to contribute to the JSON project >>> Hi Marcel, >>> so do you propose to remove the existing implementation of dynamic forwarding from JsonObject, too (or more precisely, pull it down into DynamicJsonObject)? If yes, I would worry about compatibility problems. If no, I do not >>> quite understand why one should override #doesNotUnderstand: but not #respondsTo: in a class. It seems a reasonable pattern for me to override them only together. :-) >>> Best, >>> Christoph >>> _________________________________________________________________________________________________________________________________________________________________________________________________________________________________ >>> Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel >>> Gesendet: Donnerstag, 12. November 2020 10:07:28 >>> An: squeak-dev >>> Betreff: Re: [squeak-dev] I'd like to contribute to the JSON project >>> Hi all. >>> I am in favor of adding JsonDynamicObject (or similar) which has those extra features. I would avoid putting that stuff into JsonObject. When parsing a JSON file, the dictionary class can be configured anyway. >>> Best, >>> Marcel >>> >>> Am 10.11.2020 10:16:50 schrieb Thiede, Christoph <[hidden email]>: >>> >>> Hi all, >>> >>> > And canUnderstand: ? Or is that being too picky? >>> >>> > If the doesNotUnderstand: is not visible externally then who cares? Isn't the contract (o respondsTo: m) ifFalse: [self should: [o m] raise: MessageNotUnderstood]], or respondsTo: not implies MNU ? >>> Well, my conception of the general contract would be exactly the following: >>> (o class canUnderstand: m) ifTrue: [ >>> self assert: [o respondsTo: m]]. >>> (o respondsTo: m) ifFalse: [ >>> self deny: [o class canUnderstand: m]]. >>> (o respondsTo: m) ifTrue: [ >>> self shouldnt: [o m] raise: MessageNotUnderstood]. >>> [o m] on: MessageNotUnderstood do: [ >>> self deny: [o respondsTo: m]]. >>> But I would *not* require the other direction of the implication - for #canUnderstand:, this is simply not possible for dynamic forwarding (unless we make false promises on the class side), and in my opinion, the >>> current discussion shows that the same argument applies for the second statement, too. >>> > I would like to keep the JSON library as simple as possible. Wer are just talking about syntactic sugar here, right? >>> IMHO, this goes beyond syntactic sugar. :-) As I tried to explain below, a proper implementation of #respondsTo: could be an essential prerequisite for using JsonObjects polymorphically with first-class object >>> instances. In my use case, this is a crucial feature and if my proposal is discarded, I will have to subclass JsonObject ... >>> Best, >>> Christoph >>> _________________________________________________________________________________________________________________________________________________________________________________________________________________________________ >>> Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel >>> Gesendet: Dienstag, 10. November 2020 09:34:49 >>> An: squeak-dev >>> Betreff: Re: [squeak-dev] I'd like to contribute to the JSON project >>> > and generate the getter setter on demand (via doesNotUnderstand:) >>> That's what I opted for, too, in: https://github.com/hpi-swa/MessageSendRecorder 's MessageSendRecordExtension. >>> Best. >>> Marcel >>> >>> Am 10.11.2020 09:32:07 schrieb Nicolas Cellier <[hidden email]>: >>> >>> Hi all, >>> for importing Matlab struct, I create classes on the fly and generate the getter setter on demand (via doesNotUnderstand:) >>> See MatFileReader package in http://www.squeaksource.com/STEM.html >>> Le mar. 10 nov. 2020 à 09:06, Marcel Taeumel <[hidden email]> a écrit : >>> > And canUnderstand: ? Or is that being too picky? >>> Ah, right. On the class level, it would be like Levente inferred from my suggestion. I only thought of #respondsTo: to answer "true" only for the simple setter/getters that have keys present in the actual >>> dictionary instance. Hmmm..... >>> I would like to keep the JSON library as simple as possible. Wer are just talking about syntactic sugar here, right? >>> Best, >>> Marcel >>> >>> Am 09.11.2020 21:08:14 schrieb Eliot Miranda <[hidden email]>: >>> On Sun, Nov 8, 2020 at 11:04 PM Marcel Taeumel <[hidden email]> wrote: >>> Hi Levente. >>> Sounds right. If an object can answer to some extra messages via #doesNotUnderstand:, one should also override #respondsTo:. It is like #= and #hash. >>> And canUnderstand: ? Or is that being too picky? >>> I did not know about #dictionaryClass:. That's a powerful hook. >>> Best, >>> Marcel >>> >>> Am 09.11.2020 03:07:54 schrieb Levente Uzonyi <[hidden email]>: >>> >>> Hi Christoph, >>> >>> On Sun, 8 Nov 2020, Christoph Thiede wrote: >>> >>> > Hi Levente, >>> > >>> > would you mind to merge JSON-ct.41 (#respondsTo:) as well? This would be >>> > great because I depend on this functionality in another project and >>> > currently require your JSON fork in my baseline. :-) >>> >>> I cannot merge it because that would bring back long removed methods, and >>> MC wouldn't allow me to reject those. >>> But I can add the changes manually. >>> If I'm not mistaken, it's just a single method JsonObject >> #respondsTo:. >>> >>> What is the purpose of that method? >>> I'm asking because it has got no comment, so I'm not sure its >>> implementation is correct. >>> For example, should >>> >>> JsonObject new respondsTo: #foo: >>> >>> return false? >>> What should the following return? >>> >>> JsonObject new >>> foo: 1; >>> respondsTo: #foo: >>> >>> Another question is whether it is generally useful or not? >>> If it's not, you can still have the desired behavior by creating a >>> subclass. E.g.: >>> >>> JsonObject subclass: #PseudoObject >>> instanceVariableNames: '' >>> classVariableNames: '' >>> poolDictionaries: '' >>> category: 'PseudoObject' >>> >>> PseudoObject >> respondsTo: aSymbol >>> >>> ^ (super respondsTo: aSymbol) >>> or: [self includesKey: aSymbol] >>> >>> (Json new >>> dictionaryClass: PseudoObject; >>> readFrom: '{"foo": 42}' readStream) >>> respondsTo: #foo >>> "==> true" >>> >>> Levente >>> >>> > >>> > Best, >>> > Christoph >>> > >>> > >>> > >>> > -- >>> > Sent from: http://forum.world.st/Squeak-Dev-f45488.html >>> -- >>> _,,,^..^,,,_ >>> best, Eliot >> |
> On 22. Nov 2020, at 18:51, Levente Uzonyi <[hidden email]> wrote: > > Hi Tobias, > > On Sun, 22 Nov 2020, Tobias Pape wrote: > >> >> >>> On 22. Nov 2020, at 17:46, Levente Uzonyi <[hidden email]> wrote: >>> Hi All, >>> Since most (every?) practical use of #respondsTo: is to check whether it's safe to send the message or not, I think, contrary to what was mentioned in this thread, that #respondsTo: does not have to return true when sending the message would not result in an MNU. >>> So, I suggest adding the following implementation to expose the dynamic nature of JsonObject: >>> JsonObject >> #respondsTo: aSymbol >>> >>> | precedence | >>> (super respondsTo: aSymbol) ifTrue: [ ^true ]. >>> (precedence := aSymbol precedence) = 1 ifTrue: [ >>> ^self includesKey: aSymbol ]. >>> (precedence = 3 and: [ (aSymbol indexOf: $:) = aSymbol size ]) ifTrue: [ >>> ^self includesKey: aSymbol allButLast ]. >>> ^false >> >> That's nice! but why not make it simpler? >> >> JsonObject >> #respondsTo: aSymbol >> >> | precedence | >> (super respondsTo: aSymbol) ifTrue: [ ^true ]. >> aSymbol isSimpleGetter ifTrue: [^self includesKey: aSymbol]. >> aSymbol isSimpleSetter ifTrue: [^self includesKey: aSymbol asSimpleGetter]. >> ^false > > Three reasons: > > 1. performance > > | j s | > Smalltalk garbageCollect. > j := JsonObject new > foo: 1; > bar: 2; > baz: 3; > yourself. > s := Symbol allSymbols. > { > [ s do: [ :each | ] ] bench. > [ s do: [ :each | j respondsTo: each ] ] bench. > [ s do: [ :each | j respondsTo2: each ] ] bench. "Your suggested implementation" > } > #( > '1,630 per second. 613 microseconds per run. 0 % GC time.' > '19 per second. 52.7 milliseconds per run. 0.09992 % GC time.' > '1.18 per second. 850 milliseconds per run. 32.81709 % GC time.' > ) > > Okay, that may not be too a realistic workload. The reason of the extreme > slowdown and high GC time is rapid interning and GCing of Symbols > created by #asSimpleGetter. > > If you change s to a handcrafted array that avoids Symbol creation, like > > s := #(yourself foo foo: bar bar: baz baz: foobar foobar: name name:) > > the numbers get better but still not as good as my suggestion: > > #( > '4,970,000 per second. 201 nanoseconds per run. 38.02 % GC time.' > '147,000 per second. 6.82 microseconds per run. 1.74 % GC time.' > '92,300 per second. 10.8 microseconds per run. 1.09978 % GC time.') > > I thought you'd say that. But "precedence" is one of the most obscure things around that part in the image. > 2. backwards compatibility > #isSimpleSetter and #isSimpleGetter are available since Squeak 5.3. I use this code in 5.1 and 5.2 images as well. Yea, Pre 5.3 I'd have said #asMutator. > > > 3. to use the same mechanism as #doesNotUnderstand: > Have a look at that method. Then I'd rather say change DNU too. If you're down that hole (dnu/respondsTo) anyways, I don't buy the performance argument anymore. Not everything has to be as fast as possible. Best regards -Tobias > > > Levente > >> >> -Tobias >> >>> Levente >>> On Sun, 22 Nov 2020, Thiede, Christoph wrote: >>>> (Depending on how this discussion will end, this reparented mcz file might be relevant to prevent further merging issues.) >>>> _________________________________________________________________________________________________________________________________________________________________________________________________________________________________ >>>> Von: Thiede, Christoph >>>> Gesendet: Montag, 16. November 2020 16:22:01 >>>> An: squeak-dev >>>> Betreff: AW: [squeak-dev] I'd like to contribute to the JSON project Hi Marcel, >>>> so do you propose to remove the existing implementation of dynamic forwarding from JsonObject, too (or more precisely, pull it down into DynamicJsonObject)? If yes, I would worry about compatibility problems. If no, I do not >>>> quite understand why one should override #doesNotUnderstand: but not #respondsTo: in a class. It seems a reasonable pattern for me to override them only together. :-) >>>> Best, >>>> Christoph >>>> _________________________________________________________________________________________________________________________________________________________________________________________________________________________________ >>>> Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel >>>> Gesendet: Donnerstag, 12. November 2020 10:07:28 >>>> An: squeak-dev >>>> Betreff: Re: [squeak-dev] I'd like to contribute to the JSON project Hi all. >>>> I am in favor of adding JsonDynamicObject (or similar) which has those extra features. I would avoid putting that stuff into JsonObject. When parsing a JSON file, the dictionary class can be configured anyway. >>>> Best, >>>> Marcel >>>> >>>> Am 10.11.2020 10:16:50 schrieb Thiede, Christoph <[hidden email]>: >>>> >>>> Hi all, >>>> >>>> > And canUnderstand: ? Or is that being too picky? >>>> >>>> > If the doesNotUnderstand: is not visible externally then who cares? Isn't the contract (o respondsTo: m) ifFalse: [self should: [o m] raise: MessageNotUnderstood]], or respondsTo: not implies MNU ? >>>> Well, my conception of the general contract would be exactly the following: >>>> (o class canUnderstand: m) ifTrue: [ >>>> self assert: [o respondsTo: m]]. >>>> (o respondsTo: m) ifFalse: [ >>>> self deny: [o class canUnderstand: m]]. >>>> (o respondsTo: m) ifTrue: [ >>>> self shouldnt: [o m] raise: MessageNotUnderstood]. >>>> [o m] on: MessageNotUnderstood do: [ >>>> self deny: [o respondsTo: m]]. >>>> But I would *not* require the other direction of the implication - for #canUnderstand:, this is simply not possible for dynamic forwarding (unless we make false promises on the class side), and in my opinion, the >>>> current discussion shows that the same argument applies for the second statement, too. >>>> > I would like to keep the JSON library as simple as possible. Wer are just talking about syntactic sugar here, right? >>>> IMHO, this goes beyond syntactic sugar. :-) As I tried to explain below, a proper implementation of #respondsTo: could be an essential prerequisite for using JsonObjects polymorphically with first-class object >>>> instances. In my use case, this is a crucial feature and if my proposal is discarded, I will have to subclass JsonObject ... >>>> Best, >>>> Christoph >>>> _________________________________________________________________________________________________________________________________________________________________________________________________________________________________ >>>> Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel >>>> Gesendet: Dienstag, 10. November 2020 09:34:49 >>>> An: squeak-dev >>>> Betreff: Re: [squeak-dev] I'd like to contribute to the JSON project > and generate the getter setter on demand (via doesNotUnderstand:) >>>> That's what I opted for, too, in: https://github.com/hpi-swa/MessageSendRecorder 's MessageSendRecordExtension. >>>> Best. >>>> Marcel >>>> >>>> Am 10.11.2020 09:32:07 schrieb Nicolas Cellier <[hidden email]>: >>>> >>>> Hi all, >>>> for importing Matlab struct, I create classes on the fly and generate the getter setter on demand (via doesNotUnderstand:) >>>> See MatFileReader package in http://www.squeaksource.com/STEM.html >>>> Le mar. 10 nov. 2020 à 09:06, Marcel Taeumel <[hidden email]> a écrit : >>>> > And canUnderstand: ? Or is that being too picky? >>>> Ah, right. On the class level, it would be like Levente inferred from my suggestion. I only thought of #respondsTo: to answer "true" only for the simple setter/getters that have keys present in the actual >>>> dictionary instance. Hmmm..... >>>> I would like to keep the JSON library as simple as possible. Wer are just talking about syntactic sugar here, right? >>>> Best, >>>> Marcel >>>> >>>> Am 09.11.2020 21:08:14 schrieb Eliot Miranda <[hidden email]>: >>>> On Sun, Nov 8, 2020 at 11:04 PM Marcel Taeumel <[hidden email]> wrote: >>>> Hi Levente. >>>> Sounds right. If an object can answer to some extra messages via #doesNotUnderstand:, one should also override #respondsTo:. It is like #= and #hash. >>>> And canUnderstand: ? Or is that being too picky? >>>> I did not know about #dictionaryClass:. That's a powerful hook. >>>> Best, >>>> Marcel >>>> >>>> Am 09.11.2020 03:07:54 schrieb Levente Uzonyi <[hidden email]>: >>>> >>>> Hi Christoph, >>>> >>>> On Sun, 8 Nov 2020, Christoph Thiede wrote: >>>> >>>> > Hi Levente, >>>> > >>>> > would you mind to merge JSON-ct.41 (#respondsTo:) as well? This would be >>>> > great because I depend on this functionality in another project and >>>> > currently require your JSON fork in my baseline. :-) >>>> >>>> I cannot merge it because that would bring back long removed methods, and >>>> MC wouldn't allow me to reject those. >>>> But I can add the changes manually. >>>> If I'm not mistaken, it's just a single method JsonObject >> #respondsTo:. >>>> >>>> What is the purpose of that method? >>>> I'm asking because it has got no comment, so I'm not sure its >>>> implementation is correct. >>>> For example, should >>>> >>>> JsonObject new respondsTo: #foo: >>>> >>>> return false? >>>> What should the following return? >>>> >>>> JsonObject new >>>> foo: 1; >>>> respondsTo: #foo: >>>> >>>> Another question is whether it is generally useful or not? >>>> If it's not, you can still have the desired behavior by creating a >>>> subclass. E.g.: >>>> >>>> JsonObject subclass: #PseudoObject >>>> instanceVariableNames: '' >>>> classVariableNames: '' >>>> poolDictionaries: '' >>>> category: 'PseudoObject' >>>> >>>> PseudoObject >> respondsTo: aSymbol >>>> >>>> ^ (super respondsTo: aSymbol) >>>> or: [self includesKey: aSymbol] >>>> >>>> (Json new >>>> dictionaryClass: PseudoObject; >>>> readFrom: '{"foo": 42}' readStream) >>>> respondsTo: #foo >>>> "==> true" >>>> >>>> Levente >>>> >>>> > >>>> > Best, >>>> > Christoph >>>> > >>>> > >>>> > >>>> > -- >>>> > Sent from: http://forum.world.st/Squeak-Dev-f45488.html >>>> -- >>>> _,,,^..^,,,_ >>>> best, Eliot |
Hi Tobias,
On Sun, 22 Nov 2020, Tobias Pape wrote: > > >> On 22. Nov 2020, at 18:51, Levente Uzonyi <[hidden email]> wrote: >> >> Hi Tobias, >> >> On Sun, 22 Nov 2020, Tobias Pape wrote: >> >>> >>> >>>> On 22. Nov 2020, at 17:46, Levente Uzonyi <[hidden email]> wrote: >>>> Hi All, >>>> Since most (every?) practical use of #respondsTo: is to check whether it's safe to send the message or not, I think, contrary to what was mentioned in this thread, that #respondsTo: does not have to return true when sending the message would not result in an MNU. >>>> So, I suggest adding the following implementation to expose the dynamic nature of JsonObject: >>>> JsonObject >> #respondsTo: aSymbol >>>> >>>> | precedence | >>>> (super respondsTo: aSymbol) ifTrue: [ ^true ]. >>>> (precedence := aSymbol precedence) = 1 ifTrue: [ >>>> ^self includesKey: aSymbol ]. >>>> (precedence = 3 and: [ (aSymbol indexOf: $:) = aSymbol size ]) ifTrue: [ >>>> ^self includesKey: aSymbol allButLast ]. >>>> ^false >>> >>> That's nice! but why not make it simpler? >>> >>> JsonObject >> #respondsTo: aSymbol >>> >>> | precedence | >>> (super respondsTo: aSymbol) ifTrue: [ ^true ]. >>> aSymbol isSimpleGetter ifTrue: [^self includesKey: aSymbol]. >>> aSymbol isSimpleSetter ifTrue: [^self includesKey: aSymbol asSimpleGetter]. >>> ^false >> >> Three reasons: >> >> 1. performance >> >> | j s | >> Smalltalk garbageCollect. >> j := JsonObject new >> foo: 1; >> bar: 2; >> baz: 3; >> yourself. >> s := Symbol allSymbols. >> { >> [ s do: [ :each | ] ] bench. >> [ s do: [ :each | j respondsTo: each ] ] bench. >> [ s do: [ :each | j respondsTo2: each ] ] bench. "Your suggested implementation" >> } >> #( >> '1,630 per second. 613 microseconds per run. 0 % GC time.' >> '19 per second. 52.7 milliseconds per run. 0.09992 % GC time.' >> '1.18 per second. 850 milliseconds per run. 32.81709 % GC time.' >> ) >> >> Okay, that may not be too a realistic workload. The reason of the extreme >> slowdown and high GC time is rapid interning and GCing of Symbols >> created by #asSimpleGetter. >> >> If you change s to a handcrafted array that avoids Symbol creation, like >> >> s := #(yourself foo foo: bar bar: baz baz: foobar foobar: name name:) >> >> the numbers get better but still not as good as my suggestion: >> >> #( >> '4,970,000 per second. 201 nanoseconds per run. 38.02 % GC time.' >> '147,000 per second. 6.82 microseconds per run. 1.74 % GC time.' >> '92,300 per second. 10.8 microseconds per run. 1.09978 % GC time.') >> >> > > I thought you'd say that. > But "precedence" is one of the most obscure things around that part in the image. > > >> 2. backwards compatibility >> #isSimpleSetter and #isSimpleGetter are available since Squeak 5.3. I use this code in 5.1 and 5.2 images as well. > > Yea, Pre 5.3 I'd have said #asMutator. > >> >> >> 3. to use the same mechanism as #doesNotUnderstand: >> Have a look at that method. > > > Then I'd rather say change DNU too. > If you're down that hole (dnu/respondsTo) anyways, I don't buy the performance argument anymore. > > Not everything has to be as fast as possible. of JsonObject. I assume you don't use the JSON package in production images, hence you don't care about performance. I do, so I'm not willing to change the implementation of #doesNotUnderstand: in my fork of the JSON package unless performance is at least as good as it is now. Levente > > Best regards > -Tobias > >> >> >> Levente >> >>> >>> -Tobias >>> >>>> Levente >>>> On Sun, 22 Nov 2020, Thiede, Christoph wrote: >>>>> (Depending on how this discussion will end, this reparented mcz file might be relevant to prevent further merging issues.) >>>>> _________________________________________________________________________________________________________________________________________________________________________________________________________________________________ >>>>> Von: Thiede, Christoph >>>>> Gesendet: Montag, 16. November 2020 16:22:01 >>>>> An: squeak-dev >>>>> Betreff: AW: [squeak-dev] I'd like to contribute to the JSON project Hi Marcel, >>>>> so do you propose to remove the existing implementation of dynamic forwarding from JsonObject, too (or more precisely, pull it down into DynamicJsonObject)? If yes, I would worry about compatibility problems. If no, I do not >>>>> quite understand why one should override #doesNotUnderstand: but not #respondsTo: in a class. It seems a reasonable pattern for me to override them only together. :-) >>>>> Best, >>>>> Christoph >>>>> _________________________________________________________________________________________________________________________________________________________________________________________________________________________________ >>>>> Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel >>>>> Gesendet: Donnerstag, 12. November 2020 10:07:28 >>>>> An: squeak-dev >>>>> Betreff: Re: [squeak-dev] I'd like to contribute to the JSON project Hi all. >>>>> I am in favor of adding JsonDynamicObject (or similar) which has those extra features. I would avoid putting that stuff into JsonObject. When parsing a JSON file, the dictionary class can be configured anyway. >>>>> Best, >>>>> Marcel >>>>> >>>>> Am 10.11.2020 10:16:50 schrieb Thiede, Christoph <[hidden email]>: >>>>> >>>>> Hi all, >>>>> >>>>> > And canUnderstand: ? Or is that being too picky? >>>>> >>>>> > If the doesNotUnderstand: is not visible externally then who cares? Isn't the contract (o respondsTo: m) ifFalse: [self should: [o m] raise: MessageNotUnderstood]], or respondsTo: not implies MNU ? >>>>> Well, my conception of the general contract would be exactly the following: >>>>> (o class canUnderstand: m) ifTrue: [ >>>>> self assert: [o respondsTo: m]]. >>>>> (o respondsTo: m) ifFalse: [ >>>>> self deny: [o class canUnderstand: m]]. >>>>> (o respondsTo: m) ifTrue: [ >>>>> self shouldnt: [o m] raise: MessageNotUnderstood]. >>>>> [o m] on: MessageNotUnderstood do: [ >>>>> self deny: [o respondsTo: m]]. >>>>> But I would *not* require the other direction of the implication - for #canUnderstand:, this is simply not possible for dynamic forwarding (unless we make false promises on the class side), and in my opinion, the >>>>> current discussion shows that the same argument applies for the second statement, too. >>>>> > I would like to keep the JSON library as simple as possible. Wer are just talking about syntactic sugar here, right? >>>>> IMHO, this goes beyond syntactic sugar. :-) As I tried to explain below, a proper implementation of #respondsTo: could be an essential prerequisite for using JsonObjects polymorphically with first-class object >>>>> instances. In my use case, this is a crucial feature and if my proposal is discarded, I will have to subclass JsonObject ... >>>>> Best, >>>>> Christoph >>>>> _________________________________________________________________________________________________________________________________________________________________________________________________________________________________ >>>>> Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel >>>>> Gesendet: Dienstag, 10. November 2020 09:34:49 >>>>> An: squeak-dev >>>>> Betreff: Re: [squeak-dev] I'd like to contribute to the JSON project > and generate the getter setter on demand (via doesNotUnderstand:) >>>>> That's what I opted for, too, in: https://github.com/hpi-swa/MessageSendRecorder 's MessageSendRecordExtension. >>>>> Best. >>>>> Marcel >>>>> >>>>> Am 10.11.2020 09:32:07 schrieb Nicolas Cellier <[hidden email]>: >>>>> >>>>> Hi all, >>>>> for importing Matlab struct, I create classes on the fly and generate the getter setter on demand (via doesNotUnderstand:) >>>>> See MatFileReader package in http://www.squeaksource.com/STEM.html >>>>> Le mar. 10 nov. 2020 à 09:06, Marcel Taeumel <[hidden email]> a écrit : >>>>> > And canUnderstand: ? Or is that being too picky? >>>>> Ah, right. On the class level, it would be like Levente inferred from my suggestion. I only thought of #respondsTo: to answer "true" only for the simple setter/getters that have keys present in the actual >>>>> dictionary instance. Hmmm..... >>>>> I would like to keep the JSON library as simple as possible. Wer are just talking about syntactic sugar here, right? >>>>> Best, >>>>> Marcel >>>>> >>>>> Am 09.11.2020 21:08:14 schrieb Eliot Miranda <[hidden email]>: >>>>> On Sun, Nov 8, 2020 at 11:04 PM Marcel Taeumel <[hidden email]> wrote: >>>>> Hi Levente. >>>>> Sounds right. If an object can answer to some extra messages via #doesNotUnderstand:, one should also override #respondsTo:. It is like #= and #hash. >>>>> And canUnderstand: ? Or is that being too picky? >>>>> I did not know about #dictionaryClass:. That's a powerful hook. >>>>> Best, >>>>> Marcel >>>>> >>>>> Am 09.11.2020 03:07:54 schrieb Levente Uzonyi <[hidden email]>: >>>>> >>>>> Hi Christoph, >>>>> >>>>> On Sun, 8 Nov 2020, Christoph Thiede wrote: >>>>> >>>>> > Hi Levente, >>>>> > >>>>> > would you mind to merge JSON-ct.41 (#respondsTo:) as well? This would be >>>>> > great because I depend on this functionality in another project and >>>>> > currently require your JSON fork in my baseline. :-) >>>>> >>>>> I cannot merge it because that would bring back long removed methods, and >>>>> MC wouldn't allow me to reject those. >>>>> But I can add the changes manually. >>>>> If I'm not mistaken, it's just a single method JsonObject >> #respondsTo:. >>>>> >>>>> What is the purpose of that method? >>>>> I'm asking because it has got no comment, so I'm not sure its >>>>> implementation is correct. >>>>> For example, should >>>>> >>>>> JsonObject new respondsTo: #foo: >>>>> >>>>> return false? >>>>> What should the following return? >>>>> >>>>> JsonObject new >>>>> foo: 1; >>>>> respondsTo: #foo: >>>>> >>>>> Another question is whether it is generally useful or not? >>>>> If it's not, you can still have the desired behavior by creating a >>>>> subclass. E.g.: >>>>> >>>>> JsonObject subclass: #PseudoObject >>>>> instanceVariableNames: '' >>>>> classVariableNames: '' >>>>> poolDictionaries: '' >>>>> category: 'PseudoObject' >>>>> >>>>> PseudoObject >> respondsTo: aSymbol >>>>> >>>>> ^ (super respondsTo: aSymbol) >>>>> or: [self includesKey: aSymbol] >>>>> >>>>> (Json new >>>>> dictionaryClass: PseudoObject; >>>>> readFrom: '{"foo": 42}' readStream) >>>>> respondsTo: #foo >>>>> "==> true" >>>>> >>>>> Levente >>>>> >>>>> > >>>>> > Best, >>>>> > Christoph >>>>> > >>>>> > >>>>> > >>>>> > -- >>>>> > Sent from: http://forum.world.st/Squeak-Dev-f45488.html >>>>> -- >>>>> _,,,^..^,,,_ >>>>> best, Eliot |
> On 22. Nov 2020, at 19:37, Levente Uzonyi <[hidden email]> wrote: > > Hi Tobias, > > On Sun, 22 Nov 2020, Tobias Pape wrote: > >> >> >>> On 22. Nov 2020, at 18:51, Levente Uzonyi <[hidden email]> wrote: >>> Hi Tobias, >>> On Sun, 22 Nov 2020, Tobias Pape wrote: >>>>> On 22. Nov 2020, at 17:46, Levente Uzonyi <[hidden email]> wrote: >>>>> Hi All, >>>>> Since most (every?) practical use of #respondsTo: is to check whether it's safe to send the message or not, I think, contrary to what was mentioned in this thread, that #respondsTo: does not have to return true when sending the message would not result in an MNU. >>>>> So, I suggest adding the following implementation to expose the dynamic nature of JsonObject: >>>>> JsonObject >> #respondsTo: aSymbol >>>>> >>>>> | precedence | >>>>> (super respondsTo: aSymbol) ifTrue: [ ^true ]. >>>>> (precedence := aSymbol precedence) = 1 ifTrue: [ >>>>> ^self includesKey: aSymbol ]. >>>>> (precedence = 3 and: [ (aSymbol indexOf: $:) = aSymbol size ]) ifTrue: [ >>>>> ^self includesKey: aSymbol allButLast ]. >>>>> ^false >>>> That's nice! but why not make it simpler? >>>> JsonObject >> #respondsTo: aSymbol >>>> >>>> | precedence | >>>> (super respondsTo: aSymbol) ifTrue: [ ^true ]. >>>> aSymbol isSimpleGetter ifTrue: [^self includesKey: aSymbol]. >>>> aSymbol isSimpleSetter ifTrue: [^self includesKey: aSymbol asSimpleGetter]. >>>> ^false >>> Three reasons: >>> 1. performance >>> | j s | >>> Smalltalk garbageCollect. >>> j := JsonObject new >>> foo: 1; >>> bar: 2; >>> baz: 3; >>> yourself. >>> s := Symbol allSymbols. >>> { >>> [ s do: [ :each | ] ] bench. >>> [ s do: [ :each | j respondsTo: each ] ] bench. >>> [ s do: [ :each | j respondsTo2: each ] ] bench. "Your suggested implementation" >>> } >>> #( >>> '1,630 per second. 613 microseconds per run. 0 % GC time.' >>> '19 per second. 52.7 milliseconds per run. 0.09992 % GC time.' >>> '1.18 per second. 850 milliseconds per run. 32.81709 % GC time.' >>> ) >>> Okay, that may not be too a realistic workload. The reason of the extreme >>> slowdown and high GC time is rapid interning and GCing of Symbols >>> created by #asSimpleGetter. >>> If you change s to a handcrafted array that avoids Symbol creation, like >>> s := #(yourself foo foo: bar bar: baz baz: foobar foobar: name name:) >>> the numbers get better but still not as good as my suggestion: >>> #( >>> '4,970,000 per second. 201 nanoseconds per run. 38.02 % GC time.' >>> '147,000 per second. 6.82 microseconds per run. 1.74 % GC time.' >>> '92,300 per second. 10.8 microseconds per run. 1.09978 % GC time.') >> >> I thought you'd say that. >> But "precedence" is one of the most obscure things around that part in the image. >> >> >>> 2. backwards compatibility >>> #isSimpleSetter and #isSimpleGetter are available since Squeak 5.3. I use this code in 5.1 and 5.2 images as well. >> >> Yea, Pre 5.3 I'd have said #asMutator. >> >>> 3. to use the same mechanism as #doesNotUnderstand: >>> Have a look at that method. >> >> >> Then I'd rather say change DNU too. >> If you're down that hole (dnu/respondsTo) anyways, I don't buy the performance argument anymore. >> >> Not everything has to be as fast as possible. > > You seem to ignore that #doesNotUnderstand: is the most often used method of JsonObject. > I assume you don't use the JSON package in production images, hence you don't care about performance. I do. It never has been the bottleneck. > I do, so I'm not willing to change the implementation of #doesNotUnderstand: in my fork of the JSON package unless performance is at least as good as it is now. I just want the image to remain tractable. Performance is nice. But if you rely on performance with the JSOn stuff, subclass the JsonObject and implement your keys as messages? That ought to be the fastest way, no? I though it was meant to be that way. That said, I rarely remain in the JSON space for longer than necessary; I'd rather have proper objects and only convert on "the edges" I'm not against fast things. I'm merely a bit startled by fast things that are harder to understand than necessary… Best regards -Tobias PS: Levente, your code is almost always the fastest variant of anything we discuss on here. That's amazing in itself. Don't get the impression I'm not amazed by that ;) > > > Levente > >> >> Best regards >> -Tobias >> >>> Levente >>>> -Tobias >>>>> Levente >>>>> On Sun, 22 Nov 2020, Thiede, Christoph wrote: |
On Sun, 22 Nov 2020, Tobias Pape wrote:
> > >> On 22. Nov 2020, at 19:37, Levente Uzonyi <[hidden email]> wrote: >> >> Hi Tobias, >> >> On Sun, 22 Nov 2020, Tobias Pape wrote: >> >>> >>> >>>> On 22. Nov 2020, at 18:51, Levente Uzonyi <[hidden email]> wrote: >>>> Hi Tobias, >>>> On Sun, 22 Nov 2020, Tobias Pape wrote: >>>>>> On 22. Nov 2020, at 17:46, Levente Uzonyi <[hidden email]> wrote: >>>>>> Hi All, >>>>>> Since most (every?) practical use of #respondsTo: is to check whether it's safe to send the message or not, I think, contrary to what was mentioned in this thread, that #respondsTo: does not have to return true when sending the message would not result in an MNU. >>>>>> So, I suggest adding the following implementation to expose the dynamic nature of JsonObject: >>>>>> JsonObject >> #respondsTo: aSymbol >>>>>> >>>>>> | precedence | >>>>>> (super respondsTo: aSymbol) ifTrue: [ ^true ]. >>>>>> (precedence := aSymbol precedence) = 1 ifTrue: [ >>>>>> ^self includesKey: aSymbol ]. >>>>>> (precedence = 3 and: [ (aSymbol indexOf: $:) = aSymbol size ]) ifTrue: [ >>>>>> ^self includesKey: aSymbol allButLast ]. >>>>>> ^false >>>>> That's nice! but why not make it simpler? >>>>> JsonObject >> #respondsTo: aSymbol >>>>> >>>>> | precedence | >>>>> (super respondsTo: aSymbol) ifTrue: [ ^true ]. >>>>> aSymbol isSimpleGetter ifTrue: [^self includesKey: aSymbol]. >>>>> aSymbol isSimpleSetter ifTrue: [^self includesKey: aSymbol asSimpleGetter]. >>>>> ^false >>>> Three reasons: >>>> 1. performance >>>> | j s | >>>> Smalltalk garbageCollect. >>>> j := JsonObject new >>>> foo: 1; >>>> bar: 2; >>>> baz: 3; >>>> yourself. >>>> s := Symbol allSymbols. >>>> { >>>> [ s do: [ :each | ] ] bench. >>>> [ s do: [ :each | j respondsTo: each ] ] bench. >>>> [ s do: [ :each | j respondsTo2: each ] ] bench. "Your suggested implementation" >>>> } >>>> #( >>>> '1,630 per second. 613 microseconds per run. 0 % GC time.' >>>> '19 per second. 52.7 milliseconds per run. 0.09992 % GC time.' >>>> '1.18 per second. 850 milliseconds per run. 32.81709 % GC time.' >>>> ) >>>> Okay, that may not be too a realistic workload. The reason of the extreme >>>> slowdown and high GC time is rapid interning and GCing of Symbols >>>> created by #asSimpleGetter. >>>> If you change s to a handcrafted array that avoids Symbol creation, like >>>> s := #(yourself foo foo: bar bar: baz baz: foobar foobar: name name:) >>>> the numbers get better but still not as good as my suggestion: >>>> #( >>>> '4,970,000 per second. 201 nanoseconds per run. 38.02 % GC time.' >>>> '147,000 per second. 6.82 microseconds per run. 1.74 % GC time.' >>>> '92,300 per second. 10.8 microseconds per run. 1.09978 % GC time.') >>> >>> I thought you'd say that. >>> But "precedence" is one of the most obscure things around that part in the image. >>> >>> >>>> 2. backwards compatibility >>>> #isSimpleSetter and #isSimpleGetter are available since Squeak 5.3. I use this code in 5.1 and 5.2 images as well. >>> >>> Yea, Pre 5.3 I'd have said #asMutator. >>> >>>> 3. to use the same mechanism as #doesNotUnderstand: >>>> Have a look at that method. >>> >>> >>> Then I'd rather say change DNU too. >>> If you're down that hole (dnu/respondsTo) anyways, I don't buy the performance argument anymore. >>> >>> Not everything has to be as fast as possible. >> >> You seem to ignore that #doesNotUnderstand: is the most often used method of JsonObject. >> I assume you don't use the JSON package in production images, hence you don't care about performance. > > I do. > It never has been the bottleneck. > >> I do, so I'm not willing to change the implementation of #doesNotUnderstand: in my fork of the JSON package unless performance is at least as good as it is now. > > I just want the image to remain tractable. that? Also, have you ever had a look at how other stuff is implemented in that package? > Performance is nice. But if you rely on performance with the JSOn stuff, > subclass the JsonObject and implement your keys as messages? That ought to be the fastest way, no? It depends on how your JsonObjects are created. If you parse a json from an external source, you can't do that unless you hardcode the structure of the json into your application. > I though it was meant to be that way. > > That said, I rarely remain in the JSON space for longer than necessary; I'd rather have proper objects and only convert on "the edges" See above. Levente > > I'm not against fast things. > I'm merely a bit startled by fast things that are harder to understand than necessary… > > Best regards > -Tobias > > PS: Levente, your code is almost always the fastest variant of anything we discuss on here. That's amazing in itself. Don't get the impression I'm not amazed by that ;) > >> >> >> Levente >> >>> >>> Best regards >>> -Tobias >>> >>>> Levente >>>>> -Tobias >>>>>> Levente >>>>>> On Sun, 22 Nov 2020, Thiede, Christoph wrote: |
> On 23. Nov 2020, at 18:08, Levente Uzonyi <[hidden email]> wrote: > > On Sun, 22 Nov 2020, Tobias Pape wrote: > >> >> >>> On 22. Nov 2020, at 19:37, Levente Uzonyi <[hidden email]> wrote: >>> Hi Tobias, >>> On Sun, 22 Nov 2020, Tobias Pape wrote: >>>>> On 22. Nov 2020, at 18:51, Levente Uzonyi <[hidden email]> wrote: >>>>> Hi Tobias, >>>>> On Sun, 22 Nov 2020, Tobias Pape wrote: >>>>> Three reasons: >>>>> 1. performance >>>>> | j s | >>>>> Smalltalk garbageCollect. >>>>> j := JsonObject new >>>>> foo: 1; >>>>> bar: 2; >>>>> baz: 3; >>>>> yourself. >>>>> s := Symbol allSymbols. >>>>> { >>>>> [ s do: [ :each | ] ] bench. >>>>> [ s do: [ :each | j respondsTo: each ] ] bench. >>>>> [ s do: [ :each | j respondsTo2: each ] ] bench. "Your suggested implementation" >>>>> } >>>>> #( >>>>> '1,630 per second. 613 microseconds per run. 0 % GC time.' >>>>> '19 per second. 52.7 milliseconds per run. 0.09992 % GC time.' >>>>> '1.18 per second. 850 milliseconds per run. 32.81709 % GC time.' >>>>> ) >>>>> Okay, that may not be too a realistic workload. The reason of the extreme >>>>> slowdown and high GC time is rapid interning and GCing of Symbols >>>>> created by #asSimpleGetter. >>>>> If you change s to a handcrafted array that avoids Symbol creation, like >>>>> s := #(yourself foo foo: bar bar: baz baz: foobar foobar: name name:) >>>>> the numbers get better but still not as good as my suggestion: >>>>> #( >>>>> '4,970,000 per second. 201 nanoseconds per run. 38.02 % GC time.' >>>>> '147,000 per second. 6.82 microseconds per run. 1.74 % GC time.' >>>>> '92,300 per second. 10.8 microseconds per run. 1.09978 % GC time.') >>>> I thought you'd say that. >>>> But "precedence" is one of the most obscure things around that part in the image. >>>>> 2. backwards compatibility >>>>> #isSimpleSetter and #isSimpleGetter are available since Squeak 5.3. I use this code in 5.1 and 5.2 images as well. >>>> Yea, Pre 5.3 I'd have said #asMutator. >>>>> 3. to use the same mechanism as #doesNotUnderstand: >>>>> Have a look at that method. >>>> Then I'd rather say change DNU too. >>>> If you're down that hole (dnu/respondsTo) anyways, I don't buy the performance argument anymore. >>>> Not everything has to be as fast as possible. >>> You seem to ignore that #doesNotUnderstand: is the most often used method of JsonObject. >>> I assume you don't use the JSON package in production images, hence you don't care about performance. >> >> I do. >> It never has been the bottleneck. >> >>> I do, so I'm not willing to change the implementation of #doesNotUnderstand: in my fork of the JSON package unless performance is at least as good as it is now. >> >> I just want the image to remain tractable. > > Does having a method or two implemented in an external package affect that? Also, have you ever had a look at how other stuff is implemented in that package? Been a while. I've used it for some years now but lately, I've not looked into the implementation anymore, no. > >> Performance is nice. But if you rely on performance with the JSOn stuff, >> subclass the JsonObject and implement your keys as messages? That ought to be the fastest way, no? > > It depends on how your JsonObjects are created. If you parse a json from an external source, you can't do that unless you hardcode the structure of the json into your application. Yes, exactly. > >> I though it was meant to be that way. >> >> That said, I rarely remain in the JSON space for longer than necessary; I'd rather have proper objects and only convert on "the edges" > > See above. Best regards -Tobias > > Levente > >> >> I'm not against fast things. >> I'm merely a bit startled by fast things that are harder to understand than necessary… >> >> Best regards >> -Tobias >> >> PS: Levente, your code is almost always the fastest variant of anything we discuss on here. That's amazing in itself. Don't get the impression I'm not amazed by that ;) >> >>> Levente >>>> Best regards >>>> -Tobias >>>>> Levente |
Free forum by Nabble | Edit this page |