I'd like to contribute to the JSON project

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

Re: I'd like to contribute to the JSON project

Eliot Miranda-2


On Mon, Nov 9, 2020 at 8:29 AM Thiede, Christoph <[hidden email]> wrote:

But I doubt that's what Christoph would like to have.


That is right, I was assuming some kind of late-binding prototypical object model.


For instance, a similar model seems to be used for JavaScript objects:


> x = {}
{}
> x.foo
undefined
x.hasOwnProperty('foo')
false
> x.foo = 42
42
> x.foo
42
x.hasOwnProperty('foo')
true

However, I see your concerns, Levente ... My proposal would violate the contract "if and only if #respondsTo: returns true, sending the message will not cause a MNU", if there was any contract like. But do we need logical equivalency for such a contract or would simple causality ("if #respondsTo: returns true, then sending the message will not cause a MNU") suffice? Hm ...

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,

Christoph



Von: Squeak-dev <[hidden email]> im Auftrag von Levente Uzonyi <[hidden email]>
Gesendet: Montag, 9. November 2020 15:17 Uhr
An: The general-purpose Squeak developers list
Betreff: Re: [squeak-dev] I'd like to contribute to the JSON project
 
Hi Marcel,

On Mon, 9 Nov 2020, Marcel Taeumel 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.

In that case JsonObject >> #respondsTo: should return true for all unary
and one-argument keyword selectors. But I doubt that's what Christoph
would like to have.


Levente

>
> 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
Squeak - Dev forum and mailing list archive. The general-purpose Squeak developers list


>
>
>




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


Reply | Threaded
Open this post in threaded view
|

Re: I'd like to contribute to the JSON project

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

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


Reply | Threaded
Open this post in threaded view
|

Re: I'd like to contribute to the JSON project

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



Reply | Threaded
Open this post in threaded view
|

Re: I'd like to contribute to the JSON project

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



Reply | Threaded
Open this post in threaded view
|

Re: I'd like to contribute to the JSON project

Christoph Thiede

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!
Reply | Threaded
Open this post in threaded view
|

Re: I'd like to contribute to the JSON project

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



Reply | Threaded
Open this post in threaded view
|

Re: I'd like to contribute to the JSON project

Christoph Thiede

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!
Reply | Threaded
Open this post in threaded view
|

Re: I'd like to contribute to the JSON project

Christoph Thiede
(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




JSON-ct.56.mcz (35K) Download Attachment
Carpe Squeak!
Reply | Threaded
Open this post in threaded view
|

Re: I'd like to contribute to the JSON project

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

Reply | Threaded
Open this post in threaded view
|

Re: I'd like to contribute to the JSON project

Tobias Pape


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



Reply | Threaded
Open this post in threaded view
|

Re: I'd like to contribute to the JSON project

Christoph Thiede

+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!
Reply | Threaded
Open this post in threaded view
|

Re: I'd like to contribute to the JSON project

Levente Uzonyi
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
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.')


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

Reply | Threaded
Open this post in threaded view
|

Re: I'd like to contribute to the JSON project

Tobias Pape


> 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



Reply | Threaded
Open this post in threaded view
|

Re: I'd like to contribute to the JSON project

Levente Uzonyi
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, 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

Reply | Threaded
Open this post in threaded view
|

Re: I'd like to contribute to the JSON project

Tobias Pape


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



Reply | Threaded
Open this post in threaded view
|

Re: I'd like to contribute to the JSON project

Levente Uzonyi
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.
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?

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

Reply | Threaded
Open this post in threaded view
|

Re: I'd like to contribute to the JSON project

Tobias Pape


> 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



12