"Interpreter self-nikic" PHP native Type method

Source: Internet
Author: User
Tags anthony ferrara mathematical functions nikic string methods
The method of "translating from Nikic to great God" php native type

Introduction

For the first time, the translation of other people's articles, with level four English translation ~ ~ Embarrassed, there may be a lot of inappropriate places, despite making bricks (some places really can't think of the right translation, I also posted the original text and their very low translation).

This article used me 3 nights a Noon ~, first to understand the technical generally say what, and then in the translation of ~

The purpose of doing this is to exercise their own English, on the one hand to learn some of the foreign more new technical ideas.

This article mainly discusses the native type of PHP to implement object-oriented operation, through the extension of the implementation, to solve the PHP function naming is not standardized, parameter order is not standardized, the problem of low readability.

The implementation of the extension is implemented by changing the corresponding handler function that invokes the object-oriented method in the Zend engine, registering a function, judging the type of the object-oriented caller, or, if is_string, continuing the custom processing, or returning the Zend default handler to see the following explanation

hookphp Code

PHP is an interpreted language, and the code is translated into intermediate bytecode by the Zend engine parsing execution. PHP calls the intermediate bytecode opcode, and each opcode corresponds to a handler function Zend the underlying, and the Zend engine eventually executes the handler. The hook function can only be changed by changing the corresponding processing function of the hook opcode.

An object-oriented approach to PHP native type

A few days ago, Anthony Ferrara wrote some ideas about the future of PHP. I agree with most of his views, but not all of them. This article focuses on a particular aspect: to disguise native types such as strings and arrays as "pseudo-objects", you can execute method calls on those native types.

Let's start with a few examples to see why we need "pseudo-objects":

$str = "test foo bar";$str->length();      // == strlen($str)        == 12$str->indexOf("foo") // == strpos($str, "foo") == 5$str->split(" ")     // == explode(" ", $str)  == ["test", "foo", "bar"]$str->slice(4, 3)    // == substr($str, 4, 3)  == "foo"$array = ["test", "foo", "bar"];$array->length()       // == count($array)             == 3$array->join(" ")      // == implode(" ", $array)      == "test foo bar"$array->slice(1, 2)    // == array_slice($array, 1, 2) == ["foo", "bar"]$array->flip()         // == array_flip($array)        == ["test" => 0, "foo" => 1, "bar" => 2]

Here $str is just an ordinary string, $array just an ordinary array--they are not objects. All we did was give them a bit more of an object-like feature, so they could invoke the method.

Note that the above features are not unreachable, but now exist. PHP extension scalar_objects allows you to define an object-oriented approach on the native PHP type.

The introduction of native types to object-style invocation methods also brings many benefits, which I'll list below:

A chance to make the API even more concise

The most common complaints about PHP that are heard most often are inconsistencies in the functions in the standard library, unclear naming, and inconsistent, chaotic parameters. Some typical examples are:

//不同的函数命名约定strposstr_replace//很不清晰的命名strcspnstrpbrk//颠倒的参数顺序strpos($haystack, $needle)array_search($needle, $haystack)

However, these problems are often overemphasized (we have an integrated development environment) and it is difficult to negate the situation or be quite good. It should also be pointed out that many of the functions show problems far more than the strange name of the problem. Usually the behavior of the edge condition is not fully considered, so there is a need for special handling of them in the calling code. (For string functions, the edge condition typically includes an empty string or an offset beyond the string range.) )

A general recommendation is to implement a large number of aliases in PHP6 to unify the function name and parameter order. So we're going to string\pos() have string\reoplace() , string\complement_span() or something like that. Personally (and this seems like a lot of advice to many PHP-SRC developers) This is very small for me. The names of these functions are now deeply rooted in the memory of the PHP programmer, and it does not seem worthwhile to implement some unimportant cosmetic changes to them.

The introduction of native type Object-oriented APIs also provides an opportunity to redesign the API (original: The introduction of an OO API for primitive types on the other hand offers an opport Unity of an API redesign as a side effect of switching to a new paradigm). This is also true to let us start from scratch, without having to consider the expected output of the old API. Two examples:

    • I would very much like to have $string->split($delimiter) and $array->join($delimiter) such a method, these are function functions are universally accepted names (with explode and implode different). On the other hand, if there is a string\split($delimiter) way to behave like this I would feel very disgusted because the existing str_split functions are doing a completely different (grouping).
    • I take it for granted that the new API for error reporting uses exceptions, since this is an object-oriented API, which is automatically given, and the exception is of course used with the renamed API, but this violates the usual practice of using warnings for error handling by all program functions, which is not immutable. But this is really a point of contention that I want to avoid:)

