Re: [PHP-DEV] Extension for str_replace / preg_replace with arrays

2012-12-20 Thread Larry Garfield

On 12/19/12 10:30 PM, Christopher Jones wrote:



On 12/19/2012 03:18 PM, Larry Garfield wrote:

You could likely simplify the code even further using an infinite
iterator:

http://us1.php.net/infiniteiterator

$result = preg_replace_callback(
 '/word/',
 function($matches) use ($replacements_iterator) {
 return $replacements-next();
 },
 'word word word word word'
);

--Larry Garfield



What am I missing that causes the first call to
$replacements_iterator-current() to return NULL
unless the iterator is rewound before use?


Eh, nothing.  You're right, next() doesn't return an element, it just 
advances, so you still need the current() call.  Which seems kinda silly 
to me, but whatev.


--Larry Garfield

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Extension for str_replace / preg_replace with arrays

2012-12-20 Thread Christopher Jones



On 12/20/2012 08:31 AM, Larry Garfield wrote:

On 12/19/12 10:30 PM, Christopher Jones wrote:



On 12/19/2012 03:18 PM, Larry Garfield wrote:

You could likely simplify the code even further using an infinite
iterator:

http://us1.php.net/infiniteiterator

$result = preg_replace_callback(
 '/word/',
 function($matches) use ($replacements_iterator) {
 return $replacements-next();
 },
 'word word word word word'
);

--Larry Garfield



What am I missing that causes the first call to
$replacements_iterator-current() to return NULL
unless the iterator is rewound before use?


Eh, nothing.  You're right, next() doesn't return an element, it just advances, 
so you still need the current() call.  Which seems kinda silly to me, but 
whatev.


That is documented, so it's OK.  The curiosity (bug?) is the need to call 
rewind():

$replacements_iterator = new InfiniteIterator(new ArrayIterator($replacements));
$replacements_iterator-rewind();  // why is the rewind needed?

$result = preg_replace_callback(
'/word/',
function($matches) use ($replacements_iterator) {
$r = $replacements_iterator-current();
$replacements_iterator-next();
return $r;
},
'word word word word word word word word'
);

In other (simple) scripts using InfiniteIterator the rewind wasn't needed.


--
christopher.jo...@oracle.com  http://twitter.com/ghrd

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Extension for str_replace / preg_replace with arrays

2012-12-20 Thread David Muir

On 21/12/12 10:34, Christopher Jones wrote:



On 12/20/2012 08:31 AM, Larry Garfield wrote:

On 12/19/12 10:30 PM, Christopher Jones wrote:



On 12/19/2012 03:18 PM, Larry Garfield wrote:

You could likely simplify the code even further using an infinite
iterator:

http://us1.php.net/infiniteiterator

$result = preg_replace_callback(
 '/word/',
 function($matches) use ($replacements_iterator) {
 return $replacements-next();
 },
 'word word word word word'
);

--Larry Garfield



What am I missing that causes the first call to
$replacements_iterator-current() to return NULL
unless the iterator is rewound before use?


Eh, nothing.  You're right, next() doesn't return an element, it just 
advances, so you still need the current() call.  Which seems kinda 
silly to me, but whatev.


That is documented, so it's OK.  The curiosity (bug?) is the need to 
call rewind():


$replacements_iterator = new InfiniteIterator(new 
ArrayIterator($replacements));

$replacements_iterator-rewind();  // why is the rewind needed?

$result = preg_replace_callback(
'/word/',
function($matches) use ($replacements_iterator) {
$r = $replacements_iterator-current();
$replacements_iterator-next();
return $r;
},
'word word word word word word word word'
);

In other (simple) scripts using InfiniteIterator the rewind wasn't 
needed.






What happens if you do:
$replacements_iterator = new InfiniteIterator(new 
ArrayIterator($replacements));

var_dump($replacements_iterator-current());

If I remember correctly, when you pass a traversable into foreach, under 
the hood, it basically calls:


$iterator-rewind();
while($iterator-valid()){
$value = $iterator-current();
(foreach block)
$iterator-next();
}

So that might explain why it works in (simple) scripts.

It does seem like a bug that the rewind is required though. A newly 
created iterator should already be in a rewound state so the call 
shouldn't be needed.


Cheers,
David

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Extension for str_replace / preg_replace with arrays

2012-12-20 Thread Christopher Jones



On 12/20/2012 04:05 PM, David Muir wrote:


The curiosity (bug?) is the need to call rewind():

$replacements_iterator = new InfiniteIterator(new ArrayIterator($replacements));
$replacements_iterator-rewind();  // why is the rewind needed?

$result = preg_replace_callback(
'/word/',
function($matches) use ($replacements_iterator) {
$r = $replacements_iterator-current();
$replacements_iterator-next();
return $r;
},
'word word word word word word word word'
);

In other (simple) scripts using InfiniteIterator the rewind wasn't needed.





What happens if you do:
$replacements_iterator = new InfiniteIterator(new ArrayIterator($replacements));
var_dump($replacements_iterator-current());

If I remember correctly, when you pass a traversable into foreach, under the 
hood, it basically calls:

$iterator-rewind();
while($iterator-valid()){
 $value = $iterator-current();
 (foreach block)
 $iterator-next();
}

So that might explain why it works in (simple) scripts.

It does seem like a bug that the rewind is required though. A newly created 
iterator should already be in a rewound state so the call shouldn't be needed.

Cheers,
David


I logged a bug so this can be tracked and re-discovered: 
https://bugs.php.net/bug.php?id=63823

Chris
--
christopher.jo...@oracle.com  http://twitter.com/ghrd
Newly updated, free PHP  Oracle book:
http://www.oracle.com/technetwork/topics/php/underground-php-oracle-manual-098250.html

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Extension for str_replace / preg_replace with arrays

2012-12-19 Thread Andrey Andreev
I've personally requested this on the bug tracker:  
https://bugs.php.net/bug.php?id=62315


P.S.: I hope this gets properly tracked to the thread as I read it  
from the archive and am not subscribed to the list.


 - Andrey


--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Extension for str_replace / preg_replace with arrays

2012-12-19 Thread Larry Garfield

On 12/18/12 7:44 AM, Leigh wrote:

On 18 December 2012 13:24, Stefan Neufeind neufe...@php.net wrote:


Since we already have functionality for replacing with arrays in place,
I wondered if giving it one string to replace and then an array to
choose the replacement from (rotating) would be an option. Currently
that's unsupported (either two strings or two arrays).



It's certainly possible to implement, but personally it feels like odd
behaviour. I don't know what other people think about it.



I think you could use a callback-function but would need to add quite a
few more lines to initialise your array first, do a next() on the
array inside the callback-function and (how would you pass it that
array?) and still would have to handle starting from beginning of the
array again once you reach the end etc.



You pass the array using use. You could do it something like this:

$replacements = array(
 'one', 'two', 'three'
);

$result = preg_replace_callback(
 '/word/',
 function($matches) use ($replacements) {
 $current = current($replacements);
 next($replacements) || reset($replacements);
 return $current;
 },
 'word word word word word'
);

var_dump($result);

Output:

string(21) one two three one two


You could likely simplify the code even further using an infinite iterator:

http://us1.php.net/infiniteiterator

$result = preg_replace_callback(
'/word/',
function($matches) use ($replacements_iterator) {
return $replacements-next();
},
'word word word word word'
);

--Larry Garfield

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Extension for str_replace / preg_replace with arrays

2012-12-19 Thread Christopher Jones



On 12/19/2012 03:18 PM, Larry Garfield wrote:

You could likely simplify the code even further using an infinite iterator:

http://us1.php.net/infiniteiterator

$result = preg_replace_callback(
 '/word/',
 function($matches) use ($replacements_iterator) {
 return $replacements-next();
 },
 'word word word word word'
);

--Larry Garfield



What am I missing that causes the first call to 
$replacements_iterator-current() to return NULL
unless the iterator is rewound before use?

Chris

--

?php

$replacements = array(
'one', 'two', 'three'
);

$replacements_iterator = new InfiniteIterator(new ArrayIterator($replacements));
$replacements_iterator-rewind();  // why is the rewind needed?

$result = preg_replace_callback(
'/word/',
function($matches) use ($replacements_iterator) {
$r = $replacements_iterator-current();
$replacements_iterator-next();
return $r;
},
'word word word word word'
);

var_dump($result);

// Outputs:
//string(21) one two three one two
// Without the call to $replacements_iterator-rewind(), the output is:
//string(18)  two three one two

?

--
christopher.jo...@oracle.com  http://twitter.com/ghrd


--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] Extension for str_replace / preg_replace with arrays

2012-12-18 Thread Stefan Neufeind
Hi,

inside a framework-/scripting-project we've lately discussed
string-replacements with arrays.

Currently PHP supports either replacing one string by another or
replacing first element from one array with first from another array.

What I'd like to propose is for str_replace and preg_replace to introduce:
* a functionality to replace one string with strings from an array
* to (optionally) allow for rolling replacements (1,2,3, 1,2,3, ...)
* to (optionally) allow to skip strings already replaced
  (that means not to accidentially double-replace strings)

This would allow to do things like

$content = str_replace('li',
  array('li class=A', 'li class=B', 'li class=C'),
  $content);

optionally starting over from A again. (Current default is to stop when
there are no more elements to replace with).


Would such a change/extension find support?


Kind regards,
 Stefan Neufeind

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Extension for str_replace / preg_replace with arrays

2012-12-18 Thread Leigh
Both str_replace and preg_replace already support some array based
replacements, I think adding more options to these functions specifically
would just lead to confusion.

What you're proposing can already be achieved quite easily with
preg_replace_callback and passing your array/options into the anonymous
function with `use`, I'd personally welcome a str_replace_callback
counterpart.


On 18 December 2012 12:08, Stefan Neufeind neufe...@php.net wrote:

 Hi,

 inside a framework-/scripting-project we've lately discussed
 string-replacements with arrays.

 Currently PHP supports either replacing one string by another or
 replacing first element from one array with first from another array.

 What I'd like to propose is for str_replace and preg_replace to introduce:
 * a functionality to replace one string with strings from an array
 * to (optionally) allow for rolling replacements (1,2,3, 1,2,3, ...)
 * to (optionally) allow to skip strings already replaced
   (that means not to accidentially double-replace strings)

 This would allow to do things like

 $content = str_replace('li',
   array('li class=A', 'li class=B', 'li class=C'),
   $content);

 optionally starting over from A again. (Current default is to stop when
 there are no more elements to replace with).


 Would such a change/extension find support?


 Kind regards,
  Stefan Neufeind

 --
 PHP Internals - PHP Runtime Development Mailing List
 To unsubscribe, visit: http://www.php.net/unsub.php




Re: [PHP-DEV] Extension for str_replace / preg_replace with arrays

2012-12-18 Thread Stefan Neufeind
Hi,

On 12/18/2012 01:16 PM, Leigh wrote:
 Both str_replace and preg_replace already support some array based
 replacements, I think adding more options to these functions
 specifically would just lead to confusion.

Well, yes and no. Currently you have to supply either one string to
replace with one other or you have to supply arrays for each of them.
And this wouldn't allow to replace the second, third etc. occurence
different.

Since we already have functionality for replacing with arrays in place,
I wondered if giving it one string to replace and then an array to
choose the replacement from (rotating) would be an option. Currently
that's unsupported (either two strings or two arrays).

 What you're proposing can already be achieved quite easily with
 preg_replace_callback and passing your array/options into the anonymous
 function with `use`, I'd personally welcome a str_replace_callback
 counterpart.

I think you could use a callback-function but would need to add quite a
few more lines to initialise your array first, do a next() on the
array inside the callback-function and (how would you pass it that
array?) and still would have to handle starting from beginning of the
array again once you reach the end etc.


Kind regards,
 Stefan

 On 18 December 2012 12:08, Stefan Neufeind neufe...@php.net
 mailto:neufe...@php.net wrote:
 
 Hi,
 
 inside a framework-/scripting-project we've lately discussed
 string-replacements with arrays.
 
 Currently PHP supports either replacing one string by another or
 replacing first element from one array with first from another array.
 
 What I'd like to propose is for str_replace and preg_replace to
 introduce:
 * a functionality to replace one string with strings from an array
 * to (optionally) allow for rolling replacements (1,2,3, 1,2,3, ...)
 * to (optionally) allow to skip strings already replaced
   (that means not to accidentially double-replace strings)
 
 This would allow to do things like
 
 $content = str_replace('li',
   array('li class=A', 'li class=B', 'li class=C'),
   $content);
 
 optionally starting over from A again. (Current default is to stop when
 there are no more elements to replace with).
 
 
 Would such a change/extension find support?
 
 
 Kind regards,
  Stefan Neufeind

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Extension for str_replace / preg_replace with arrays

2012-12-18 Thread Leigh
On 18 December 2012 13:24, Stefan Neufeind neufe...@php.net wrote:

 Since we already have functionality for replacing with arrays in place,
 I wondered if giving it one string to replace and then an array to
 choose the replacement from (rotating) would be an option. Currently
 that's unsupported (either two strings or two arrays).


It's certainly possible to implement, but personally it feels like odd
behaviour. I don't know what other people think about it.


 I think you could use a callback-function but would need to add quite a
 few more lines to initialise your array first, do a next() on the
 array inside the callback-function and (how would you pass it that
 array?) and still would have to handle starting from beginning of the
 array again once you reach the end etc.


You pass the array using use. You could do it something like this:

$replacements = array(
'one', 'two', 'three'
);

$result = preg_replace_callback(
'/word/',
function($matches) use ($replacements) {
$current = current($replacements);
next($replacements) || reset($replacements);
return $current;
},
'word word word word word'
);

var_dump($result);

Output:

string(21) one two three one two