Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:89972 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 81278 invoked from network); 3 Jan 2016 04:05:15 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 3 Jan 2016 04:05:15 -0000 Authentication-Results: pb1.pair.com header.from=jbafford@zort.net; sender-id=pass Authentication-Results: pb1.pair.com smtp.mail=jbafford@zort.net; spf=pass; sender-id=pass Received-SPF: pass (pb1.pair.com: domain zort.net designates 96.241.205.2 as permitted sender) X-PHP-List-Original-Sender: jbafford@zort.net X-Host-Fingerprint: 96.241.205.2 nova.zort.net Received: from [96.241.205.2] ([96.241.205.2:53129] helo=nova.zort.net) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id D1/E3-33667-9FD98865 for ; Sat, 02 Jan 2016 23:05:14 -0500 Received: from [10.0.1.2] (pulsar.zort.net [96.241.205.6]) (authenticated bits=0) by nova.zort.net (8.14.5/8.14.5) with ESMTP id u03458Th013621 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Sat, 2 Jan 2016 23:05:08 -0500 Content-Type: text/plain; charset=utf-8 Mime-Version: 1.0 (Mac OS X Mail 8.2 \(2104\)) In-Reply-To: Date: Sat, 2 Jan 2016 23:05:07 -0500 Cc: PHP internals , patriciotarantino@gmail.com Content-Transfer-Encoding: quoted-printable Message-ID: <03C19EDB-DCB1-4234-A1A5-4991600EF259@zort.net> References: To: Sara Golemon , Bishop Bettini X-Mailer: Apple Mail (2.2104) Subject: Re: [PHP-DEV] RFC Operator Overloading in Userspace From: jbafford@zort.net (John Bafford) Hi Sara, On Jan 2, 2016, at 21:14, Sara Golemon wrote: >=20 > Patricio Tarantino has asked me to help him propose Operator > Overloading in PHP 7.1 (based in part on my operator extension in > PECL). I think we can expose this to usespace as magic methods with > very little overhead (the runtime check and dispatch is already there, > after all). >=20 > I do think that the "Future Expansion" section bears following through > with as well, but the basic set of methods already hooked for GMP > would be a nice start. >=20 > https://wiki.php.net/rfc/operator-overloading >=20 > -Sara While I don=E2=80=99t necessarily think adding operator overloading is a = great idea, I think if it=E2=80=99s to be done, we could do better. = I=E2=80=99d offer two suggestions: 1) rather than the list of magic function names, use the actual = operators themselves > function ^($value) or > function operator <<($value) This way, new magic methods don=E2=80=99t have to be created in the = event we created new operators later. (Unlikely, I know.) To handle ambiguity between prefix/postfix/infix operators, you could = use something like: > function prefix -($value) > function infix -($left, $right) > function postfix ++($value) This would also address an issue in the proposal as written: __add and = __sub don=E2=80=99t handle the ambiguity of prefix + and - operators. Bishop Bettini suggests: > public function __overload(string $operator, object $rhs =3D null); // = $rhs =3D=3D=3D null iff op is unary but you really need separate functions (or an additional parameter) to = handle that case. You can=E2=80=99t only pass in null because then you = can=E2=80=99t disambiguate between $foo - null and -$foo. 2) I think we should take a look at Swift=E2=80=99s operator definition = mechanism. Besides just allowing for operator overloading, Swift also = allows you to specify entirely custom operators. For example (from the = Swift Programming Language book, Language Guide, Advanced Operators = chapter): > =E2=80=9CNew operators are declared at a global level using the = operator keyword, and are marked with the prefix, infix or postfix = modifiers: >=20 >> prefix operator +++ {} >=20 > The example above defines a new prefix operator called +++. This = operator does not have an existing meaning in Swift, and so it is given = its own custom meaning below in the specific context of working with = Vector2D instances. For the purposes of this example, +++ is treated as = a new =E2=80=9Cprefix doubling incrementer=E2=80=9D operator. It doubles = the x and y values of a Vector2D instance, by adding the vector to = itself with the addition assignment operator defined earlier: >=20 >> prefix func +++ (inout vector: Vector2D) -> Vector2D { >> vector +=3D vector >> return vector >> }=E2=80=9D > =E2=80=9CThe following example defines a new custom infix operator = called +-, with left associativity and a precedence of 140:=E2=80=9D >=20 >> =E2=80=9Cinfix operator +- { associativity left precedence 140 } >> func +- (left: Vector2D, right: Vector2D) -> Vector2D { >> return Vector2D(x: left.x + right.x, y: left.y - right.y) >> }=E2=80=9D Operators can be defined as prefix, infix, or postfix. Infix operators = can specify associativity (left, right, or none (default)) and = precedence. Swift limits the first character of an operator is limited = to one from a set of typical operator symbols and a set of unicode = characters, so you can=E2=80=99t create or overload operators using = arbitrary ascii characters. In PHP, we might imagine this example to look like: > //in global scope > operator infix +- associativity(left) precedence(140); > function +-($left, $right) { =E2=80=A6 } In Swift, operator definitions and overloads are done in on a global = basis (and multiple definitions are resolved appropriately with = Swift=E2=80=99s type system). This makes sense for Swift, but it would = be more difficult for PHP, given PHP=E2=80=99s more flexible type = system. I=E2=80=99m unclear what the best approach is to handle = typehints, which in this case are more part of the operator functions = logic name than just run-time limitations on parameters. The major problem I see with this, besides the parser complexity it = would entail, is that it would make static analysis that much harder, = and you wind up with PHP code that can=E2=80=99t actually compile unless = the operator definitions are loaded. -John