Hopefully not too dead of a topic (just catching up on the list...), but

1) I think a lot of this pattern can be encoded at the library level assuming a 
catch-all operator

2) A practical use case I had wanted to do this for was distributed objects 
(e.g., batching updates until a commit). 

Either way, again, I think it's a library-level thing assuming an updated meta 
object protocol.

Regards,

- Leo




On Apr 13, 2011, at 1:37 AM, [email protected] wrote:

> Send es-discuss mailing list submissions to
>       [email protected]
> 
> To subscribe or unsubscribe via the World Wide Web, visit
>       https://mail.mozilla.org/listinfo/es-discuss
> or, via email, send a message with subject or body 'help' to
>       [email protected]
> 
> You can reach the person managing the list at
>       [email protected]
> 
> When replying, please edit your Subject line so it is more specific
> than "Re: Contents of es-discuss digest..."
> Today's Topics:
> 
>   1. Re: [Harmony proxies] Discussion on the "declarative object"
>      experiment (Dmitry A. Soshnikov)
>   2. Re: [Harmony proxies] Discussion on the "declarative object"
>      experiment (David Bruant)
>   3. Re: 'this' is more complicated than I thought
>      (PropertyReferencesbreak equivalences) (Claus Reinke)
> 
> From: "Dmitry A. Soshnikov" <[email protected]>
> Date: April 13, 2011 1:18:51 AM PDT
> To: David Bruant <[email protected]>
> Cc: [email protected]
> Subject: Re: [Harmony proxies] Discussion on the "declarative object" 
> experiment
> 
> 
> On 13.04.2011 12:08, David Bruant wrote:
>> 
>> Le 13/04/2011 09:02, Dmitry A. Soshnikov a écrit :
>>> 
>>> On 12.04.2011 20:41, David Bruant wrote:
>>>> 
>>>> Hi,
>>>> 
>>>> I'd like to share my experience on a recent experiment. First off, I'd 
>>>> like to apologize for the name; "declarative object" doesn't really 
>>>> capture it and may be confusing. Second of all, what I have created 
>>>> doesn't really solve any use case (I'll discuss it), but offers at most 
>>>> some syntactic sugar. Code can be found here : 
>>>> https://github.com/DavidBruant/DeclO
>>>> 
>>>> One idea is to have an object "o". This object can accept any property 
>>>> name (get trap only in my case). Accessing a property will generate an 
>>>> object on-the-fly which itself can accept any property name and generate 
>>>> an object, etc. At the end, the object can be used as a constructor to do 
>>>> something. Example:
>>>> ---
>>>> var a = new o.azerty.are.the.first.letters.of.my.keyboard();
>>>> var b = new o.David.Bruant.writes.JavaScript();
>>>> ---
>>>> The point could be to build something based on the property names (stored 
>>>> in the propNames variable and added with the push l.8). Of course, a 
>>>> constructor taking a string array could be as useful. That's the reason 
>>>> why I said earlier it doesn't solve any use case. The syntax sugar is the 
>>>> only added value I can think of.
>>>> The exact use of the string array is to be defined in the constructTrap 
>>>> function. The pattern is here.
>>>> 
>>> 
>>> Yes, the pattern is interesting, though, really, which practical use-case 
>>> will it have?
>> I warned from the beginning that I didn't see any :-p
>> More seriously, the main point of sharing my experiment was the discussion 
>> on shared handlers for several proxies.
>> 
>>> Currently a one possible I see -- a query to database with building the 
>>> query itself. Sort of:
>>> 
>>> where
>>>     .name("Dmitry")
>>>     .surname("Soshnikov")
>>>     .active(true)
>> I have tried to think of a lot of use cases. This one, for instance, doesn't 
>> even requires proxies (As I understand it). As long as you know the number 
>> and names of the all properties (I assume you do by knowing which database 
>> table you're querying), ES5 accessor properties could be used. This goes 
>> with the restriction that it's likely to be far more memory consumming, but 
>> the pattern could be applied the same way.
>> Now that I think about it, I realize that for getters/setters, the exact 
>> same object could be used (may depend on the use case). Same for my pattern, 
>> I use Proxy.createFunction for each intermediary (l.10), but I could 
>> factorize it and return the same proxy each time since traps don't change at 
>> all.
>> 
>> Also, I'd like to note that if each of your property is a function call, you 
>> don't even need accessor properties. That's what jQuery already does by 
>> returning "this".
>> 
>> 
>>> etc (though, it should be callable in contrast with yours implementation). 
>>> But, it also arguable whether it's so useful.
>> I have no strong opinion on callable or not. It was just an idea that the 
>> pattern would better be used as a constructor. The main point of the pattern 
>> lies on the use of the get trap in "firstHandler" and "middleHandler". It 
>> could be improved by a different call/construct trap (and the use of 
>> arguments for these).
>> 
> 
> Yeah, right, that's why I also mentioned that it's arguable whether the 
> pattern is useful to apply to this particular issue. It wast just a guess.
> 
> Regarding shared handlers, if exactly this is the point, we have also think 
> which practical things can we have.
> 
>> 
>>> 
>>> However, your letter made me think on proposing existential operator, which 
>>> is a syntactic sugar to avoid long testing whether a property exists and 
>>> only after that to apply it. This already is again used in CoffeeScript, so 
>>> I'll show the examples:
>>> 
>>> let street = user.address?.street
>>> 
>>> which desugars e.g. into:
>>> 
>>> street = (typeof user.address != "undefined" && user.address != null)
>>>     ? user.address.street
>>>     : undefined;
>> Shouldn't it desugar to "(typeof user.address == "object" && user.address != 
>> null)?" ?
>> 
> 
> Yeah, it's also just an example, any (but the most efficient) desugared 
> variant can be used.
> 
> Dmitry.
> 
> 
> 
> From: David Bruant <[email protected]>
> Date: April 13, 2011 1:32:14 AM PDT
> To: "Dmitry A. Soshnikov" <[email protected]>
> Cc: [email protected]
> Subject: Re: [Harmony proxies] Discussion on the "declarative object" 
> experiment
> 
> 
> Le 13/04/2011 10:18, Dmitry A. Soshnikov a écrit :
>> 
>> On 13.04.2011 12:08, David Bruant wrote:
>>> 
>>> Le 13/04/2011 09:02, Dmitry A. Soshnikov a écrit :
>>>> Yes, the pattern is interesting, though, really, which practical use-case 
>>>> will it have?
>>> I warned from the beginning that I didn't see any :-p
>>> More seriously, the main point of sharing my experiment was the discussion 
>>> on shared handlers for several proxies.
>>> 
>>> (...)
>>> 
>> (...)
>> 
>> Regarding shared handlers, if exactly this is the point, we have also think 
>> which practical things can we have.
> The straightforward benefit I see for shared handlers is to avoid one handler 
> instanciation per proxy instanciation. The downside is the brainfuck it 
> produces in terms of scope definition and code organisation (I've worked hard 
> to make my code easy to read. I find it hard nonetheless).
> 
> Do you have other practical things in mind?
> 
> David
> 
> 
> 
> From: "Claus Reinke" <[email protected]>
> Date: April 13, 2011 1:38:07 AM PDT
> To: <[email protected]>, "Lasse Reichstein" <[email protected]>
> Subject: Re: 'this' is more complicated than I thought 
> (PropertyReferencesbreak equivalences)
> 
> 
>> The behavior of References isn't as arbitrary or different from other 
>> languages as it might seem. It's really a way to specify l-values.
> 
> Not arbitrary, but different, and quite drastically so (as far as
> usage is concerned). Your remarks helped me to pin down the difference (and 
> eliminated two of my questions, thanks!-): References are l-values, but they 
> cannot be used as such, due to forced, implicit conversion curtailing their 
> lifetimes.
> 
> The differences between References and general l-values (_values_ that 
> represent locations where other values may be
> stored) lies in how they may be used and how long they live:
> 
> - l-values are first-class values: they can be passed around,    assigned to 
> variables, stored in data structures; they happen    to support a 
> de-referencing operation, but merely evaluating
>   an l-value does not de-reference it; l-values can be    de-referenced 
> explicitly; some languages implicitly coerce    l-values into r-values 
> (causing de-reference) depending on
>   usage context (this is where the names come from: values    on the left and 
> right hand sides of assignments), but even    those languages tend to provide 
> means to control when    coercions take place
> 
> - References start out as l-values, but don't live long enough
>   to be used as such. They cannot be passed around, stored    in data 
> structures, or assigned to variables; any attempt to    evaluate them leads 
> to immediate de-reference, no matter    whether the usage context expects an 
> l-value or not; there
>   is no way to prevent the implicit de-reference
> 
> It is mostly the implicit coercion in evaluation, combined with
> the early evaluation inherent in Javascript's call-by-value semantics, that 
> breaks those equivalences.
> 
>> In other languages, e.g., C or Java, you have the same problem:
>>  int x = something.prop;
>>  x = 10;
>> is not the same as
>>  something.prop = 10;
> 
> My C has been buried for too long, but were not l-values
> one of C's showcases? Something like this
> 
>   int *x = &(something.prop);
>   *x = 10;
> 
> should work, by making x hold l-values (in case I messed up the syntax beyond 
> recognition: x should be a pointer to int,
> its value being the address of something.prop, so we can use
> the r-value of x as an l-value in the second assignment).
> 
> C allowed us to be explicit about whether we wanted l-values
> or r-values, overriding the default conversions when necessary.
> Some later languages, such as Haskell or Standard ML, dropped
> the implicit coercions entirely, so all de-references are explicit.
> 
> ECMAScript relies on implicit de-reference, but triggers that by
> every evaluation. So we don't have explicit de-reference, we do
> not have C's flexibility for explicit de-reference control, and we
> do not even have C's context-sensitive implicit de-reference.
> 
> Which means that things like
> 
> (1 ? obj.prop : obj.prop) = 3;
> (0, obj.prop) = 2;
> 
> will work in C, but fail in ES (References are very short-lived
> l-values - every operation evaluates and de-references them,
> independent of whether the result is going to be used in an
> l-value or r-value context). 
> Also, in C we can write
> 
> x = &(obj.prop);
> *x = 4;
> 
> to express that we want x to hold l-values, and storing l-values in arrays 
> isn't much different
> 
> int *a[1] = { &obj.prop };
> *(a[0]) = 1;
> 
> In ES, we only have the default-to-r-value path. For instance,
> 
> [obj.prop][0] = 1; 
> will not use obj.prop as an l-value, and there does not seem to be a 
> straightforward alternative for programmers who want to work with ES 
> References as l-values.
>> So far, References as a specification mechanism is just following other 
>> languages, and behaving exactly as any seasoned programmer would expect. 
> 
> Does the above explain why a seasoned programmer
> might reasonably expect differently, because ECMAScript behaves differently 
> from other languages?
> 
>> The binding of "this" when calling a Reference value mimics method calls. It 
>> does so fine when you treat objects as objects, but not when you try to 
>> extract a method from its object .. It's a shallow abstraction, but it does 
>> work when you play along with it.
> 
> I was trying to point out that the mechanism works for the
> simple case and is known to confuse programmers for other cases. In 
> particular, I am trying to find out whether the current mechanism is a 
> special case of a more complete mechanism,
> one that works equally well for simple and non-simple cases.
> 
> Since PropertyReferences hold the object the method was
> selected from, all that seems needed is to make References
> survive evalutation, ie, make References first-class values.
> 
> An alternative would be to preserve context-information
> during evaluation: if the result of '(?:)' is to be used as an
> l-value, then evaluation should perhaps not de-reference
> the l-values in the conditional.
> 
> I am less concerned with being able to use '(?:)' on the
> left hand side of assignments, and more with being able
> to use equivalences like '(true ? x : x) <--> x', independent
> of where the expression occurs. Since we can write such
> conditionals on left hand sides, why not make sure that
> they actually work there?
> 
>>> Question 1:     Should a Reference hold on to the current                   
>>>      property value?
>> Which value? The one the property (if it existed) had when the reference was 
>> created? Or the current one - if the Reference survives for any amount of 
>> time, the object property could change its value in the meantime.
> 
> Thanks. So the answer probably is 'no' - which value we get depends on when 
> we look behind the reference. 
> I guess I was confused by property accessors not actually accessing the 
> property - once the decision is made to return a Reference instead of the 
> property value, it would only be
> consequent to keep Reference construction and de-reference
> separated. As long as we are able to specify when to pass the reference and 
> when to look up the value behind it.
> 
>>> Question 2:
>>>    If a Reference allows us to recover 'obj' from 'obj.method',
>>>    why does this information have to get lost when passing     it through a 
>>> variable binding?
>>>    .. could this error source be eliminated by passing the      Reference 
>>> as a value, instead of only the value component
>>>    without the base object, one step further?
>> Of course it's possible, but personally I prefer to have the "this" object 
>> obvious in the call line. That way I know what object the method is being 
>> called on. Without it, the loss of context is in the source code, making it 
>> harder to read and maintain.
> 
> I'm afraid you won't get that comfort;-) At the moment, programmers can just 
> write the more complicated
> 
>   var short = function(x) { return obj.method(x); };
>   short("hi"); // no 'this' object on the call line
> 
> We can try to make this more readable, and we can try to
> eliminate a common source of bugs, but the rest is between
> you and your team's coding style and style checker.
>>> Question 3:
>>>    It seems that trying to reuse References for 'this' forces
>>>    early calls to GetValue (because users should not have to
>>>    call 'obj.method.valueOf()' or 'obj.property.valueOf()' to      trigger 
>>> the delayed selection, and because the property
>>>    value is not stored in the PropertyReference).
>> I'm not sure I understand what the problem is here.
> 
> Probably because the description is a bit confusing. I was
> trying to understand why References get eliminated early,
> through calls to GetValue, and was enumerating non-reasons
> before coming to my question:
> 
>>> This loses information that we would like to hold on to -     if we really 
>>> cannot solve this for References in general,
>>> why not store the 'this'-candidate in the function instead
>>> (similar to the fairly new '[[boundThis]]')?
>> Won't work. The same function can be used in many places at the same time.
> 
> Ah, good point. If functions were constants, we could make copies (sharing 
> the code, but with different this values). But
> they aren't, so we need the 'this'-candidates outside the function.
> 
>> E.g.
>> [obj1.foo, obj2.foo][(Math.random() * 2) | 0]();
> 
> Note that, currently, either selection will have that anonymous first array 
> as 'this', not obj1 or obj2. But
> you were aware of that, right?-)
>>> Question 4: (general version of question 2)
>>>    Why is the origin information in References lost so easily?
>>> 
>>>    It seems that most parts of the spec require GetValue() by
>>>    default, with few exceptions. What would go wrong if the
>>>    available information would be passed on instead (isn't
>>>    it sufficient for the final consumers to call GetValue(),
>>>    provided that the original property value is stored in the
>>>    PropertyReference, to avoid interference)?
>> References is a specification tool. If it survived for an extended amount of 
>> time, and visibly so, implementations would have to actually implement 
>> something to represent it. As it is now, a reference is found and 
>> immediately consumed, which allows implementations to never create it at 
>> all, and work directly on the value in r-value contexts, and on the object 
>> and property in l-value contexts.
> 
> Yes, and that is my argument. L-values as first-class values is the common 
> way to handle references, whether it is in C, in Haskell, in ML, .., ever 
> since Strachey documented l-values in 1967, and probably longer than that. 
> Once references become visible to programmers, one might as well support them 
> fully. Eliminating
> temporary structures is a common implementation optimization, not limited to 
> References, and not a language spec concern.
> 
>>> Broken equivalences:
> ..
>>>    var x = obj.m; x(); <-/-> obj.m();
>>> 
>>>    obj.m.valueOf() <-/-> obj.m
>> Why should that work? The valueOf function isn't guaranteed to return 
>> anything related to the object it's on.
> 
> The default valueOf for Function comes from Object,
> where it is 'ToObject this', which for Object is the input
> argument without conversion. I think..
> 
>> This is exactly correct. Extracting a method from its object will break the 
>> connection to the object. Which is kind of expected when you allow any 
>> function to be used as both a method and a non-method.
> 
> I expected none of these:
> 
> - Property access is not extraction.
> - Extraction is triggered by constructs that could just
>   as well pass on the property accessor (and probably
>   should, as the alternative leads to runtime errors).
> - Extraction alone will not break the connection, only
>   some forms of triggering extractions will do so.
> - A new connection is established by trying to pass
>   a property accessor through an Array.
> 
>>> I was not aware that just about any code transformation
>>> would be invalidated by the handling of References. If this cannot be 
>>> fixed, could the specification be more explicit about this, please?
>> When I think of References as l-values, the current behavior actually become 
>> the expected one. The only tricky bit is that method-calls actually need an 
>> l-value to work correctly.
> 
> Even the l-value part is unusual, as I've tried to show.
> 
> Claus
> 
> 
> 
> 
> _______________________________________________
> es-discuss mailing list
> [email protected]
> https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to