Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:93387 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 37596 invoked from network); 17 May 2016 18:39:25 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 17 May 2016 18:39:25 -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.68 as permitted sender) X-PHP-List-Original-Sender: rowan.collins@gmail.com X-Host-Fingerprint: 74.125.82.68 mail-wm0-f68.google.com Received: from [74.125.82.68] ([74.125.82.68:36659] helo=mail-wm0-f68.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id E8/94-11000-C556B375 for ; Tue, 17 May 2016 14:39:25 -0400 Received: by mail-wm0-f68.google.com with SMTP id w143so6860842wmw.3 for ; Tue, 17 May 2016 11:39:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=subject:references:from:to:message-id:date:user-agent:mime-version :in-reply-to:content-transfer-encoding; bh=PveVNZ05TqWpXLpBgvZ873h3XSa2zL0dMnk0tC4eFLI=; b=IWpbhP5F+LUgeEu2l2Xjby4ybe12i/ZjQwO10x1bMduR4+UtQ75cSvHIykTVumNKKt m8Q99/Ql+25Vw9/C1d83r9huqyxp1S3QgENvH8kP3G6zBdUdPCebDfcFOCE9qkgbZG2s d/AoDjo7sJ6ATmgUVfMcogg6n4q6WSkNdOSjLIRMKuh7asZtSU1mqUJDzyj3Mi7mhXLc 6VTscHNvvIKmndjZ3svsxIWXoTBXZpSW9ZbQc+LlUCzihnel0VMYP9h8W5Hgjuh5o20z k8prBSmx7p/kH2DqAkI5Sf3JlTHEsNl0BmLl8WqBdPLSXi+2lA2Q4cyR75H5rvl+9N8V dg2A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:subject:references:from:to:message-id:date :user-agent:mime-version:in-reply-to:content-transfer-encoding; bh=PveVNZ05TqWpXLpBgvZ873h3XSa2zL0dMnk0tC4eFLI=; b=lWYUcwRI7yf8zfTRK4lFRmOwyAgkfSD7Yh4/q8BgaVhuK23vjJ4BsME7LD2JbvllRy tfXqI6xQFmoLbNlp18RdtU9gvd3uZyvmlSrBoozdu6L/5Pg7PzRGSiUu7G4oS8IDGHzX NiAonMAlL+AN/+WcrWifEdu7zC5RIUgMGdACxjauk3MuPe7YYYYSs4uLsTClyQ+7NbId BCf4NzzRKxoVHfwV9aAqxXZXojM4y+9S34uMm1OrHSu4Ys0Ej7sxC4Xe2AJA1tswQuWV PwVIyxNRvT7DH25QDDUkN/xdaxbfhxj8MU3DQLt6DOPzB1kI6A2XG2KUooEq1xfkFemC I/pA== X-Gm-Message-State: AOPr4FUkK/p98S9tbA6KvBevrIyXg6BewIHF0XsoVT6Y7NfxNHToV/xibY6HXYoLfqv+OA== X-Received: by 10.28.54.69 with SMTP id d66mr27017268wma.94.1463510362110; Tue, 17 May 2016 11:39:22 -0700 (PDT) Received: from [192.168.0.98] ([93.188.182.58]) by smtp.gmail.com with ESMTPSA id m20sm4945916wma.23.2016.05.17.11.39.20 for (version=TLSv1/SSLv3 cipher=OTHER); Tue, 17 May 2016 11:39:21 -0700 (PDT) References: <61e6a083-91c2-799f-9757-02f56fe184e9@gmail.com> To: PHP internals Message-ID: <5fa12e6f-476f-b0e5-b4e3-ea3c7dc1925d@gmail.com> Date: Tue, 17 May 2016 19:37:24 +0100 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:45.0) Gecko/20100101 Thunderbird/45.1.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Subject: Re: [PHP-DEV] [RFC] Simple Annotations From: rowan.collins@gmail.com (Rowan Collins) On 17/05/2016 18:47, Rasmus Schultz wrote: >> I don't really understand what closures have to do with annotations, or how that relates to capturing context. > > The point is that, rather than trying to capture context, you can just > as well ask for what you need. > > I'm going to use a very contrived example, because I really can't > think of any real case that requires context: > > class User > { > << new Validation(function ($value) { return false !== > filter_var($value, FILTER_VALIDATE_EMAIL); }) >> > public $email; > } > > Like I said, extremely contrived - in practice, you wouldn't need to > attach functionality in that way. Right, in my mind this is less about *context*, and more about *passing code into the implementation*. I think we agree that an implementation of validation-by-annotation would look something like: $validators = $reflected_thing->getAnnotations('someFilter'); foreach ( $validators as $validator ) { $validator->validate($some_instance); } This gets its *context* from the code running the validator; the implementation of the validate() method would normally just be part of the annotation type: <> var $foo; The closure example you gave would be a way of providing on-the-fly dynamic *behaviour* as the argument to an annotation. This wouldn't really make sense for validation (a custom validator would still probably be defined once and used for several fields, but theoretically you could have: <> It's not the context that's magic here, it's the ability to specify code as part of the annotation *value*, rather than the annotation *definition*. A more obvious example therefore is using annotations to implement DbC: <> Although as I admitted to Guilherme, that requires some magic to run it at the right time anyway... >> An example from the other thread of a context-bound annotation would be implementing validation like this > > You're not annotating the function - this is just a round-about way of > annotating the argument. > > You would do that directly, like this: > > function foo( > << ValidateRange(0, 100) >> > int $percentage > ) { ... } Sure, but it's easy to come up with a variant that requires access to more than one parameter, say: << ValidateLessThan($min, $max) >> function foo($min, $max) Which without any context or AST would need to be either: << ValidateLessThan('$min', '$max') >> function foo($min, $max) ...which rather defeats the point of having code rather than just a string. Or: << ValidateCustom(function($min, $max) { return $min < $max } >> function foo($min, $max) ...which feels rather clunky. >> If the expression would have to be made up entirely of constants anyway, might the same "constant expressions" used in class const definitions be a better fit than "any valid PHP expression" - plus a specific exception for creating objects out of those constant expressions. > > Probably not - what happens with what is today "nested annotations" > then? Or will you make an exception for those too? How would you "nest" annotations in your scheme anyway? As far as I can see, they would be either multi-level arrays (a valid constant expression) or nested constructor calls. So there's still exactly one exception made, the "new Foo(args)" construct. > The problem is, you're just reinventing a subset of the programming > language, and I'm sure you can keep expanding on that indefinitely. > What for? Just use the facilities already defined by the language. That's a fair point. The flipside is that the more things you allow the user to do, the more edge cases you have to deal with when evaluating the expressions in your special "zero context". > This fear of any feature that lets you do "evil" is incomprehensible > to me. Most features of almost any programming language can be used > for "evil". I am not suggesting removing the ability to avoid people doing evil; I'm suggesting that the feature you call "simple annotations" could be a lot simpler. What is the value of being able to write this: function foo() { return 'MyAnnotation'; } << foo() >> class A {} When you could just write this: << 'MyAnnotation' >> > IMO, the real question is whether a feature accomplishes > what you want. If you insist on something that also prevents things > you don't want, you're bound to end up with something a lot more > complex that fits into the language a lot less naturally... In my mind, something that lets me evaluate an arbitrary expression in some weird null-context, at an unspecified time (because I don't know what code will be the first to request that annotation), only to have the result stored in some invisible static variable, is *more* complex than many of the alternatives. Regards, -- Rowan Collins [IMSoP]