Support for basic linear algebra on Array's

Brendan Eich brendan at mozilla.com
Sun Nov 18 19:08:34 PST 2012


Oliver Hunt wrote:
> On Nov 18, 2012, at 6:17 PM, Matt Calhoun<calhoun137 at gmail.com>  wrote:
>
>> I believe that having a concise notation for linear algebra is an important feature of a programming language that can dramatically improve code readability, and furthermore that linear algebra is a powerful tool that has many applications in java script.  I would like to make the following two suggestions: 
>>
>>
>> 1. Extend the "+" operator to work on Array's of numbers (or strings).
>>
>> 2. Allow for scalar multiplication of Array's which contain only numbers. 
>>
>>
>> Although there are many problems with a simple linear algebraic solution which arise in contexts where java script is a natural language of choice (for example WebGL), there are no simple ways to express these solutions in java script because the language itself creates a barrier to even basic operations such as subtracting two vectors, in the sense that the amount of writing it takes to express these operations obscures their mathematical content.  For more complicated linear algebraic work, the problem is quite severe. 
>>
>
> Changing the behaviour of any of the basic operators on builtin/pre-existing types is essentially a non-starter.  + already has sufficiently, errr, "sensible" behaviour to be widely used on arrays.  Other operators don't really have any such "sensible" use cases, but changing their semantics on one kind of object vs. other kinds would be highly worrying. 
>
>
> (2) would also be a non-starter i feel: JS implicitly converts to number in all other cases, and if we made operator behaviour dependent on content type (in a nominally untyped language) I suspect we would very rapidly end up in a world of semantic pain, and another WAT presentation. 
>

I think we could actually reduce the WAT effect in JS with *opt-in* 
operators for value objects. This is on the Harmony agenda:

http://wiki.ecmascript.org/doku.php?id=strawman:value_objects
http://wiki.ecmascript.org/doku.php?id=strawman:value_proxies

I've implemented int64 and uint64 for SpiderMonkey, see 
https://bugzilla.mozilla.org/show_bug.cgi?id=749786, where in the patch 
there's a comment discussing how the operators for these new 
value-object types work:

/*
  * Value objects specified by
  *
  *  http://wiki.ecmascript.org/doku.php?id=strawman:value_objects
  *
  * define a subset of frozen objects distinguished by the 
JSCLASS_VALUE_OBJECT
  * flag and given privileges by this prototype implementation.
  *
  * Value objects include int64 and uint64 instances and support the 
expected
  * arithmetic operators: | ^ & == < <= << >> >>> + - * / %, boolean 
test, ~,
  * unary - and unary +.
  *
  * != and ! are not overloadable to preserve identities including
  *
  *  X ? A : B <=>  !X ? B : A
  *  !(X && Y) <=>  !X || !Y
  *  X != Y <=>  !(X == Y)
  *
  * Similarly, > and >= are derived from < and <= as follows:
  *
  *  A > B <=>  B < A
  *  A >= B <=>  B <= A
  *
  * We provide <= as well as < rather than derive A <= B from !(B < A) 
in order
  * to allow the <= overloading to match == semantics.
  *
  * The strict equality operators, === and !==, cannot be overloaded, 
but they
  * work on frozen-by-definition value objects via a structural 
recursive strict
  * equality test, rather than by testing same-reference. Same-reference 
remains
  * a fast-path optimization.
  *
  * Ecma TC39 has tended toward proposing double dispatch to implement 
binary
  * operators. However, double dispatch has notable drawbacks:
  *
  *  - Left-first asymmetry.
  *  - Exhaustive type enumeration in operator method bodies.
  *  - Consequent loss of compositionality (complex and rational cannot be
  *    composed to make ratplex without modifying source code or wrapping
  *    instances in proxies).
  *
  * So we eschew double dispatch for binary operator overloading in 
favor of a
  * cacheable variation on multimethod dispatch that was first proposed 
in 2009
  * by Christian Plesner Hansen:
  *
  *  https://mail.mozilla.org/pipermail/es-discuss/2009-June/009603.html
  *
  * Translating from that mail message:
  *
  * When executing the '+' operator in 'A + B' where A and B refer to value
  * objects, do the following:
  *
  *  1. Get the value of property LOP_PLUS in A, call the result P
  *  2. If P is not a list, throw a TypeError: no '+' operator
  *  3. Get the value of property ROP_PLUS in B, call the result Q
  *  4. If Q is not a list, throw a TypeError: no '+' operator
  *  5. Intersect the lists P and Q, call the result R
  *  6. If R is empty throw, a TypeError: no '+' operator
  *  7. If R has more than one element, throw a TypeError: ambiguity
  *  8. If R[0], call it F, is not a function, throw a TypeError
  *  9. Evaluate F(A, B) and return the result
  *
  * Rather than use JS-observable identifiers to label operator 
handedness as
  * in Christian's proposal ('this+', '+this'), we use SpecialId 
variants that
  * cannot be named in-language or observed by proxies.
  *
  * To support operator overloading in-language, we need only provide an API
  * similar to the one Christian proposed:
  *
  *  function addPointAndNumber(a, b) {
  *    return new Point(a.x + b, a.y + b);
  *  }
  *
  *  Function.defineOperator('+', addPointAndNumber, Point, Number);
  *
  *  function addNumberAndPoint(a, b) {
  *    return new Point(a + b.x, a + b.y);
  *  }
  *
  *  Function.defineOperator('+', addNumberAndPoint, Number, Point);
  *
  *  function addPoints(a, b) {
  *    return new Point(a.x + b.x, a.y + b.y);
  *  }
  *
  *  Function.defineOperator('+', addPoints, Point, Point);
  */


This is all experimental and not for ES6, but it does not increase the 
WAT effects, quite the contrary. int64, uint64, decimal, bignum, 
complex, and even vector and matrix value object types for linear 
algebra and graphics applications need operators and literal syntax for 
usability. Requiring method-based or functional APIs is just 
user-hostile and drives developers back toward binary double. See

http://www.jroller.com/cpurdy/entry/the_seven_habits_of_highly1

especially the first comment.

> Also anytime i've seen someone propose * operating on arrays it rapidly becomes a flamewar between element-by-element multiplication and n-dimensional-dot-product. 
>

I agree that * or other operators should not be naively supported on 
arrays, which are not value objects in any case. Any vector or matrix 
value object would want sweet literal syntax, but it wouldn't be array 
literal syntax, exactly.

The use-cases want opt-in operators/literals via modules, with a 
principled approach to avoiding adding support for * to arbitrary other 
code. Lexically scoped operators, perhaps as hygienic macros a la a 
future sweetjs.org approach (infix operator macros are on the agenda 
there, not yet supported), is the way to go.

Anyway, Matt's request is reasonable in my view, when phrased in terms 
of well-scoped opt-in extensions rather than magic new-default behavior 
for arrays.

/be

>
> ES6 provides comprehensions however that might make the world nicer for a lot of your use cases. 
>
>
> --Oliver
>
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>


More information about the es-discuss mailing list