php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #79079 Opt-in strict [and/or custom] comparison for switch/case
Submitted: 2020-01-08 11:09 UTC Modified: 2020-01-08 20:58 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:1 (100.0%)
From: phpuser at yopmail dot com Assigned: cmb (profile)
Status: Duplicate Package: Scripting Engine problem
PHP Version: Next Minor Version OS:
Private report: No CVE-ID: None
 [2020-01-08 11:09 UTC] phpuser at yopmail dot com
Description:
------------
First, switch/case compares values using *loose* equality (==) which causes issues with null, 0, "" etc. and requires ugly hacks, for instance: https://github.com/doctrine/orm/commit/a9bca86d4d06557b8159b82b2de0b6f678c9dffd

I almost always want *strict* equality (===).

Idea of syntax (related to the second idea below):

    switch ( EXPR ) using strict_equality { CASES }

(note: that syntax is open to debate, but in any case I would *not* want a declare()).


Second (but far less important), sometimes I would like to use a switch/case with a custom comparison (instead of equality).

Idea of syntax (related to the first idea above):

    switch ( EXPR ) using ( BINARY_PREDICATE ) { CASES }

Examples:

    switch (getSomeString()) using ('str_starts_with') {
        case 'foo_':
        case 'bar_':
            /* starts with "foo_" or "bar_" */
            break;
        case 'qux_2_':
            /* starts with "qux_2_" */
            // no break
        case 'qux_':
            /* starts with "qux_" */
            break;
        default:
            /* doesn't start with any of the above */
    }

    switch (getSomeString()) using (fn($value, $case) => (bool) preg_match($case, $value)) {
        case '/^(0|-?[1-9]\d*)$/D':
            /* ... */
            break;
        case '/^[[:xdigit:]]{2}$/D':
            /* ... */
            break;
        // ...
    }

    switch (getSomeInt()) using (fn($value, $case) => $value >= $case) {
        case 50:
            /* >= 50 (i.e. in range(50, \PHP_INT_MAX)) */
            break;
        case 10:
            /* in range(10, 49) */
            break;
        case 0:
            /* in range(0, 9) */
            break;
        default:
            /* < 0 (i.e. in range(\PHP_INT_MIN, -1)) */
    }

And as a bonus, it would be even nicer if it could handle specifying built-in comparison operators directly like e.g. "using (>=)" (or maybe "using >="), in which case maybe "using strict_equality" wouldn't be needed.

But again, let's not let extra wishes hinder the most wanted: strict switch.


Thoughts?


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2020-01-08 11:20 UTC] cmb@php.net
-Status: Open +Status: Duplicate -Package: PHP Language Specification +Package: Scripting Engine problem -Assigned To: +Assigned To: cmb
 [2020-01-08 11:20 UTC] cmb@php.net
That looks like a duplicate of bug #70440.
 [2020-01-08 20:10 UTC] phpuser at yopmail dot com
@cmb: The linked request (whose syntax is swapped and example buggy, btw) had been created more than 4 years ago, and was suspended more than 2 years ago (on the motive that it would need an RFC, but given how proposals from outsiders are generally "welcomed" on internals, I'm not very surprised that nobody has tried since then)... so what now?
 [2020-01-08 20:58 UTC] requinix@php.net
The idea isn't dead, we're just marking it here on this bug tracker as a duplicate - meaning there is something here on the tracker that addresses the issue. And the age of it really isn't that important.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 14:01:32 2024 UTC