-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
New build Mon Apr 1 23:18:26 UTC 2024
- Loading branch information
Automated Build
committed
Apr 1, 2024
1 parent
51cbe8a
commit a839f17
Showing
42 changed files
with
5,891 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,230 @@ | ||
<!DOCTYPE HTML/><html lang="en-US"><head><meta charset="UTF-8"/><meta http-equiv="X-UA-Compatible" content="IE=edge"/><meta name="viewport" content="width=device-width, initial-scale=1"/><title>Reinventing the Wheel: PHP Generators</title><meta name="generator" content="Custom"/><meta property="og:title" content="Reinventing the Wheel: PHP Generators"/><meta property="og:locale" content="en_US"/><meta name="description" content="Attempt of a lunatic to recreate functionalities that a language already has using the same language, and failing."/><meta property="og:description" content="Attempt of a lunatic to recreate functionalities that a language already has using the same language, and failing."/><meta name="keywords" content="php, generators"/><link rel="canonical" href="https://mliezun.github.io/2020/01/24/php-generator.html"/><meta property="og:url" content="https://mliezun.github.io/2020/01/24/php-generator.html"/><meta property="og:site_name" content="mliezun.github.io"/><meta property="og:image" content="https://mliezun.github.io/assets/images/nyc.jpg"/><link rel="icon" type="image/x-icon" href="/assets/images/favicon.ico"/><meta property="og:type" content="article"/><meta name="twitter:card" content="summary"/><meta property="twitter:title" content="Reinventing the Wheel: PHP Generators"/><meta name="twitter:creator" content="@migueliezun"/><meta name="twitter:image" content="https://mliezun.github.io/assets/images/nyc.jpg"/> | ||
<script type="application/ld+json">{"description":"Attempt of a lunatic to recreate functionalities that a language already has using the same language, and failing.","author":{"@type":"Person","name":"Miguel Liezun"},"@type":"BlogPosting","url":"https://mliezun.github.io/2020/01/24/php-generator.html","headline":"Reinventing the Wheel: PHP Generators","dateModified":"2020-01-24T00:00:00-03:00","datePublished":"2020-01-24T00:00:00-03:00","mainEntityOfPage":{"@type":"WebPage","@id":"https://mliezun.github.io/2020/01/24/php-generator.html"},"@context":"https://schema.org"} | ||
</script><link rel="preconnect" href="https://fonts.googleapis.com"/><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin=""/><link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Ibarra+Real+Nova:wght@400;700&display=swap"/><link rel="stylesheet" href="/assets/css/style.css"/></head><body><div class="body-wrapper"><div class="body-content"><div class="site-header"><header><a href="/" style="text-decoration: none !important">Blog</a></header></div><hr/><p>Reading time: | ||
<span id="reading-time"></span></p><article><div> | ||
|
||
</div><h2>Reinventing the Wheel: PHP Generators | ||
</h2><div> | ||
|
||
</div><h3>First thing first. How a generator works? | ||
</h3><div> | ||
|
||
</div><h4>Starting back at C | ||
</h4><div> | ||
Let's create a function that each time we call it we get the next number of the fibonacci sequence. | ||
|
||
<pre class="triple-quote c"> | ||
int fibonacci() | ||
{ | ||
static int a = 0; | ||
static int b = 1; | ||
int aux = b; | ||
b = a + b; | ||
a = aux; | ||
return a; | ||
} | ||
</pre> | ||
|
||
If we call fibonacci(), the first time we'll get 1, the second time 1, the third 2, the fourth 3, and so on... | ||
|
||
This happens because we declared variables <span class="single-quote">a, b</span> to be static. This means that they mantain the value after the function returns. Normally, what happens (if we don't declare a variable as static) is that the variables inside the function don't mantain the values of the last execution. | ||
|
||
|
||
</div><h4>First generator for PHP | ||
</h4><div> | ||
The equivalent function in PHP is pretty similar to C's approach. | ||
|
||
<pre class="triple-quote php"> | ||
|
||
|
||
function fibonacci() | ||
{ | ||
static $a = 0; | ||
static $b = 1; | ||
$aux = $b; | ||
$b = $a + $b; | ||
$a = $aux; | ||
return $a; | ||
} | ||
|
||
$out = []; | ||
|
||
for ($i = 1; $i <= 10; $i++) { | ||
$out[] = fibonacci(); | ||
} | ||
|
||
echo implode(', ', $out) . "\n"; | ||
|
||
/* | ||
Output: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 | ||
*/ | ||
</pre> | ||
|
||
Let's compare this to the <span class="single-quote">real</span> PHP version using <span class="single-quote">yield</span>. | ||
|
||
<pre class="triple-quote php"> | ||
|
||
|
||
function fibonacci($N) | ||
{ | ||
$a = 0; | ||
$b = 1; | ||
for ($i = 0; $i < $N; $i++) { | ||
$aux = $b; | ||
$b = $a + $b; | ||
$a = $aux; | ||
yield $a; | ||
} | ||
} | ||
|
||
$out = []; | ||
|
||
foreach (fibonacci(10) as $fib) { | ||
$out[] = $fib; | ||
} | ||
|
||
echo implode(', ', $out) . "\n"; | ||
|
||
/* | ||
Output: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 | ||
*/ | ||
</pre> | ||
|
||
|
||
</div><h4>Creating a custom version of PHP <span class="single-quote">yield</span> | ||
</h4><div> | ||
This is my own version using the library parallel and channels (probably uses yield internally). | ||
|
||
<pre class="triple-quote php"> | ||
|
||
|
||
class MyGenerator implements Iterator | ||
{ | ||
private $chan; | ||
private $current; | ||
private $iteratorFn; | ||
private $runtime; | ||
private $key = -1; | ||
private $valid = true; | ||
|
||
public function __construct($iteratorFn) | ||
{ | ||
$this->iteratorFn = $iteratorFn; | ||
$this->runtime = new \parallel\Runtime(); | ||
$channel = new \parallel\Channel(); | ||
|
||
$this->runtime->run(function() use ($iteratorFn, $channel) { | ||
$iteratorFn(function ($val) use ($channel) { | ||
$channel->send($val); | ||
}); | ||
$channel->close(); | ||
}); | ||
|
||
$this->chan = $channel; | ||
$this->next(); | ||
} | ||
|
||
public function current() | ||
{ | ||
return $this->current; | ||
} | ||
|
||
public function next() | ||
{ | ||
try { | ||
++$this->key; | ||
$val = $this->chan->recv(); | ||
$this->current = $val; | ||
} catch (\parallel\Channel\Error\Closed $e) { | ||
$this->valid = false; | ||
} | ||
return $this->current; | ||
} | ||
|
||
public function key() {return $this->key;} | ||
public function valid() {return $this->valid;} | ||
public function rewind() {} | ||
} | ||
|
||
|
||
function fibonacci($N) | ||
{ | ||
return new MyGenerator(function ($yield) use ($N) { | ||
$a = 0; | ||
$b = 1; | ||
for ($i = 0; $i < $N; $i++) { | ||
$aux = $b; | ||
$b = $a + $b; | ||
$a = $aux; | ||
$yield($a); | ||
} | ||
}); | ||
} | ||
|
||
$out = []; | ||
|
||
foreach (fibonacci(10) as $fib) { | ||
$out[] = $fib; | ||
} | ||
|
||
echo implode(', ', $out) . "\n"; | ||
</pre> | ||
|
||
|
||
</div><h4>Performance comparison: PHP vs Custom | ||
</h4><div> | ||
|
||
</div><h5>Tested code | ||
</h5><div> | ||
<pre class="triple-quote php"> | ||
for ($i = 0; $i < 1000; ++$i) { | ||
foreach (fibonacci(100) as $fib) { | ||
$out[] = $fib; | ||
} | ||
} | ||
</pre> | ||
|
||
|
||
</div><h5><span class="single-quote">yield</span> version | ||
</h5><div> | ||
<pre class="triple-quote "> | ||
real 0m0,083s | ||
user 0m0,059s | ||
sys 0m0,023s | ||
</pre> | ||
|
||
|
||
</div><h5><span class="single-quote">MyGenerator</span> version | ||
</h5><div> | ||
<pre class="triple-quote "> | ||
real 0m2,138s | ||
user 0m1,426s | ||
sys 0m1,363s | ||
</pre> | ||
|
||
So, it's aproximately 26 times slower :-) | ||
|
||
</div></article><script>var text = document.getElementsByTagName('article')[0].innerText; | ||
var wpm = 220; | ||
var words = text.trim().split(/\s+/).length; | ||
var time = Math.ceil(words/wpm); | ||
document.getElementById('reading-time').innerText = (time || 1) + (time > 1 ? ' minutes' : ' minute'); | ||
</script><footer><hr/><div class="footer-wrapper"><div><div>This blog was made by | ||
<a target="_blank" href="https://github.com/mliezun">Miguel Liezun</a> using | ||
<a target="_blank" href="https://github.com/mliezun/grotsky">Grotsky</a></div><div>Blog | ||
<a target="_blank" href="https://github.com/mliezun/mliezun.github.io">source code</a></div></div><div class="footer-socials"><a target="_blank" href="https://mliezun.github.io/feed.xml"><img alt="Github" src="/assets/images/socials/rss.png" width="20" height="20" style="border-radius: 3px"/></a><a target="_blank" href="https://github.com/mliezun"><img alt="Github" src="/assets/images/socials/github.png" width="20" height="20"/></a><a target="_blank" href="https://x.com/migueliezun"><img alt="X (Twitter)" src="/assets/images/socials/x.ico" width="20" height="20" style="border-radius: 5px"/></a><a target="_blank" href="https://www.linkedin.com/in/miguel-liezun-8697a9168/"><img alt="LinkedIn" src="/assets/images/socials/linkedin.png" width="20" height="20"/></a></div></div></footer></div></div><script async="" src="https://www.googletagmanager.com/gtag/js?id=G-B0X6717RHT"></script><script>window.dataLayer = window.dataLayer || []; | ||
function gtag(){dataLayer.push(arguments);} | ||
gtag('js', new Date()); | ||
|
||
gtag('config', 'G-B0X6717RHT'); | ||
</script><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/styles/default.min.css"/><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/highlight.min.js"></script><script>document.querySelectorAll('.triple-quote').forEach(function (el) { | ||
if (el.classList.length > 1) hljs.highlightElement(el, {language: el.classList[1]}); | ||
else hljs.highlightElement(el); | ||
el.classList.remove('hljs'); | ||
}) | ||
</script><script>document.querySelectorAll('.single-quote').forEach(function (el) { | ||
if (el.classList.length > 1) hljs.highlightElement(el, {language: el.classList[1]}); | ||
else hljs.highlightElement(el); | ||
el.classList.remove('hljs'); | ||
}) | ||
</script></body></html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
<!DOCTYPE HTML/><html lang="en-US"><head><meta charset="UTF-8"/><meta http-equiv="X-UA-Compatible" content="IE=edge"/><meta name="viewport" content="width=device-width, initial-scale=1"/><title>Crafting interpreters</title><meta name="generator" content="Custom"/><meta property="og:title" content="Crafting interpreters"/><meta property="og:locale" content="en_US"/><meta name="description" content="Lox language interpreter based on the book craftinginterpreters.com by Bob Nystrom."/><meta property="og:description" content="Lox language interpreter based on the book craftinginterpreters.com by Bob Nystrom."/><meta name="keywords" content="interpreter,parser,lexer"/><link rel="canonical" href="https://mliezun.github.io/2020/02/12/crafting-interpreters.html"/><meta property="og:url" content="https://mliezun.github.io/2020/02/12/crafting-interpreters.html"/><meta property="og:site_name" content="mliezun.github.io"/><meta property="og:image" content="https://mliezun.github.io/assets/images/nyc.jpg"/><link rel="icon" type="image/x-icon" href="/assets/images/favicon.ico"/><meta property="og:type" content="article"/><meta name="twitter:card" content="summary"/><meta property="twitter:title" content="Crafting interpreters"/><meta name="twitter:creator" content="@migueliezun"/><meta name="twitter:image" content="https://mliezun.github.io/assets/images/nyc.jpg"/> | ||
<script type="application/ld+json">{"description":"Lox language interpreter based on the book craftinginterpreters.com by Bob Nystrom.","author":{"@type":"Person","name":"Miguel Liezun"},"@type":"BlogPosting","url":"https://mliezun.github.io/2020/02/12/crafting-interpreters.html","headline":"Crafting interpreters","dateModified":"2020-02-12T00:00:00-03:00","datePublished":"2020-02-12T00:00:00-03:00","mainEntityOfPage":{"@type":"WebPage","@id":"https://mliezun.github.io/2020/02/12/crafting-interpreters.html"},"@context":"https://schema.org"} | ||
</script><link rel="preconnect" href="https://fonts.googleapis.com"/><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin=""/><link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Ibarra+Real+Nova:wght@400;700&display=swap"/><link rel="stylesheet" href="/assets/css/style.css"/></head><body><div class="body-wrapper"><div class="body-content"><div class="site-header"><header><a href="/" style="text-decoration: none !important">Blog</a></header></div><hr/><p>Reading time: | ||
<span id="reading-time"></span></p><article><div> | ||
|
||
</div><h2>Crafting interpreters | ||
</h2><div> | ||
I've just finished the section 2 of the book _Crafting Interpreters_, and I wanted to upload it to github right away. | ||
|
||
Take a look at the <a href="https://github.com/mliezun/jlox">source code</a>. | ||
|
||
Beside the lox specification I've added: | ||
|
||
<li>The keyword <span class="single-quote">until</span> that is a variation of <span class="single-quote">while</span> loops (as in ruby). also</li> | ||
<li><span class="single-quote">print</span> is a function instead of a statement.</li> | ||
<li><span class="single-quote">eval</span> function that let's you eval source code in runtime.</li> | ||
<li>Class methods.</li> | ||
|
||
I'll implement another language interpreter, this time using <span class="single-quote">golang</span> and with a syntax similar to ruby. | ||
|
||
</div></article><script>var text = document.getElementsByTagName('article')[0].innerText; | ||
var wpm = 220; | ||
var words = text.trim().split(/\s+/).length; | ||
var time = Math.ceil(words/wpm); | ||
document.getElementById('reading-time').innerText = (time || 1) + (time > 1 ? ' minutes' : ' minute'); | ||
</script><footer><hr/><div class="footer-wrapper"><div><div>This blog was made by | ||
<a target="_blank" href="https://github.com/mliezun">Miguel Liezun</a> using | ||
<a target="_blank" href="https://github.com/mliezun/grotsky">Grotsky</a></div><div>Blog | ||
<a target="_blank" href="https://github.com/mliezun/mliezun.github.io">source code</a></div></div><div class="footer-socials"><a target="_blank" href="https://mliezun.github.io/feed.xml"><img alt="Github" src="/assets/images/socials/rss.png" width="20" height="20" style="border-radius: 3px"/></a><a target="_blank" href="https://github.com/mliezun"><img alt="Github" src="/assets/images/socials/github.png" width="20" height="20"/></a><a target="_blank" href="https://x.com/migueliezun"><img alt="X (Twitter)" src="/assets/images/socials/x.ico" width="20" height="20" style="border-radius: 5px"/></a><a target="_blank" href="https://www.linkedin.com/in/miguel-liezun-8697a9168/"><img alt="LinkedIn" src="/assets/images/socials/linkedin.png" width="20" height="20"/></a></div></div></footer></div></div><script async="" src="https://www.googletagmanager.com/gtag/js?id=G-B0X6717RHT"></script><script>window.dataLayer = window.dataLayer || []; | ||
function gtag(){dataLayer.push(arguments);} | ||
gtag('js', new Date()); | ||
|
||
gtag('config', 'G-B0X6717RHT'); | ||
</script><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/styles/default.min.css"/><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/highlight.min.js"></script><script>document.querySelectorAll('.triple-quote').forEach(function (el) { | ||
if (el.classList.length > 1) hljs.highlightElement(el, {language: el.classList[1]}); | ||
else hljs.highlightElement(el); | ||
el.classList.remove('hljs'); | ||
}) | ||
</script><script>document.querySelectorAll('.single-quote').forEach(function (el) { | ||
if (el.classList.length > 1) hljs.highlightElement(el, {language: el.classList[1]}); | ||
else hljs.highlightElement(el); | ||
el.classList.remove('hljs'); | ||
}) | ||
</script></body></html> |
Oops, something went wrong.