This is my main motivation for implementing native type Object-oriented APIs: from scratch, allow us to implement a reasonable set of API designs. Of course, all the benefits of this change are not known. Object-oriented syntax provides a number of deeper benefits, which are discussed below.

Improved readability

Program-type calls are generally not chained. Consider the following example:

$output = array_map(function($value) {    return $value * 42;}, array_filter($input, function($value) {    return $value > 10;});

At first glance, which is arraay_map and what is array_filter the use of each? (Original: What is Array_map and Array_filter applied to?) What is the order in which they are called? The variables are $input hidden between two closures, and the order of the functions is the opposite of the order in which they were actually called. Now the same example uses object-oriented syntax:

$output = $input->filter(function($value){return $value > 10;})->map(function($value){return $value * 42;});

I dare say this way, the Order of operations (first filter in map ) and the initial input array are $input more pronounced.

This example is obvious to someone for piecing together the feeling, because array_map and array_filter is another example of the order of the function parameters (which is why the input array is in the middle). Another example of an input parameter in the same position (from the actual code):

substr(strstr(rtrim($className, '-'), '\\', '_'), 15);

In this example, the last is a series of additional parameters '_'), '\\', '_'), 15, , which makes it difficult to match these parameters with the applied functions. Compare this to the version using the object-oriented approach:

$className->trimRight('_')->replace('\\', '_')->slice(15);

This function is closely associated with their parameters, and the invocation of the method matches the order in which they were executed.

Another benefit from the readability of this syntax is the needle/haystack unclear problem. Aliases by introducing a uniform parameter order specification Let's solve this problem, the problem of using object-oriented API is basically nonexistent.

$string->contains($otherString);$string->contains($someValue);$string->indexOf($otherString);$string->indexOf($someValue);

The confusion over which part of the rule is applied is no longer there.

Polymorphic

PHP now has an Contable interface that can implement custom output functions through the class count($obj) . Why do you need this? Because our PHP functions are not polymorphic. However, we do need polymorphism in our approach:

If an array $array->count() is implemented as a method, the code actually does not care if it is $array an array, and he can be an object of any other type of implementation count() method, which basically gives us Countable all the behavior, ~ (Original: This basically gives us The same behavior as countable, just without the engine hackery it requires.)

This is also a very common solution. For example, you can implement a class that implements all of the string type methods UnicodeString , and then you can use the normal string and UnicodeStrings . Well, at least it's still a theory. This is obviously limited to the use of the string method, and it returns an error when the Cascade operation is invoked (original: this would obviously only working as long as the usage is limited to just the string me Thods, and would fail once the concatenation operator is employed) (operator overloading currently only supports classes in the kernel).

I still have a strong belief in the hope that this will be clear, the same applies to arrays and so on. By inheriting the same interface, you can have an array that behaves the same way SplFixedArray . (Original: You could a splfixedarray behave the same as an array, by implementing the same interface.)

Now that we've summed up some of the benefits of this approach, let's take a look at its problems:

Loosely-typed

Excerpts from Anthony's blog:

Scalars are not objects, but more importantly they are not of any kind. PHP relies on a type system, where strings and numbers are the same. Many of the flexibility in the system can be easily converted to other scalars based on any scalar.

More importantly, because of the loosely typed system, you cannot know at any time which type of a variable is. You can say what type you want him to be, but you don't know what type is inside of him. Even with casting or scalar type hinting it isn ' t a perfect situation since there is cases where types can still change.

To illustrate this problem, consider the following example:

$num = 123456789;$sumOfDigits = array_sum(str_split($num));

This $num is used as a string number, which is str_split sliced and array_sum summed. Now try the object-oriented method call with the same effect:

$num = 123456789;$sumOfDigits = $num->chunk()->sum();

The method of the string here cheunk() is called by a number. What will happen?? Anthony recommends this solution:

This means that all scalar operations will necessarily require the corresponding scalar type. This will result in the need for a scalar with all the mathematical methods of the object model, of course including all the string methods. It's a nightmare.

As stated in the introduction, this is by no means an acceptable solution. But I think we can get away with it. Just throw a bug in that situation (exception!). )。 To explain why this approach is possible, let's look at what types PHP can have.

Native Types in PHP

In addition to objects, PHP has the following variable types:

nullboolintfloatstringarrayresource

Now, let's consider which of the above is going to require an object-oriented approach: Let's first remove resource it and then look at the rest. nulland bool obviously don't need an object-oriented approach unless you want to make a $bool->invert() boring conversion like this.

The vast majority of mathematical functions are not suitable for using object-oriented methods. Consider some of the following examples:

log($n)$n->log()sqrt($n)$n->sqrt()acosh($n)$n->acosh()

