Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:90000 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 63632 invoked from network); 4 Jan 2016 19:41:06 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 4 Jan 2016 19:41:06 -0000 Authentication-Results: pb1.pair.com smtp.mail=rowan.collins@gmail.com; spf=pass; sender-id=pass Authentication-Results: pb1.pair.com header.from=rowan.collins@gmail.com; sender-id=pass Received-SPF: pass (pb1.pair.com: domain gmail.com designates 74.125.82.51 as permitted sender) X-PHP-List-Original-Sender: rowan.collins@gmail.com X-Host-Fingerprint: 74.125.82.51 mail-wm0-f51.google.com Received: from [74.125.82.51] ([74.125.82.51:38392] helo=mail-wm0-f51.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 89/69-07292-2DACA865 for ; Mon, 04 Jan 2016 14:41:06 -0500 Received: by mail-wm0-f51.google.com with SMTP id b14so1233946wmb.1 for ; Mon, 04 Jan 2016 11:41:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=subject:to:references:from:message-id:date:user-agent:mime-version :in-reply-to:content-type:content-transfer-encoding; bh=3QqaMO1Xqn/PkHDHqMeFNcZAel0EV3aVmvPD6LQ3dfs=; b=eH6cDFHYq1/rn1A9pno1HRNzDVlxOs3ECmgqQ81WCJ75rDrYsv2MsizCcmcAsf4uHU vFrzPGeS44FNmmsvvMs0IhvcomQDPXvpzRPRpnxcyaoExLF72iQBe/qlBbP88r84Z824 5lKT4T6PFYYTuFEvtCS4Gt7eYKLCylbMoL71rzAitDpwT74vEoCfrXEPLUAHGk9UkSUX Rk56ybXWqC8HGI4lBhPrF30CC16bvfR/2bMDbmi7TZ8TrdTqMNbwGI/mLdZN2U9AQgxe lG1dwUgPiYbF0RyMYEOG4bdEF/CCrhAbu3K7zSW+QDmKAMRkoJNWod4G6K2yKNlM+PkD KXMg== X-Received: by 10.194.104.5 with SMTP id ga5mr99001531wjb.155.1451936462591; Mon, 04 Jan 2016 11:41:02 -0800 (PST) Received: from [192.168.1.189] ([2.31.24.87]) by smtp.googlemail.com with ESMTPSA id 193sm79582wmg.16.2016.01.04.11.41.01 for (version=TLSv1/SSLv3 cipher=OTHER); Mon, 04 Jan 2016 11:41:01 -0800 (PST) To: internals@lists.php.net References: <12.34.07292.41F9A865@pb1.pair.com> Message-ID: <568ACAC7.4040606@gmail.com> Date: Mon, 4 Jan 2016 19:40:55 +0000 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Thunderbird/38.5.0 MIME-Version: 1.0 In-Reply-To: <12.34.07292.41F9A865@pb1.pair.com> Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Subject: Re: [PHP-DEV] Re: RFC Operator Overloading in Userspace From: rowan.collins@gmail.com (Rowan Collins) On 04/01/2016 16:34, Andrea Faulds wrote: > In Haskell, a purely-functional programming language, certain > operators (and also certain math functions like abs()) are defined as > part of "typeclasses", somewhat akin to interfaces in classical > object-oriented languages like Java or PHP. These typeclasses group > related operations together, and a conforming implementation of that > typeclass must implement all the operations. [...] I think it would be > more worth pursuing a Haskell-style approach in PHP, most likely with > a hierarchy of magic interfaces. For those not familiar with type classes, it's worth mentioning something you clarified to me over Twitter some time ago, about how they differ from interfaces (correct me if I go wrong). With an interface, the definition of GMP could include "implements NumLike", meaning that any instance of GMP "is a NumLike object"; there are only two entities to define: the interface, and the class which implements it. With a type class, GMP itself wouldn't implement NumLike, you would have a third entity, which was "an instance of NumLike for GMP objects"; GMP would "have a NumLike type class", defined externally to it. This goes some way to addressing the question of which operand receives the message that an overloaded operator has been invoked - the implementation would not have a "$this". As I understand it, multi-parameter type classes even allow you to bridge between types that aren't aware of each other - e.g. define the result of gmp_init(42) + \Litipk\BigNumbers\Decimal::create(42) Incidentally, my main exposure to operator overloading and custom operators is in PostgreSQL, which implements them as a special case of overloaded function despatch: you can have two functions "add(int, int)" and "add(float, float)", which will be selected between when a statement is compiled; you can then define the binary operator "+" for types "int, int" maps to function "add(int, int)", and it's dispatched the same way. Again, this removes the question of which operand should receive the message, because the operator (and its associated function) are not part of the type - if you want to add an int to a float, you can / must define both "operator + (int, float)" and "operator + (float, int)". Like in C++, though, Postgres's operators aren't intrinsically grouped, and it's up to you to use them in idiomatic ways, such as "||" for various types of concatenation (because SQL) and "@>" for "contains". The major disadvantage to separating the implementation of the operator / type class from the class definition is that I can't see how it would work with autoloading. Regards, -- Rowan Collins [IMSoP]