theread.me

This commit is contained in:
2023-12-06 18:15:32 +00:00
parent f3fc53e5e6
commit 158340b507
476 changed files with 24 additions and 21530 deletions

View File

@ -1,212 +0,0 @@
---
layout: post
title: "CSS Filters are awesome!"
date: 2015-03-28 17:13:46
permalink: css-filters/
categories: programming
author: Mahdi
---
I've been working on the [CSS Filter Editor
widget](https://bugzilla.mozilla.org/show_bug.cgi?id=1055181) in Firefox
Developer Tools for a couple of weeks, thanks to [Patrick
Brosset](https://medium.com/@patrickbrosset) for mentoring me and [Tim
Nguyen](https://github.com/nt1m) for his great contributions.
Here is an [online version](http://mdibaiee.github.io/CSS-Filter-Tooltip/) to
use as a playground. This version is modified to be cross-browser and therefore
is a little different from the original widget used in Firefox.
You can also use [David Walsh's
demo](http://davidwalsh.name/demo/css-filters.php), although it doesn't have as
much flexibility.
CSS Filters are supported by most modern browsers ([Can I Use CSS
Filters](http://caniuse.com/#feat=css-filters)), if your browser doesn't
support this, please change your browser (I recommend
[Firefox](https://www.mozilla.org/en-US/firefox/new/)).
Introduction
============
CSS Filters introduce a few useful effects and some image adjusting functions,
namely blur, drop-shadow, contrast, brightness, [and a few
others](https://developer.mozilla.org/en-US/docs/Web/CSS/filter) which can be
really useful if used properly.
A simple demo showing blur, contrast and brightness combined (hover over image):
<iframe width="100%" height="300" src="//jsfiddle.net/mdibaiee/zLmyhe7t/embedded/result,css" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
I group filters by the type of value they take, let's explain them briefly:
Length
------
These filters accept a length value (px, em, cm, [etc](http://www.w3.org/Style/Examples/007/units)). blur is the only member of this family.
Percentage
----------
These filters accept percentage values, but if you omit the percentage sign,
the value is multiplied by 100, e.g. `contrast(2)` is another way of writing
`contrast(200%)`. Negative values have the same effect as zero.
Most filters explain themselves:
* brightness
* contrast
* grayscale
* invert
* opacity
* saturate
* sepia
### invert
I first understood how cool this filter can be after I saw Tim Nguyen using
this in theme switching. Yeah you can't invert everything and "Yay, I have a
new theme", but you can use invert on some elements and it works flawlessly,
believe me.
<iframe width="100%" height="100" src="//jsfiddle.net/mdibaiee/373dnby8/embedded/result,css" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
### opacity
You might wonder why do we have this function, as we already have an opacity
property in CSS, that's because the opacity property is not hardware
accelerated, but the filter property is hardware accelerated in most
browsers, which includes this function.
Angle
-----
hue-rotate is the only function to accept an angle value (degree / radian).
###hue-rotate
If you're familiar with [Hue](https://en.wikipedia.org/wiki/Hue) you probably
know that it's measured by angles. The hue-rotate rotates the hue circle of
an image relative to it's current hue value (360 and 0 have the same
results).
<iframe width="100%" height="300" src="//jsfiddle.net/mdibaiee/smk922fh/embedded/result,css" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
Special
-------
These filter's don't fit in any of the groups above, they have special/mixed values.
### drop-shadow
The drop-shadow filter accepts a *shadow-list*, four length values, and one
color. box-shadow and text-shadow also accept shadow lists.
You're probably familiar with shadow lists already: `drop-shadow(x y radius spread color)`.
Unfortunaly spread doesn't work in either Chrome or Firefox as of this writing — It is treated as an error.
drop-shadow is pretty cool, as it doensn't have the limitations of box-shadow
and text-shadow. box-shadow applies a shadow to the outer shape, but
drop-shadow applies a shadow to elements independant to their shape, they
might be triangles, PNG's with transparent background or just anything.
drop-shadow clones the element's image, moves it to the offset defined,
applies blur and changes it's color, putting it under the original element.
Couldn't do it better:
![drop-shadow explained](/img/dropshadow.gif)
Here is an example, a PNG image with transparent background and a CSS triangle made using the border hack:
<iframe width="100%" height="150" src="//jsfiddle.net/mdibaiee/z077vbs0/embedded/result,css" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
### url
With the url function we have the power of CSS and SVG Filters in one place.
You can reference an SVG element by linking to it with a hash of the filter
element's ID:
{% highlight css %}
filter: url(/example.svg#filter)
{% endhighlight %}
If you want to know more about SVG Filters, I recommend [MDN's tutorial on SVG Filters](https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Filter_effects).
### Custom
Now those filters are pretty cool, but what if I told you this is [going to be] done with CSS?
![Map Folding with Custom CSS Filters](/img/map.jpg)
{% include caption.html text='Source: http://www.adobe.com/devnet/archive/html5/articles/css-shaders.html' %}
Custom Filters allows usage of vertex and fragment shaders which run directly
in the GPU. Custom filters' specs is subject to change, so there's no
implementation yet. For more info on this topic follow the links below:
* [Getting started with CSS custom filters](http://alteredqualia.com/css-shaders/article/#shaders)
* [Introducing CSS shaders: Cinematic effects for the web](http://www.adobe.com/devnet/archive/html5/articles/css-shaders.html)
* [CSS shaders specifications](http://dev.w3.org/fxtf/custom/)
Gotchas
=======
You now have a basic understanding of filters, good. Here are a few gotchas
you'd better know.
Order matters
-------------
The order in which filters are applied matters. Take this example:
{% highlight css %}
filter: blur(10px) contrast(2);
{% endhighlight %}
Hey, browser, please blur the element, then double the contrast of the blurred
element. (blurred parts have their contrast affected)
{% highlight css %}
filter: contrast(2) blur(10px);
{% endhighlight %}
Hey browser, please double the contrast of my element, then blur it out. (high
contrast image is blurred normally)
Here is the actual comparison:
<iframe width="100%" height="300" src="//jsfiddle.net/mdibaiee/608yoqrx/embedded/result,css" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
Inheritance
-----------
Okay, you now know the order of filters matters, the filter property is not
actually *inherited*, but when you apply a filter on a parent element, of
course it's children are affected too, but what if the children have their own
css filters? Ah-ha! CSS properties are applied bottom-up, which means
childrens' filters are applied first.
<iframe width="100%" height="300" src="//jsfiddle.net/mdibaiee/o40d7cs7/embedded/result,css" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
Implementation
--------------
I said using the url function we have "the power of CSS and SVG filters in one
place", but the CSS filters are actually implemented using SVG filters! You
know, the functions are actually referencing to an svg generated in the
browser. Here is the list of [CSS Filter
equivalents](http://www.w3.org/TR/filter-effects/#ShorthandEquivalents).
Go Wild
=======
You can use CSS Filter on *any* element, experiment different things; `<video>`, `<canvas>`, `<iframe>`, GIF images, etc.
My try (although I couldn't get the GIF and CSS animation to be in sync, know a solution? Leave a comment please):
<iframe width="100%" height="300" src="//jsfiddle.net/mdibaiee/hjaL0ka3/embedded/result,css,js" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
-----
That's it, you can subscribe to my [RSS]({{ "/feed.xml" | prepend: site.baseurl | prepend: site.url }}) or follow me on [Twitter](https://twitter.com/{{ site.twitter_username }}) to get more articles like this.
<style>
#mahdi {
transition: filter 1s ease;
-webkit-transition: filter 1s ease;
}
#mahdi:hover {
filter: blur(3px);
-webkit-filter: blur(3px);
}
</style>

View File

@ -4,7 +4,6 @@ title: "BroadcastChannel API"
date: 2015-04-02 17:13:46
permalink: broadcastchannel-api/
categories: programming
author: Mahdi
---
[BroadcastChannel API](https://developer.mozilla.org/en-US/docs/Web/API/Broadcast_Channel_API)

View File

@ -1,178 +0,0 @@
---
layout: post
title: "ES7 Array and Generator comprehensions"
date: 2015-06-06 13:47:00
permalink: es7-array-generator-comprehensions/
categories: programming
author: Mahdi
---
Array comprehension is a new feature proposed for ES7, with a new syntax to
create new arrays from existing
[iterables](http://www.2ality.com/2015/02/es6-iteration.html), comprehensions
can replace map and filter.
Generator comprehension brings the same feature to generators, this is a more
useful feature as it removes the need to write new generators for simple
map/filter operations.
Generator comprehensions allow us to easily write single-line generators, which
can replace our arrays in some situations, you might ask why we might consider
replacing arrays with generators, the most important reason is their
[laziness](#laziness). I've explained laziness later in the article.
Comprehensions are currently only supported by Firefox, use Firefox 30+ or
[Babel](https://babeljs.io/repl/) to run the examples. The Node.js version of
examples using generator `function* ()`s is available at the
[repository](https://github.com/mdibaiee/array-vs-generator) (doesn't require
transpilation, use latest node).
Syntax
======
The syntax is pretty simple, you can only use `for of` and `if` inside comprehensions.
Array comprehensions:
{% highlight javascript %}
let numbers = [1,2,3,4,5];
let even = [ for (n of numbers) if (n % 2 === 0) n ];
// equivalent:
// let even = numbers.filter(n => n % 2 === 0);
console.log(...even); // 2 4
{% endhighlight %}
Generator comprehensions:
{% highlight javascript %}
// yield 0...5
let generator = function* () {
for (let i = 0; i < 6; i++) {
yield i;
}
}
let squared = ( for (n of generator()) n * n );
// equivalent:
// let squared = Array.from(generator()).map(n => n * n);
console.log(...squared); // 0 1 4 9 16 25
{% endhighlight %}
You can also nest comprehensions:
{% highlight javascript %}
// yield 0...5
let generator = function* () {
for (let i = 0; i < 6; i++) {
yield i;
}
}
// yield three numbers after number
let after = function* (number) {
for (let i = 1; i < 4; i++) {
yield number + i;
}
}
// for each number 0...5, yield an array of 3 numbers after it
let nested = ( for (n of generator())
[ for (i of after(n)) i ]
)
console.table(Array.from(nested));
// 1, 2, 3
// 2, 3, 4
// 3, 4, 5
// 4, 5, 6
// 5, 6, 7
// 6, 7, 8
{% endhighlight %}
Laziness
========
This is one of the most important advantages of generators over arrays and
things alike. The reason why I'm including this here is to give you a good
reason to write generators instead of arrays while generator comprehensions make
it extremely easy to write them this is a proof of their usefulness.
In programming, laziness means doing nothing until the results are requested or
in simpler terms, avoiding unnecessary work. For example, when you create an
array and map it, the result will be evaluated no matter you need it now or not,
you need the whole thing or a part of it, etc.
Take this example:
{% highlight javascript %}
let bigArray = new Array(100000);
for (let i = 0; i < 100000; i++) {
bigArray[i] = i;
}
let first = bigArray.map(n => n * n)[0];
console.log(first);
{% endhighlight %}
You know what happens here, first, map is evaluated, returning thousands of
squared numbers, then the first element is returned. We must allocate and
evaluate the whole squared array to be able to know about it's first or second
element.
Think of optimizing it, is it possible to get the desired result without storing
temporary arrays in memory? Can we get the first number directly without
consuming a big chunk of memory?
Yes, using generators, Look at this:
{% highlight javascript %}
let bigGenerator = function* () {
for (let i = 0; i < 100000; i++) {
yield i;
}
}
let squared = ( for (n of bigGenerator()) n * n );
console.log(squared.next());
{% endhighlight %}
Let's see what happens in this case. Here, we create a generator which will
yield numbers 0...100000, nothing is actually allocated or evaluated, we just
have a generator which will return a new number every time we call `next()`.
Then we use generator comprehension to create another generator which squares
the numbers our `bigGenerator()` yields, again, we don't evaluate or allocate
anything, we just create a generator which will call another generator's
`next()` method, square the results, and yield it.
Now when we call `squared.next()`, the `squared` generator calls
`bigArray().next()`, squares the results and yields it, it doesn't do any
unnecessary work, it's lazy.
[
![Generator diagram](/img/generator-diagram.png)
](/img/generator-diagram.png)
{% include caption.html text='Calling squared.next() 4 times' %}
If you profile heap/memory usage and running time, you will see the difference.
I have prepared a Node.js version of the test case. With the help of [`process.memoryUsage()`](https://nodejs.org/api/process.html#process_process_memoryusage) and [`console.time`](https://developer.mozilla.org/en-US/docs/Web/API/Console/time) we can easily see the difference.
It's a lot faster, with less space required, isn't that awesome?
[Repository: mdibaiee/array-vs-generator](https://github.com/mdibaiee/array-vs-generator)
![Array vs Generator performance](/img/array-vs-generator.png)
If you want to know more about lazy iterators, I recommend raganwald's [Lazy Iterables in JavaScript](http://raganwald.com/2015/02/17/lazy-iteratables-in-javascript.html).
More:
[MDN: Array Comprehensions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Array_comprehensions)
[MDN: Generator Comprehensions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Generator_comprehensions)
[MDN: for...of](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of)
[MDN: Iterators and Generators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators?redirectlocale=en-US&redirectslug=JavaScript%2FGuide%2FIterators_and_Generators)
[ES6 in Depth: Generators](https://hacks.mozilla.org/2015/05/es6-in-depth-generators/?utm_source=javascriptweekly&utm_medium=email)

View File

@ -1,221 +0,0 @@
---
layout: post
title: "Autocomplete using Tries"
date: 2015-07-24 09:44:00
permalink: autocomplete-predict-trie/
categories: programming
author: Mahdi
---
In this article, I'm going over creating an autocompletion/prediction system
using a data-structure called Trie, it's fast and easy to customize.
Trie
====
[Trie](https://en.wikipedia.org/wiki/Trie) is a simple data-structure most commonly used as a dictionary, it looks like so:
![Trie](/img/trie.jpg)
As you see, it's just a *tree*, a set of nodes connected to other [child] nodes, but the nodes have a special relationship:
Each child node extends it's parent with one extra character.
{% highlight javascript %}
// Something like this
child.value = parent.value + 'c';
{% endhighlight %}
It's pretty easy to traverse this tree and predict the next possible words.
Implementation
--------------
We're going to use ES6 classes to create our `Trie` and `Node` classes.
Let's start with our simple Node class:
{% highlight javascript %}
class Node {
constructor(value = '') {
this.value = value;
this.children = [];
}
}
{% endhighlight %}
Unlike [binary trees](https://en.wikipedia.org/wiki/Binary_tree) where each node has a left and right child, Trie nodes don't necessarily have a limit on how many children they can have.
Trie class:
{% highlight javascript %}
class Trie {
constructor() {
this.root = new Node();
}
add(value, parent = this.root) {
for (let i = 0, len = value.length; i < len; i++) {
let node = parent.children.find(child => child.value[i] === value[i]);
if (!node) {
node = new Node(value.slice(0, i + 1));
parent.children.push(node);
}
parent = node;
}
return parent;
}
find(value, parent = this.root) {
for (let i = 0, len = value.length; i < len; i++) {
parent = parent.children.find(child => child.value[i] === value[i]);
if (!parent) return null;
}
return parent;
}
}
{% endhighlight %}
Every Trie must have a root node with empty value, that's how our
single-character nodes follow the rule of Tries.
Ok, our first method, `add` handles adding a value to the trie, creating
necessary parent nodes for our value. At each iteration, we compare the `i`th
character of our value, with `i`th character of current node's children's value,
if we find one, we continue to search the next branch, else, we create a node
with `value.slice(0, i + 1)` and move onto the created node.
It might be a little hard to grasp at first, so I created a visualization of
this method to help you understand it easier, take a look:
[Trie Visualization](https://mdibaiee.github.io/autocomplete-trie/demo/add.html)
Then we have our find method, which searches for the given value in the trie.
The algorithm for searching is the same, comparing by index and moving to the
next branch.
# Example
That's it for our simple Trie class, now let's create an actual input with
autocomplete functionality using our Trie.
{% highlight html %}
<input>
<div class='results'>
</div>
{% endhighlight %}
I put some random names and stuff into three categories, results: [data.json](https://mdibaiee.github.io/autocomplete-trie/demo/data.json)
Now we have to create a Trie of our data:
{% highlight javascript %}
const trie = new Trie();
let data = {...}; // read from data.json
for (let category in data) {
for (let item of data[category]) {
let node = trie.add(item);
node.category = category;
}
}
{% endhighlight %}
As simple as that, our trie is made, it looks like this: [Data](https://mdibaiee.github.io/autocomplete-trie/demo/data.html)
Now, let's actually show results:
{% highlight javascript %}
const input = document.querySelector('input');
const results = document.querySelector('#results');
input.addEventListener('keyup', () => {
results.innerHTML = '';
const nodes = trie.find(input.value);
if (!nodes) return;
for (let node of nodes.children) {
const category = node.category ? `- ${node.category}` : '';
results.innerHTML += `<li>${node.value} ${category}</li>`;
}
});
{% endhighlight %}
[Autocomplete 1](https://mdibaiee.github.io/autocomplete-trie/1.html)
![Autocomplete 1](/img/autocomplete-1.png)
This will only show the instant-childs of the word entered, but that's not what
we want, we want to show *complete* words, how do we do that?
First, we need a way to detect complete words, we can have a flag to recognize
complete words, we can modify our `add` method to automatically flag whole words
or we can manually add the flag after adding the node, as we did by setting a
category for our words, so we already have a flag to recognize whole words,
that's our `category` property, now let's add a new method to our Trie class to
find whole words.
{% highlight javascript %}
...
findWords(value, parent = this.root) {
let top = this.find(value, parent);
if (!top) return [];
let words = [];
top.children.forEach(function getWords(node) {
if (node.category) words.push(node);
node.children.forEach(getWords);
});
return words;
}
...
{% endhighlight %}
And change our event listener like so:
{% highlight javascript %}
const input = document.querySelector('input');
const results = document.querySelector('#results');
input.addEventListener('keyup', () => {
results.innerHTML = '';
const nodes = trie.findWords(input.value); // << Change
if (!nodes.length) return; // << Change
for (let node of nodes) { // << Change
const category = node.category ? `- ${node.category}` : '';
results.innerHTML += `<li>${node.value} ${category}</li>`;
}
});
{% endhighlight %}
[Autocomplete 2](https://mdibaiee.github.io/autocomplete-trie/2.html)
![Autocomplete 2](/img/autocomplete-2.png)
Ta-daa!
We have our autocomplete working! Let's add zsh-like-tab-to-next-char functionality.
{% highlight javascript %}
input.addEventListener('keydown', e => {
// Tab Key
if (e.keyCode === 9) {
e.preventDefault();
const current = trie.find(input.value);
if (!current.children.length) return;
input.value = current.children[0].value;
}
});
{% endhighlight %}
That's it! We have an input with autocomplete and tab-to-next-char. Isn't it awesome?
[Final Result](https://mdibaiee.github.io/autocomplete-trie/2.html)
*Pst! I have a repository of algorithm implementations in ES6, you might want to
take a look!
[mdibaiee/harmony-algorithms](https://github.com/mdibaiee/harmony-algorithms)*

View File

@ -1,116 +0,0 @@
---
layout: post
title: "Open-source: The Good, The Bad and The Ugly"
date: 2015-10-13 06:15:00
permalink: open-source-good-bad-ugly/
categories: programming
author: Mahdi
---
I have been doing Open-source for a while, I don't call myself an "expert" or
something like that, but I'd like to share my opinion and experience on
contributing to, and maintaining open-source code.
So, I've been following and contributing to open-source projects for quite a
time, and I have had different experiences every time. There are always good and
bad experiences along a road, it's never a heaven, never a hell. I've had
contributions as small as fixing a typo in README, and as big as adding a new
feature to Firefox Developer Tools or refactoring a whole repository!
Here I'm going to share my experiences and what I've learned along the way that
you should consider if you want to take this road.
# The Good I love open-source, it's awesome how people share their efforts with
others, and others give feedback to the maintainer to make the software better.
It's an always-growing system, even if a maintainer stops maintaining, it's
possible to _fork_ a repository and continue it, although not as easy, but
possible.
The best part of doing open-source, in my opinion, is building connections and
learning from others.
Whether you are maintaining or contributing to a project, you are going to learn
new things, it just happens.
If you are a maintainer of a repository with a countable amount of users, you
are going to constantly learn your mistakes from others, finding these mistakes
by yourself is really hard, because you can't easily look at a subject _the
other way_, but users have this potential to look at your code with their eyes,
seeing mistakes you can't see.
If you are contributing, following or just exploring projects, you are
definitely going to learn, the solutions people suggest to a problem, the way
they communicate, etc. Usually, not always, the maintainer has a better
knowledge over the subject of project than you, so you are going to learn from
him and other contributors by reading their code or exploring the issues and how
they've been solved. I personally learned a lot this way. I would volunteer to
fix a bug, then the maintainer and other contributors would show up to give
their suggestions and ideas on the issue, which I would then learn from. I also
subscribe to interesting issues that I don't know how to fix to see how they get
solved.
# The Bad First off, the most annoying thing about open-source contributions is
that people (I'm looking at you, maintainers) think that contributors are
jobless bored people who don't know how to spend their time and have come to
waste some time on some random open-source project, NO, seriously.
I have a job, I totally care about my time and I'm not making a Pull-request
because I'm bored.
Now, why is that important to know: it has happened to me a couple of times that
I ask on an issue:
_"- Okay, I'm interested, what **exactly** has to be done?"_
_"- Great, please do x, y, z"_
_... some time later_
_"- Here is x, y and z, please review and merge"
_"- Oh, thank you very much, but you know, now that I think of it, I don't want
x, y or even z. Closing."
and I'm like:
<!-- ![Are you kidding me?](/img/are-you-kidding-me.jpg) --> <img alt='Are you
kidding me?' src='/img/are-you-kidding-me.jpg' />
{% include caption.html text='Are you kidding me?' %}
This is the worst thing that can happen to you, try to avoid it, you don't want
your valuable time wasted.
How to avoid it you ask, there is a sign that I've found which leads to this
problem most of the time and that's **lack of clear specification**, just like
with clients, if the maintainer doesn't specify what should be done, you should
stop.
It happened to me, just like the past discussion, except he didn't tell me
_"Please do x, y, z"_, he made himself look too busy and said: _"The title says
it all"_, no, it doesn't say it all. "x, y and z" can be implemented in `2^9`
ways, and sadly, you are not going to accept the `192`th way, as you "don't like
it". Do not get trapped in these time-wasting situations, I wish maintainers
understood how valuable people's times are.
# The Ugly The sad part about open-source is, if the maintainer decides not to
support the project anymore, people will _kind of_ suffer. If the maintainer
abandons the project, the project is *almost* doomed, as forking and continuing
is really hard, reading the code from bottom up and understanding it isn't easy,
and as there is no outcome, people usually decide to abandon a project once they
lose interest in the topic.
If I personally lose interest in a project I've made, I'll abandon it, I will
try to guide new users through but I usually don't offer as much support, I have
more important things to do, it's really sad, but true.
To prevent this from happening, you must be able to make money out of your
project, or your project must be really interesting and challenging to keep you
working on it.
------
That's it, please note that everything you read here is my opinion, it's not a
rule, not a judgment, it's my opinion and experience. If you would like to
discuss this further, put a comment below or reach me at
[twitter](https://twitter.com/mdibaiee).

View File

@ -4,7 +4,6 @@ title: "Immortals go extinct"
permalink: immortals-go-extinct/
categories: life
excerpt_separator: <!--more-->
author: Mahdi
---
We are all going to die, we all know that well.<br /><br /> Now I want to take

View File

@ -4,7 +4,6 @@ title: "Stop High-Frequency Fuck-ups"
permalink: stop-high-frequency-fuck-ups/
categories: life
excerpt_separator: <!--more-->
author: Mahdi
---
**High-Frequency Fuck-Ups**:

View File

@ -4,7 +4,6 @@ title: "Don't chase: Become the good one"
permalink: dont-chase-become-the-good-one/
categories: life
excerpt_separator: <!--more-->
author: Mahdi
---
When it comes to relationships, most (unsuccessful) people are _chasing_ the

View File

@ -7,7 +7,6 @@ categories:
- primitive-living
- travel
excerpt_separator: <!--more-->
author: Mahdi
---
![general view of the forest](/img/primitive-living-0.jpg)

View File

@ -4,7 +4,6 @@ title: "Difference between Travis CI tests: PR and Push"
permalink: travis-ci-pr-push/
categories: programming
excerpt_separator: <!--more-->
author: Mahdi
---
I just want to leave this here as I often tend to look it up myself and the

View File

@ -6,7 +6,6 @@ categories:
- life
- diy
excerpt_separator: <!--more-->
author: Mahdi
---
![a view of the stand + kindle](/img/kindle-stand/1.jpg)

View File

@ -8,7 +8,6 @@ categories:
- math
math: true
toc: true
author: Mahdi
---
I wanted to get proficient in Haskell so I decided to follow [An [Essential]

View File

@ -5,7 +5,6 @@ date: 2017-10-19
permalink: mathematical-induction-proving-tiling-methods/
categories: math
math: true
author: Mahdi
---
On my way towards self-taught data science, I've stumbled upon the need to be

View File

@ -5,7 +5,6 @@ date: 2019-02-11
permalink: self-hosted/
categories: life
excerpt_separator: <!--more-->
author: Mahdi
---
Since 3 years ago, I have always been eager to move away from Google and other

View File

@ -4,7 +4,6 @@ title: "Iran Sanctions: A Story of Discrimination and Isolation"
date: 2019-07-27 17:13:46
permalink: sanctions-discrimination-isolation-iran/
categories: life, iran
author: Mahdi
---
Let me take you through a story on what it feels like to be isolated from the

View File

@ -4,7 +4,6 @@ title: "Depression as an Umwelt"
date: 2021-02-14 00:00:00
permalink: depression-as-an-umwelt/
categories: personal, philosophy
author: Mahdi
---
[Von Uexkülls A Stroll Through the Worlds of Animals and

View File

@ -4,7 +4,6 @@ title: "A Fear of Worlds Unknown"
date: 2021-04-05 00:00:00
permalink: a-fear-of-worlds-unknown/
categories: personal, philosophy
author: Mahdi
---
When it comes to ethics, the impossibly hard question of ethics, we get dizzy when we try to think about relativity of it. The ideas of 4E cognition and imminence have been closer to my heart than the alternative approaches, however, I have always been dumbfounded by the question of ethics in such a framework.

View File

@ -5,7 +5,6 @@ subtitle: "An Alternative Definition of Objectivity for Rigid Scientists"
date: 2021-10-30 12:57:46
permalink: alternative-objectivity-and-inherent-subjectivity/
categories: philosophy
author: Mahdi
---
As a computer scientist and someone who loves

View File

@ -4,7 +4,6 @@ title: "My first contribution to Linux Kernel: Step by step"
date: 2021-11-06 00:00:00
permalink: first-linux-contribution/
categories: programming
author: Mahdi
published: false
---

View File

@ -5,7 +5,6 @@ subtitle: Using `rust-lldb` to understand rust memory internals
date: 2022-06-16 00:00:00
permalink: rust-box-str-vs-string/
categories: programming
author: Mahdi
---
Today I and a friend went down a rabbit hole about Rust and how it manages the
@ -28,10 +27,10 @@ bytes).
I will be using `rust-lldb` throughout this post to understand what is going on
in the rust programs we write and run. The source code for this blog post is
available on
[mdibaiee/rust-memory-playground](https://git.mahdi.blog/mahdi/rust-memory-playground).
[rust-memory-playground](https://git.theread.me/thereadme/rust-memory-playground).
```bash
git clone https://git.mahdi.blog/mahdi/rust-memory-playground
git clone https://git.theread.me/thereadme/rust-memory-playground
cd rust-memory-playground
```
@ -63,7 +62,7 @@ $ cargo build && rust-lldb target/debug/stack-program
Breakpoint 1: where = stack-program`stack_program::add_ten::h42edbf0bdcb04851 + 24 at main.rs:3:5, address = 0x0000000100001354
(lldb) run
Process 65188 launched: '/Users/mahdi/workshop/rust-memory-playground/target/debug/stack-program' (arm64)
Process 65188 launched: '/Users/workshop/rust-memory-playground/target/debug/stack-program' (arm64)
Process 65188 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x0000000100001354 stack-program`stack_program::add_ten::h42edbf0bdcb04851(a=5) at main.rs:3:5
@ -154,7 +153,7 @@ $ cargo build && rust-lldb target/debug/stack-and-heap-program
Breakpoint 1: where = stack-and-heap-program`stack_and_heap_program::main::ha895783273646dc7 + 100 at main.rs:4:5, address = 0x0000000100005264
(lldb) run
Process 67451 launched: '/Users/mahdi/workshop/rust-memory-playground/target/debug/stack-and-heap-program' (arm64)
Process 67451 launched: '/Users/workshop/rust-memory-playground/target/debug/stack-and-heap-program' (arm64)
Process 67451 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x0000000100005264 stack-and-heap-program`stack_and_heap_program::main::ha895783273646dc7 at main.rs:4:5
@ -202,7 +201,7 @@ And here we go again:
Breakpoint 1: where = string-program`string_program::main::h64ca96ee87b0ceaf + 44 at main.rs:3:5, address = 0x000000010000476c
(lldb) run
Process 68317 launched: '/Users/mahdi/workshop/rust-memory-playground/target/debug/string-program' (arm64)
Process 68317 launched: '/Users/workshop/rust-memory-playground/target/debug/string-program' (arm64)
Process 68317 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x000000010000476c string-program`string_program::main::h64ca96ee87b0ceaf at main.rs:3:5

View File

@ -5,7 +5,6 @@ subtitle: "Videogames as an embodied activity"
date: 2022-07-23 00:00:00
permalink: embodying-the-avatar-videogames/
categories: programming
author: Mahdi
---
Videogames are a pervasive part of lives of children and adults alike, with 73%

View File

@ -5,7 +5,6 @@ subtitle: "Publishing raw version of my blog posts"
date: 2022-07-27 00:00:00
permalink: raw-permalinks-for-accessibility/
categories: programming
author: Mahdi
---
I realised that my blog and its content, even though very simple and
@ -20,15 +19,15 @@ prepending `/raw` to the URL of my posts.
Try it out:
```
curl https://mahdi.blog/raw/raw-permalinks-for-accessibility/
curl https://mahdi.blog/raw/embodying-the-avatar-videogames/
curl https://mahdi.blog/raw/rust-box-str-vs-string/
curl https://theread.me/raw/raw-permalinks-for-accessibility/
curl https://theread.me/raw/embodying-the-avatar-videogames/
curl https://theread.me/raw/rust-box-str-vs-string/
```
You can get a raw listing of my blog posts at `/raw/`:
```
curl https://mahdi.blog/raw/
curl https://theread.me/raw/
```
To make this easily readable on small screens and terminals, I used vim's
@ -42,8 +41,8 @@ And to reformat my posts, I went over my text lines (I avoided breaking code
sample lines), and used `gq` to reformat each section.
The source code for my blog is available on my
[git](https://git.mahdi.blog/mahdi/mahdi.blog) server, you can find the source
[git](https://git.theread.me/thereadme/theread.me) server, you can find the source
for [the raw
plugin](https://git.mahdi.blog/mahdi/mahdi.blog/src/branch/master/_plugins/raw.rb)
plugin](https://git.theread.me/thereadme/theread.me/src/branch/master/_plugins/raw.rb)
as well as the [layout
file](https://git.mahdi.blog/mahdi/mahdi.blog/src/branch/master/_layouts/raw.html).
file](https://git.theread.me/thereadme/theread.me/src/branch/master/_layouts/raw.html).

View File

@ -5,7 +5,6 @@ subtitle: "A tiny introduction to Rukiga"
date: 2022-09-06 00:00:00
permalink: rukiga-african-language/
categories: travel, language
author: Mahdi
---
During my trip to south of Uganda I interacted with people who mainly spoke a
@ -150,7 +149,7 @@ as Mushana.
| Esati | Shirt |
| Eshero | Hippo |
| Emporogoma | Lion |
| Eizina ryangye Mahdi | My name is Mahdi |
| Eizina ryangye ... | My name is ... |
|Ndaruga Iran| Im from Iran|
|Nashemererwa kubanimwe| Im happy to be here|
|Webare munonga| Thank you very much|

View File

@ -5,7 +5,6 @@ subtitle: "Travel journal "
date: 2022-09-10 00:00:00
permalink: uganda-trip/
categories: travel
author: Mahdi
---
I and a friend of mine from Iran decided to go to Uganda to explore the country,
@ -254,7 +253,7 @@ laughter! The preacher would crack jokes in between his preach and people would
chuckle, which I found to be nice. Tutamuzongoza taught me how to introduce
myself with these phrases:
Eizina ryangye Mahdi: My name is Mahdi
Eizina ryangye ...: My name is ...
Ndaruga Iran: Im from Iran

View File

@ -5,7 +5,6 @@ subtitle: "A Tiny Introduction"
date: 2022-09-15 00:00:00
permalink: middle-persian-pahlavi-script/
categories: language
author: Mahdi
custom_head: <link rel="stylesheet" href="/css/khusro.css"">
---

View File

@ -5,7 +5,6 @@ date: 2022-10-15 00:00:00
permalink: parsi-minevisam/
lang: fa
categories: language
author: Mahdi
---
از روی کنجکاوی، بر آن که تا چه اندازه در زبانی که با آن گویش میکنیم، از واژه‌های عربی، فرانسوی، انگلیسی و یا دیگر زبان‌ها بهره میبریم، در این نوشتار و نوشتار‌های آینده‌ی خود کوشش میکنم تا از واژه‌های وام گرفته شده از زبان‌های دیگر بهره نگیرم.

View File

@ -5,7 +5,6 @@ date: 2022-10-21 00:00:00
permalink: parsi-khodemooni/
lang: fa
categories: language
author: Mahdi
---

View File

@ -4,7 +4,6 @@ title: "Why I don't recommend Ireland when asked"
date: 2022-10-27 00:00:00
permalink: i-dont-recommend-ireland/
categories: personal, ireland
author: Mahdi
---
I have been living in Ireland for the past three years, and when asked about

View File

@ -6,7 +6,6 @@ date: 2022-11-04 00:00:00
permalink: iran-1401-timeline/
categories: iran, history
published: false
author: Mahdi
custom_head: <link rel="stylesheet" href="/css/timeline.css"">
---

View File

@ -5,7 +5,6 @@ subtitle: "Readings on Iran's nationalisation of oil"
date: 2022-11-13 00:00:00
permalink: mosaddegh-iran-national-oil/
categories: iran, history
author: Mahdi
---
I have been reading Mosaddegh's memoirs, specifically the two books _Brief

View File

@ -6,7 +6,6 @@ date: 2022-11-15 00:00:00
permalink: animals-and-machines/
categories: personal, science
math: true
author: Mahdi
---
I find comparing animals and machines absurd, because of course, animals win!

View File

@ -5,7 +5,6 @@ subtitle: "...میخواهم دم بگیرم"
date: 2022-11-27 00:00:00
permalink: i-want-to-breathe/
categories: personal
author: Mahdi
excerpt_separator: <!--more-->
---

View File

@ -5,7 +5,6 @@ subtitle: "آیا زندگی زیباست؟"
date: 2023-01-06 00:00:00
permalink: is-life-beautiful/
categories: personal
author: Mahdi
published: false
excerpt_separator: <!--more-->
---

View File

@ -5,7 +5,6 @@ date: 2023-02-27 00:00:00
permalink: zaban-va-farhang/
lang: fa
categories: language
author: Mahdi
---
هنگامی که از پارسی‌گویی با دوستانم سخن میگویم، پرسشی که بسیار آورده می‌شود، «چرا» است. این پرسش بجا است، برای همین در این نوشته میکوشم از دید خودم پاسخی به این پرسش بدهم.

View File

@ -5,7 +5,6 @@ subtitle: "Stillhet!"
date: 2023-06-02 00:00:00
permalink: norway/
categories: personal
author: Mahdi
excerpt_separator: <!--more-->
published: false
---