Skip to content

Instantly share code, notes, and snippets.

@marcioAlmada
Last active August 29, 2015 14:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save marcioAlmada/a4b30704ee6c95ad4bd7 to your computer and use it in GitHub Desktop.
Save marcioAlmada/a4b30704ee6c95ad4bd7 to your computer and use it in GitHub Desktop.
My RFC To Do Wishlist For PHP 7.1

My RFCs To Do Wishlist For PHP 7.1

  • Blank identifier pre draft
  • Context Sensitive Lexer II link
  • Function types pre draft
  • Remove ancient default pharstub that grosses me out yuck
  • Multiple return values MAYBE
  • [ ]
  • TOP SECRET

Blank Identifier

It's a special identifier used to discards values without cost on function declarations or variable assignments. It can be particularly useful when a variable place-holder is needed but the actual value is irrelevant.

Practical Examples

On Declarations

Sometimes we build interfaces to fit a context but a subtype of that given interface doesn't need all that is provided:

interface Validator {
   public function isValid($value, $context=null) : boolean;
}

class Csrf implements Validator {
   public function isValid($value, $context=null) : boolean {
       //...
   }
}

class BarCode implements Validator {
   public function isValid($value, $) : boolean {
       //...
   }
}

Without the blank identifier, the ''BarCode'' implementation would be like:

class BarCode implements Validator {
   public function isValid($value, $ignored) : boolean {
       //...
   }
}

On Assignments

Sometimes it's needed to discard a given value during assignment but a temporary variable becomes required. With the blank identifier this becomes more explicit:

// without blank identifier
list($a, $temp, $c) = ['relevant', 'useless', 'relevant'];

// with blank identifier
list($a, $, $c) = ['relevant', 'useless', 'relevant'];

Type Hintings

Sometimes it makes sense to typehint a blank identifiers on ''function|method'' argument list declarations. The following code is valid and the typehints are functional:

interface Watcher {
    public function __construct(Resource $resource, $event);
}

class WatcherMock {
    public function __construct(Resource $, $) {
        //...
    }
}

new WatcherMock(new NotResource, 'delete'); // !

// PHP error:  Argument 1 passed to WatcherMock::__construct must be an instance of Resource, NotResource given...

Blank identifier candidates:

In your opinion, What's the bestest blank identifier evah? :3

  • $ (nameless variable)
  • $__ (bc compatible version of nameless variable)
  • @ (black hole identifier)

=> We can't use _ or __ because it's a valid constant name

Open issues

Should variadic blank identifiers be allowed?

function log(Log $log, $message, ...$) {}

Context Sensitive Lexer II

It's just Context sensitive lexer but this time with support for namespaces, classes, traits, and interfaces names.

I got quite frustrated for not making it for PHP 7.0 so I decided to work on this for PHP 7.1

There are some hypothesis floating around on my head on how to do it in an great way, different from the bare bones implementation of the previous RFC, but they need real experiments.

Maybe I'll try to find a collaborator for this one.

Function Types | Callable Types

Because people can typehint their bloated classes but functional people cant typehint their callbacks. Not everybody on PHP world is a platonic Java lover, we want functions to be first class too.

This would allow people to define more specific requirements for a callable on ''method|function'' declarations through type hints. This is how you define a callable type:

function reducer(array $numbers) : int;

This is how you typehint the declared callable:

function reduce(array $numbers, reducer $reducer) {
    return $reducer($numbers);
} 

Complete example:

namespace some\lib;

function reducer(array $numbers) : int;

function reduce(array $numbers, reducer $reducer) {
     return $reducer($numbers);
} 
namespace userland\code;

// Ok
some\lib\reduce([1, 2, 3, 4], 'array_product');

// Ok
some\lib\reduce([1, 2, 3, 4], 'array_sum');

// Ok
some\lib\reduce([1, 2, 3, 4], function(array $numbers) :int {
    $result = 0;
    foreach($numbers as $number) $result = // some expression
    return $result;
});

// fails because array merge returns an array
// and does not satisfies reducer interface
some\lib\reduce([1, 2, 3, 4], 'array_merge');

// fails because the given callable returns a string
// and does not satisfies reducer interface
some\lib\reduce([1, 2, 3, 4], function(array $numbers) :string {
     return implode($numbers, ",");
}); 

I don't know how to baptize this for PHP yet. On other languages we just call it a type and go home. But PHP type system is 💩 💩 💩 no matter how people tried to fix it. I'm afraid calling it "function types" is not clear clear enough.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment