Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:92456 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 55531 invoked from network); 19 Apr 2016 13:25:27 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 19 Apr 2016 13:25:27 -0000 Authentication-Results: pb1.pair.com smtp.mail=bishop.bettini@gmail.com; spf=pass; sender-id=pass Authentication-Results: pb1.pair.com header.from=bishop.bettini@gmail.com; sender-id=pass Received-SPF: pass (pb1.pair.com: domain gmail.com designates 209.85.214.194 as permitted sender) X-PHP-List-Original-Sender: bishop.bettini@gmail.com X-Host-Fingerprint: 209.85.214.194 mail-ob0-f194.google.com Received: from [209.85.214.194] ([209.85.214.194:32936] helo=mail-ob0-f194.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id A7/22-43496-6C136175 for ; Tue, 19 Apr 2016 09:25:27 -0400 Received: by mail-ob0-f194.google.com with SMTP id js7so1929424obc.0 for ; Tue, 19 Apr 2016 06:25:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:reply-to:sender:in-reply-to:references:from:date :message-id:subject:to:cc; bh=WFzB2kL21QXP6ABc4N4ja19Pfnp/KR9hJQdOBz+YGQ4=; b=wip6Bl1zSJYikyARD9v538g/y8cfIkt1VN3EnF7kH6hn46OY/tQc+xiPXg6Mo11dFg aPmbZ8NTUbs/EmwY8fB65k+i2fx2fuw9Wu7qqe8sGadzZxjp9x/6EyNL5FK5FP0Rx4vT QTjrF7e1qR3keD6SKtyU+jlHKsUi5aVy5a34IR43+BRWJXQsPp+iYhF6o19IoFO0uREq z9xElsjmsK5IDLTyB7paTgjHuw4sDeHtvP+paSTPdZ9LZI++LjJL2fV84caajl5g8pi2 MYSmXEGx/+HWuQCem4L2CgnEBZGmAepSyGgjYKGrRyA6xGFwzCXdpqgmOclChVEvVwQl Zr+A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:reply-to:sender:in-reply-to :references:from:date:message-id:subject:to:cc; bh=WFzB2kL21QXP6ABc4N4ja19Pfnp/KR9hJQdOBz+YGQ4=; b=MK4UMZTlRp8gvY+STflqF3W0agvsdf2SLewn+z6AT0fVEbsq8UQpjw7BrbYMQ9jj8u 2lOnBFqJNtQHkU7N4SXGbQO8JmQjRZ+WyLYNjmvz3Jr4z/UerIXM2qVOsaJACZZIsaZG p5QPjMvU5JzlBI5kpU78GlYLteYRPzvLG5kHbBUOLGeMc0sxCIHaJ/WS84VkkxkDhecn 93cfDC4dhhRLGf9AZ3mwXD6aPwHV3by/lRFVDxe22X3iyIhjXmL6CaYZAZzMit4XXSQB ++V4szrn/5PruFOmfMt4coF4EJnXmcL0+EgWK+CpamFqSTM8oPmUty4x8W4F7K1RqzEY uNdQ== X-Gm-Message-State: AOPr4FXpYAOQ9Z6+kRP8/3rwCI7YBz7Axj7rm1uo7XwbQKXfgFEThSVIYJZv7VsLQa3iajB5Br710wi9HkNXlA== X-Received: by 10.182.245.138 with SMTP id xo10mr1134178obc.56.1461072323954; Tue, 19 Apr 2016 06:25:23 -0700 (PDT) MIME-Version: 1.0 Reply-To: bishop@php.net Sender: bishop.bettini@gmail.com Received: by 10.157.36.137 with HTTP; Tue, 19 Apr 2016 06:24:54 -0700 (PDT) In-Reply-To: <571589AF.3090502@gmail.com> References: <571581C7.7010901@gmail.com> <571589AF.3090502@gmail.com> Date: Tue, 19 Apr 2016 09:24:54 -0400 X-Google-Sender-Auth: _ACAAE5aBWxi5WzAOa7qSXAlgu8 Message-ID: To: Stanislav Malyshev Cc: PHP internals Content-Type: multipart/alternative; boundary=001a11c1d78adc52650530d66847 Subject: Re: [PHP-DEV] [VOTE] Catching Multiple Exception Types From: bishop@php.net (Bishop Bettini) --001a11c1d78adc52650530d66847 Content-Type: text/plain; charset=UTF-8 On Mon, Apr 18, 2016 at 9:28 PM, Stanislav Malyshev wrote: > Hi! > > > It's about the perception of consistency. "Oh, I can do this! Neat:" > > > > function neat(Foo | Bar $a) { ... } > > You shouldn't be able to do this, because it makes no sense - why would > a function accept two random types and only them? That's probably a bad > design - it should be one type or two functions. > > > "But I can't do this? WTF?" > > > > catch (FooException | BarException $ex) { ... } > > But this makes total sense - you routinely catch more than one type of > exceptions, just not you write it catch(Foo) ... catch(Bar...). You very > rarely have functions that do exactly the same with two types, and only > those. The usage is different. > > I do not think approach "it should look the same, no matter what the > usage is" is right. > > > And vice-versa. The perception revolves around the fact that both appear > > to be signatured, regardless of how they're implemented in the engine. > > But that's not what they do. Function says "I accept only parameter of > this type, and it's an error if it's not". Catch says "I will process > exception of this type, but if it's not, other catch clause may process > it". You don't chain functions like that, but you do chain catch > clauses. Again, different usage. > // concrete example // My application uses two implementation of collection pattern: // one from eloquent and one from haldayne. I have a log method that // logs value of either collection implementation and catches the same // kind of invalid collection regardless of implementation // // in this example, both union types and multi-catch are available namespace Eloquent; class Collection implements Contract\Arrayable { public static function toArray() { if (! (is_array($this->data) || is_object($this->data))) { throw new Exception\UnexpectedValue; } // .... } } namespace Haldayne; class Map implements ToArray { public static function toArray() { if (! (is_array($this->data) || is_object($this->data))) { throw new \UnexpectedValueException; } // .... } } namespace Application; function log(Eloquent\Collection | Haldayne\Map $entity) { $logger->log($entity->toArray()); } try { log(Config::find()); } catch (Eloquent\Exception\UnexpectedValue | \UnexpectedValueException $ex) { die('Configuration is neither array nor object'); } There is a pleasant symmetry in all of this. As a developer, I handle both library's concrete collection implementations similarly for both happy and unhappy paths, all using a compact expression (Class1 | Class2). The engine helps me out here. Now, imagine multi-catch passes (as I expect), but union types does not. I would change my log function to this: function log($entity) { if ($entity instanceof Eloquent\Collection | $entity instanceof Haldayne\Map) { $logger->log($entity->toArray()); } else { throw new \InvalidArgumentException; } } "Ugh, this is much easier in multi-catch. If only functions took multiple types, this would be much simpler to write." Now imagine union types pass, but multi-catch doesn't. Then I'd change my catch: try { log(Config::find()); } catch (Eloquent\Exception\UnexpectedValue $ex) { die('Configuration is neither array nor object'); } catch (\UnexpectedValueException $ex) { die('Configuration is neither array nor object'); } "ugh, this is much easier in function types. If only I could catch multiple exception types in one block." So when I'm talking about "user confusion", I'm referring to a perception of inconsistency by userland developers. And, I think we'd be well-wise to avoid designing inconsistencies. So even though I consider both union types and multi-catch to be on the rare side of utility, I consider having one and not the other a worse situation than having neither. --001a11c1d78adc52650530d66847--