I think you'll agree that the readability of mathematical functions is better than the form of function notation. Of course there are a few object-oriented approaches you can use to properly apply numeric types, such as $num->format(10) reading them quite well. However, here, for an object-oriented digital API is not really needed, only a small number of functions you may need. (Moreover, the current mathematical API does not have a lot of problems with naming, and the mathematical operation is related to naming the equivalent standard.) )

There are only strings and arrays left for us now, and we've seen a lot of great APIs for both types. But what do we have to do about the loose type problem? Here are the important points:

We routinely treat strings as numbers (for example, from HTTP or DB), which in turn is not right: it is very rare to use numbers directly as strings. For a chestnut, the following code will confuse us:

strpos(54321, 32, 1);

It's a weird operation to think of numbers as strings, and that's OK, just a cast once. Examples of using the original summation numbers:

$num = 123456789;$sumOfDigits = ((string) $num)->chunk()->sum();

Now we get it, yes, we do want to think of numbers as strings. It is acceptable for me to deal with this technique in such a way that it can be used in this way.

It's even easier for an array: he's not going to show up. An array operation is treated as an operation other than an array type.

On the other hand, this problem can be improved by scalar type hints (I fully agree that all versions of PHP are present – The most embarrassing problem is that it is still not present (original: which I totally assume to being present in any PHP version this GE TS In-really embarrassing that we still don ' t has them)). If the inner type hints string , you get the input string will be a string (even if passed to the function is not-depending on the type hint implementation of the specific content).

Of course, I'm not suggesting there's no problem here. Because of the wrong function design, it is sometimes possible for unknown types to sneak into the code, for example substr($str, strlen($str)) to be smart to return bool(false) instead of string(0) "" . (However, this problem only substr exists.) The object-oriented API doesn't have that problem, so you can't touch that problem. )

Object transitive semantics

In addition to the problem of type, there is a semantic problem with native type pseudo-Methods: The object in PHP has different transitive semantics than other types (to some extent, similar to references). If we allow strings and arrays to make object-oriented method calls, they will look like objects, so some people might expect them to have object-passing semantics as arguments. This problem exists in both strings and arrays:

function change($arg) {echo $arg->length();//$arg looks like object$arg[0] = 'x';//但是没有对象的传递语义}$str = 'foo';change($str);//$str stays the same$array = ['foo', 'o', 'o'];change($array);//$array stays the same

We will of course change the transitive semantics. First of all, it seems to me that passing through the value of a large data structure like an array is a fairly low idea, and I prefer them to pass as objects. However, that would be a pretty big breakthrough backwards compatibility, and that wouldn't be easy to automatically refactor (original: However, that would is a pretty big backwards-compatibility break and one that's not Easy to refactor automatically) (at least I guess so.) I didn't do an experiment to explore the actual impact of such a change. On the other hand, it would be a disaster for a string to pass the argument through the object, unless we let the string be completely immutable at the same time, discarding all the current variability of local variables (I personally find it very easy-to try to change one byte of a python string).

I don't know if there is a good way to solve this expected problem, except that the emphasis on strings and arrays in our documentation is only considered "pseudo-image" in the object-oriented approach, not a real object.

This problem can be extended to other object-related features. For example you will be asked $string instanceof string if it is correct like this. I'm not sure what the whole thing is going to be. It may be better to stick strictly to the object-oriented approach, and then emphasize that they are not real objects. However, it may be better to support the deeper features of the object-oriented system. This view should be further considered.

The current state

In a word, there are many problems with this approach, but I don't think they are particularly important. At the same time, this provides a good opportunity to introduce simple and straightforward APIs for our basic types, improving the readability (writeable) of the code when it performs its operations.

So what is the current state of the idea? From what I've collected, people in the interior are not particularly opposed to this approach, but prefer to rename all functions. The main reason for not advancing this is the API offer ~

For this purpose, I created the scalar_objects extension, which was implemented as a PHP extension. It allows you to register a class that handles the method invocation of the respective native type. See an example:

class StringHandler {public function length(){return strlen($this);}public function contains($str){return false !== strpos($this, $str);}}register_primitive_type_handler('string', 'StringHandler');$str = 'foo bar baz';var_dump($str->legth());//int(11)var_dump($str->contains('bar'));//bool(true)var_dump($str->contains('hello'));//bool(false)

Not long ago, I started a string handler that included an API description of the work, but had never really completed which project (I hope I soon found something to start his motives again). There are, of course, many other projects that are working to achieve such APIs.

Well, that's one of the improvements I'd like to see in PHP6. I might write another article about my plan for that direction.

Reference

Original link: http://nikic.github.io/2014/03/14/Methods-on-primitive-types-in-PHP.html

Hookphp:http://netsecurity.51cto.com/art/201407/446430.htm

  • Related Article

    Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.