简体   繁体   中英

How to type-infer PHP-functions with optional arguments

The thing with PHP is that it doesn't have a specific syntax when using a function with optional arguments. This:

foo(10);

can either be this

function foo($a) {}

or this

function foo($a = 0) {}

or this

function foo($a, $b = 0, ...) {}

(or even function foo() {} , but disregard that for now).

So how do we type-infer it when a function is used before it's defined?

One solution is to record all usages until the definition comes, and then see if they all can unify with it. The example above would then store

int -> unit

and later check if it's compatible with

int -> (typ list) -> unit

or whatever (where typ list is the list of optional arguments).

You think this could work? Are there other conventional ways to deal with this?

I don't know to what degree this answers your question, but to elaborate on my comment above you could use PHP's built-in suite of reflection classes to help introspect and derive useful information about functions and their arguments.

Specifically, I think ReflectionFunction and ReflectionParameter could be useful in your case, although there is much more functionality that might help.

For example, here is a very simple example where you want to get some information about a function's arguments:

<?php

// a simple function with an
// optional/default argument
function foo($a, $b = 0)
{
    return $a + $b;
}

// create a ReflectionFunction object
// passing the name of the function name.
// you can also pass a variable reference 
// to an anonymous function.
$refl = new ReflectionFunction('foo');

// iterate over the ReflectionFunction's
// parameter list to get a ReflectionParameter
// object for each of foo's arguments. here we're 
// just printing out a __toString() summary of each
// argument.
foreach ($refl->getParameters() as $param) {
    echo $param . PHP_EOL;
}

Yields:

Parameter #0 [ <required> $a ]
Parameter #1 [ <optional> $b = 0 ]

As you can see, this simple example shows some information about foo 's argument list: param number, required/optional, var name and default value.

$param is an instance of ReflectionParameter so there is a bunch of methods you can call on that to get more information about each argument, including:

export
__construct
__toString
getName
isPassedByReference
canBePassedByValue
getDeclaringFunction
getDeclaringClass
getClass
isArray
isCallable
allowsNull
getPosition
isOptional
isDefaultValueAvailable
getDefaultValue
isDefaultValueConstant
getDefaultValueConstantName

Hope this helps! :)

您可能必须插入“弱”类型变量并保留它们,直到找到函数定义为止,或者首先构建完整的AST,然后通过类型推断对其进行运行,如果存在定义不明的函数,则会引发错误(我想知道您如何处理内置函数,也许使用预烘焙的类型签名数据库?)。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM