Jump to content

Hanna Codes unintentionally "memoize"


Recommended Posts

Just reporting this to save other people some debugging time:

Hanna Codes unintentionally "memoize" results.

Here's a rough example of what I mean.

Imagine a stateful Hanna Code.

For example, imagine a Hanna Code that maintains a count, and increases the count each time it's used:

[[count]]
[[count]]
[[count]]

You'd expect this:

1
2
3

But you'll get this instead:

1
1
1

Here's where it gets very odd though: your Hanna Code will in fact be called three times, and the counter will in fact end up at "3"!

It took me a bit to figure out what was going on.

The problem is that all Hanna Codes are extracted up front, here. Then they're processed one by one, here. As each Hanna Code is processed, it gets replaced here. And that's the problem: the replacement is global; all matches get replaced, not just the first.

So in this example all three `[[count]]`s will be extracted, and the loop will iterate three times, but the first iteration will replace all occurrences of `[[count]]`, leaving nothing for the next two iterations to replace.

(I'm calling this "unintentional memoization" because typically you memoize to avoid work. In this case work isn't avoided, the result of the work simply isn't used.)

  • Like 2
Link to comment
Share on other sites

Maybe "strtr" instead of "str_replace" would take care of things as it only replaces the first instance. I am surprised though that it's not mentioned at all here: https://stackoverflow.com/questions/1252693/using-str-replace-so-that-it-only-acts-on-the-first-match so maybe I am missing something? Perhaps this is worth a thorough read: https://stackoverflow.com/questions/8177296/when-to-use-strtr-vs-str-replace

Link to comment
Share on other sites

@adrian Take a look at the description of strtr:

Quote

strtr  Translate characters or replace substrings

...

If given three arguments, this function returns a copy of string where all occurrences of each (single-byte) character in from have been translated to the corresponding character in to, i.e., every occurrence of $from[$n]has been replaced with $to[$n], where $n is a valid offset in both arguments.

So the purpose of `strtr` is to replace individual characters, not substrings. Take a look at Example #3 to see what I mean.

(The `tr` in `strtr` comes from the Unix command `tr`, which does the same thing.)

Link to comment
Share on other sites

Sorry, I should explain a bit more! `strtr` can work in two modes, and in one mode it can replace substrings. But that isn't its purpose, and I think it would be confusing to use it for that. (It would be especially confusing if, like me, you happen to know about `tr`.)

Even more, though: like `str_replace`, `strtr` replaces all matching strings, not just the first. So it can't actually solve the original problem anyway.

  • Like 1
Link to comment
Share on other sites

Thanks for the explanations. I actually use strtr quite a lot for an array of substring replacements - works great. Sorry for the confusion about how it replaces - I wasn't thinking straight and was thinking about this difference: "strtr will not replace in parts of the string that already have been replaced - str_replace will replace inside replaces", rather than the replacing only the first occurrence - sorry I rushed without thinking it through - my bad :(

Link to comment
Share on other sites

I don't know anything about the history of `strtr` in PHP, but my guess would be that the reason it has the ability to replace strings in the first place is simply an extension of its original purpose from single-byte characters to multi-byte. It just so happens that in PHP multi-byte characters are represented as strings…

I don't know if that's right, but I've seen it in other languages, so it certainly seems plausible. And when you have that in your head using it to just replace arbitrary strings feels, you know, funny. 🙂

  • Like 2
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...