# Regarding PHP6, string/array APIs

- Thread: https://externals.io/message/61460
- Original archive: https://news-web.php.net/php.internals/61460
- Started by Alexey Zakhlestin on 2012-07-19T08:05:35+00:00
- Messages: 5
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · RFCs at https://externals.io/rfc.md · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #61460 — Alexey Zakhlestin — 2012-07-19T08:05:35+00:00

URL: https://externals.io/message/61460#61460

Stas made a good point about need to start with new API, which then can be followed by syntactic sugar.

So, we need some ideas to start with:

1. A lot of people told, that it would be a good idea to come with a written standard regarding arguments order. I don't care what it will be, as long as it will be documented.

2. It would be really useful to have 2 versions of each function: one which mutates the variable and one which returns the new variable.

Example:

    <?php
      $src = 'SoUrCe';
      $result = lowered($src); // $result == 'source', $src == 'SoUrCe'
      $result = lower($srd);   // $result == true,     $src = 'source'
    ?>

3. Speaking of implementation… Functions, which return slice of string/array could be made to reference the same memory-areas as the source strings/arrays. That is until the first modification, of course. Kinda advanced copy-on-write semantics. I know something like that is implemented in D http://dlang.org/d-array-article.html and Go

4. casting between strings and arrays of characters would be a great thing to have too. this way, useful array-oriented functions could be applied to strings

---

## #61477 — Andrew Faulds — 2012-07-19T11:40:58+00:00

URL: https://externals.io/message/61460#61477 · In reply to: #61460

One consideration: Should be a general array/string/int/float/bool API. PHP
is weakly typed: therefore, say, reverse() would reverse a string OR an
array. negate() would invert a bool, negate an int/float. slice() would
slice a section of a string OR an array. `max()` would find maximum of an
array, or `max()` of two numeric values, etc. If you get my meaning. These
are all examples of course. Many functions would have to be type-specific
(numeric, array/string, boolean, array, string), but they should be
multi-type as far as possible IMO.


> Stas made a good point about need to start with new API, which then can be
> followed by syntactic sugar.
>
> So, we need some ideas to start with:
>
> 1. A lot of people told, that it would be a good idea to come with a
> written standard regarding arguments order. I don't care what it will be,
> as long as it will be documented.
>
> 2. It would be really useful to have 2 versions of each function: one
> which mutates the variable and one which returns the new variable.
>
> Example:
>
>     <?php
>       $src = 'SoUrCe';
>       $result = lowered($src); // $result == 'source', $src == 'SoUrCe'
>       $result = lower($srd);   // $result == true,     $src = 'source'
>     ?>
>
> 3. Speaking of implementation… Functions, which return slice of
> string/array could be made to reference the same memory-areas as the source
> strings/arrays. That is until the first modification, of course. Kinda
> advanced copy-on-write semantics. I know something like that is implemented
> in D http://dlang.org/d-array-article.html and Go
>
> 4. casting between strings and arrays of characters would be a great thing
> to have too. this way, useful array-oriented functions could be applied to
> strings

---

## #61534 — Anthony Ferrara — 2012-07-20T00:33:58+00:00

URL: https://externals.io/message/61460#61534

Hey all,

So I've been thinking about this for a while. Here's what I've come up with:

1. We want to maintain loose typing, so implementing a different API on
string than on int types would be bad.

2. We want to retain backwards compatibility to some extent with the legacy
API.

3. We want the ability to simplify the standard library.

So here's my thought. Make $var->method($arg1, $arg2) on scalar types a
"short-hand" for \php\method($var, $arg1, $arg2).

So we re-organize the base API into \php, cut down to just the base
methods. So:

\php\length()
 - If array, `count()`, else `strlen()`
\php\substr()
 - Treat as string always
\php\replace()
 - Normal str_replace semantics
\php\split()
 - Treat as string always
\php\join()
 - Treat as array always
\php\shuffle()
 - If array, array_shuffle, otherwise str_shuffle
\php\pos()
 - if array, `array_search()`, else `strpos()`
\php\reverse()
 - if array, `array_reverse()`, else `strrev()`
\php\merge()
 - If array, array_merge, if not, string concat
\php\type()
 - return type information about variable
etc

Now, those that are clearly type specific, or are too specialized to belong
on a "global" type, would then be sub-namespaced:

\php\array\map()
\php\array\keys()
\php\math\min()
\php\math\max()
\php\math\round()
\php\string\number_format()
\php\string\chr()
\php\string\ord()
etc.

The benefit here, is that user types can implement the same "core"
interface and be used polymorphically with the core types (for at least the
base API). So then, countable() would disappear.

Now, there's one more thing that needs to happen. If you call
\php\length($var) directly (procedurally, not as a method call), we'd need
to check if $var is an object that implements ->length(), and if so, call
to that instead of an error.

That's the base idea. It could be extended further to include true objects
for scalars, which would implement the rest of the core API. So, you could
do:

(new \php\Array($array))->keys();

This would then assume standard object semantics for the "wrapped" type,
while at the same time losing the dynamic typing ability of the language
(but it's done on purpose here to keep the API clean).

For BC, we'd need to modify zend_parse_parameters to extract the array from
a wrapped array object, to keep BC code functioning correctly in either
case, but it should be pretty transparent to the user which is passed...

Is it perfect? Absolutely not. But it tries to get around the BC breaks, as
well as the dynamic typing issue that ints can be strings, and vise versa.

Thoughts?

Anthony

---

## #61547 — Alexey Zakhlestin — 2012-07-20T09:03:32+00:00

URL: https://externals.io/message/61460#61547

> Hi!
> 
> > […]
> 
> I'm not sure I understand why. What's wrong with $src = lowered($src);?

That's just convenience. matter of readability.

lower() can be implemented in userland and if we had "standard" userland library that would be a good place for it :)

function lower(&$str)
{
    $str = lowered($str);
}

> Also, when lower() returns not true? If there's a legitimate situation
> when it must return not true (I can't think of any, but maybe for more
> complex functions there is) what lowered() is supposed to do in the same
> situation? If there's none, why bother returning true?

As you said, it might be needed in more complex functions and it makes sense to return true just for consistency.
Other option is to (implicitly) return null and use exceptions.
And I, personally, would prefer exceptions ;)

> > […]
> 
> Strings are not modified in PHP (IS_STRING zvals can be modified but the
> actual string buffers aren't) so there's no actual "write" and thus no
> copy needed. But having this would require separate refcounting on
> string values, which may be a bit complicated to do.

much worse than that. refcounting on string-slices!

> > […]
> 
> We already have it, it's `str_split()`.

I know. But that is not "casting". I can not pass string to the function which expects array (thinking about array_map, array_filter, …). I have to call str_split explicitly.

---

## #61548 — Alexey Zakhlestin — 2012-07-20T09:20:28+00:00

URL: https://externals.io/message/61460#61548 · In reply to: #61534

Anthony, the whole concept is interesting. Can you probably write that as RFC. I believe that will make it easier to read/understand it.

Right now, I have only one question:



> The benefit here, is that user types can implement the same "core" interface and be used polymorphically with the core types (for at least the base API). So then, countable() would disappear. 

what is this "core" interface?
something magically assumed for internal types but explicitly defined as interface for user classes?
or implicit case-by-case interface like in python?
