Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:105356 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 89442 invoked from network); 23 Apr 2019 15:32:31 -0000 Received: from unknown (HELO mail-it1-f194.google.com) (209.85.166.194) by pb1.pair.com with SMTP; 23 Apr 2019 15:32:31 -0000 Received: by mail-it1-f194.google.com with SMTP id a190so23094126ite.4 for ; Tue, 23 Apr 2019 05:32:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=Uzw1/x5hMSxb4sA3/+4Xp5PmsgGpv+wEpOLPk0DD/Po=; b=Rbkn4Of2HOr4R6WQYWG8rmWRPYtlFwzs7C8Wf6sAIGy71NSR4xj9I/X6vyScVwwfVi Zb0kCT8jssONJFnXiCfpgcI4L7noS5jT4B/1emZsnouRtaXtnVcJ/hRQVN4KjElILOCO s64d0kCVTsbnBI75koLMahp50HlVbKjw7BPNcYxhd09x//NuNgQhmVRKfFEBI/uQ2gTW Rda5X1rhWuwOpqBpoZZUyVFLf3bCzxH6ye54fJKidMEj3rlHGKr6ZhAUr/UQoguI0Nq9 ft5mgAt3VFxNFiamc6UElFipdecBxrPbTfX2+39rSU5JH9zqm6evjUVwFg2euv75YFzZ Iecg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=Uzw1/x5hMSxb4sA3/+4Xp5PmsgGpv+wEpOLPk0DD/Po=; b=HpbHBzNpdjw77n8EyTmYmmtmfUsXPIyrAknEq0lx64m0q8YQkwV2fld5sPT2axr00u KK9D73mNpp0t1NAKEBsDf7/vxNVbb4A5+i9/QC2NnirzIyzHSwLSFHAH/Eu/OcNqQbSZ fbAMEbgw9LFBdKIIchPiTXPnMaStfFGd4ALoF2Cyu/pUlmswGCtltcGGhz1izNChW4hx 4aq/NDHO5uT/N8lWwUpYzAWVu82bMfq3p/FhbsmKeWgqxPYs4axrCiFxofFy4PgY34Iv RLNVLMvgHIVUH4OwaOKFNN0Vq0OjpyGtTrwVGRm8YGxQsNA9WKNphzdrZyWoeaDfzhky Navg== X-Gm-Message-State: APjAAAUET+vK8b92ZHCNu2B6ifH3bD+Ao2f/UCt/QsjoREmgh5SuHzTk QrxzzrDmPUW7sKE9dAiWuK4cw9BKxwedZlSWcwk= X-Google-Smtp-Source: APXvYqwb8yNL9eN0LDsfduDyiCK/3oHAMMomsaoGUIhREDh8nSkglPw80hnhpLuGPUPWR3SMtXLKaP+uRB+PhADI9io= X-Received: by 2002:a05:660c:12ce:: with SMTP id k14mr1758623itd.23.1556022774523; Tue, 23 Apr 2019 05:32:54 -0700 (PDT) MIME-Version: 1.0 References: <9fee0f79-a77d-c0f1-ec24-efa4dd587f91@hristov.com> In-Reply-To: <9fee0f79-a77d-c0f1-ec24-efa4dd587f91@hristov.com> Date: Tue, 23 Apr 2019 14:32:42 +0200 Message-ID: To: Andrey Hristov , Nikita Popov , Stephen Reay , Dan Ackroyd Cc: azjezz , PHP Internals Content-Type: multipart/alternative; boundary="000000000000bcec82058731c889" Subject: Re: [PHP-DEV] Object Type Casting Reloaded From: benjamin.morel@gmail.com (Benjamin Morel) --000000000000bcec82058731c889 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable @Nikita Popov > It's not possible to use (ClassName) as a cast syntax, because it is ambiguous. Aw. I did not think about a possible conflict here, thanks for bringing this up! @Stephen Reay > My objection to `as` is that it specifically prevents (or makes very confusing) the `foreach` use I mentioned. There=E2=80=99s no variables invo= lved in imports/traits, and neither of those relates to foreach. I'm sorry, I still don't understand what the issue with foreach is? As I said before, the proposed syntax does not aim to be used inside the foreach () parentheses, but rather as an explicit declaration inside the foreach {} block. > As for the `string $foo =3D $bar->getFoo();` =E2=80=98looking strongly ty= ped=E2=80=99 and wondering if it will allow re-declaration - do you think the same when you see `function (string $foo) { $foo =3D explode(=E2=80=98 =E2=80=98, $foo); = }` ? Functions have allowed type hints since 5.0 - nearly 15 years ago, and nobody seems to be confused if those variables can be redeclared. Whether you *should* redeclare them to a different value is something you need to decide for yourself. You have a point. I can't say why, but outside of the function declaration, it looks more like a static typing to me (and someone else had the same gut reaction earlier in this thread). I may just be plain wrong. > As for limiting this to class/interface names - why would you do that? It took YEARS to get scalar type hints for function parameters, why would you not include them from the start on anything new that pertains to essentially the same functionality? I'm definitely not against supporting other types, it's just that the original syntax I had in mind was using () casting, which was already covered for other types. Now if people like Hack's `as` syntax, it would probably make sense to generalize it indeed. @Dan Ackroyd > Similar to the nullable casting idea, you're taking a problem caused > by your own code/framework, and then thinking it should be solved in > core, when a simple solution is available in user-land. > ... > btw I'm sure you're already aware of it, but this is using a > 'dependency injector' as a service locator. If your current DI library > isn't powerful enough for you, rather than abusing it like this, I think that the sudden focus on the specific case of DI container / service locator reveals a misunderstanding here. The example I chose is obviously responsible for that and this choice was perhaps infortunate: it didn't help convey the true meaning of the proposal. As I said earlier, I'm a heavy user of Dependency Injection AND Inversion of Control; my framework does not suffer from any such limitation: my controllers' and services' dependencies are explicitly declared and injected automatically, and no such code relies on fetching dependencies from the container directly. These classes are not even aware of the existence of the container, and not tied to the DI framework in any way. Also, my repositories are full blown, and encapsulate the ORM to return specific entities. YET, I also do some quick prototypes or CLI scripts that would not benefit from too much boilerplate, and may use the DI container or the ORM's entity manager directly. I also get objects from various losely typed data sources (functions returning mixed types, arrays, iterators of all sorts, etc.) that I expect to be of a given type, and that would benefit from the added *readability, type checking and static analysis capabilities* the current proposal offers= . @Andrey Hristov > this is easily solvable with the following (considering strict_types is enabled) > function tostr(string $in) : string { return $in; } This solves it for a single type, but you have to write a function for every class you want to enforce: function toEmailService(EmailService $service) : EmailService { return $service; } function toUser(User $user) : User { return $user; } As you can see, this gets ugly real quick. Your IDE and/or static analysis tool will also probably warn about "Expecting Foo, got mixed", whereas with an explicit cast/enforced-type-hint, the tooling would know that you're explicitly stating that this unknown typed value is an instance of Foo. - Ben On Tue, 23 Apr 2019 at 12:52, Andrey Hristov wrote: > Hi, > On 23.04.19 =D0=B3. 13:44 =D1=87., azjezz wrote: > > Hello Dan, > > > > I don' think this a problem relating to just one use case, some PHP > builtin functions have weird union return types, where static analysis > tools would warn you about the return type being `string|bool`, when you > are expecting `string`. > > > > using type constrain : > > ``` > > $foo =3D substr($foo, 1, 3) as string; > > // there's no need to check if `$foo` is false here. > > ``` > > this is easily solvable with the following (considering strict_types is > enabled) > > function tostr(string $in) : string { return $in; } > > $foo =3D tostr($foo); > > Put it in a convenience namespace and that's it. > > Cheers, > Andrey > > > > > > > Cheers, > > > > - Saif > > > > > > Sent with ProtonMail Secure Email. > > > > =E2=80=90=E2=80=90=E2=80=90=E2=80=90=E2=80=90=E2=80=90=E2=80=90 Origina= l Message =E2=80=90=E2=80=90=E2=80=90=E2=80=90=E2=80=90=E2=80=90=E2=80=90 > > On Tuesday, April 23, 2019 11:33 AM, Dan Ackroyd > wrote: > > > >> HI Benjamin, > >> > >> Similar to the nullable casting idea, you're taking a problem caused > >> by your own code/framework, and then thinking it should be solved in > >> core, when a simple solution is available in user-land. > >> > >> If you changed what you currently have: > >> > >> $service =3D $diContainer->get('email.service'); > >> > >> to also take the expected class: > >> > >> $service =3D $diContainer->get('email.service', EmailService::class); > >> > >> And then check inside your 'DI container' whether the expected type is > >> returned, this solves the problem without needing new syntax. > >> > >> btw I'm sure you're already aware of it, but this is using a > >> 'dependency injector' as a service locator. If your current DI library > >> isn't powerful enough for you, rather than abusing it like this, I'd > >> recommend looking at a different one, like > >> https://github.com/rdlowrey/Auryn > >> > >> Also, similar: > >> > >>> By the way, this RFC is a special case of something that could be far > >>> more generic. If it was possible to register callbacks to be used whe= n > >>> casting, ... > >> > >> Apparently this might not be possible as it's ambiguous....which is a > shame. > >> > >> cheers > >> Dan > >> Ack > >> > >> On Mon, 22 Apr 2019 at 22:47, Benjamin Morel benjamin.morel@gmail.com > wrote: > >> > >>> Hi internals, > >>> I'd like to revive an old discussion > https://externals.io/message/67131 about > >>> object type casting. > >>> The idea would be to allow (ClassName) casting: > >>> > >>> $service =3D (EmailService) $diContainer->get('email.service'); > >>> > >>> > >>> The above code would throw a TypeError if the value is not an instanc= e > of > >>> the given class. I see the following advantages: > >>> > >>> - Type safety: we can be sure that the value is of the correct type > or that > >>> we'll get an Error. This syntax allows to fail early if the > variable > >>> happens to not be of the expected type, and avoids much more > verbose checks; > >>> > >>> - Static analysis: IDEs and static code analysis tools can now > understand > >>> the type of the variable, without having to resort to `@var` > annotations. > >>> > >>> > >>> These combine into a third advantage: readability. Today's equivalent > of > >>> the above one-liner could be: > >>> > >>> /** @var EmailService $service */ > >>> $service =3D $diContainer->get('email.service'); > >>> if (! $service instanceof EmailService) { > >>> throw new TypeError('Expected instance of EmailService, ...'= ); > >>> } > >>> > >>> > >>> Which is a lot of boilerplate code that could be easily avoided by > >>> introducing this new syntax. > >>> Before moving forward and working on a formal RFC, I'd like to hear > your > >>> thoughts: what's your early feeling about this? Did I miss other > >>> discussions around this subject? Are there any technical issues that > come > >>> to mind? Could this feature help the upcoming JIT compiler produce mo= re > >>> efficient machine code by knowing the type of the variable at compile > time? > >>> etc. > >>> Note: "casting" might not be the perfect name here as what we're real= ly > >>> doing is a type check, but this reuses the type casting syntax and > >>> resembles Java's object casting. > >>> Thank you, > >>> Ben > >> > >> -- > >> > >> PHP Internals - PHP Runtime Development Mailing List > >> To unsubscribe, visit: http://www.php.net/unsub.php > > > > > > > > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > > --000000000000bcec82058731c889--