raw version of blog posts

This commit is contained in:
Mahdi Dibaiee 2022-07-27 09:48:57 +01:00
parent ae0fc73214
commit 908f0c65d5
30 changed files with 1812 additions and 763 deletions

View File

@ -1,3 +0,0 @@
mahdi.blog
==========

View File

@ -19,31 +19,6 @@ collections:
art: art:
title: art title: art
permalink: /art/:path/ permalink: /art/:path/
#math:
#title: math
#output: true
#permalink: /math/:path/
#path: /math
#programming:
#title: programming
#output: true
#permalink: /programming/:path/
#path: /programming
#life:
#title: life
#output: true
#permalink: /life/:path/
#path: /life
#travel:
#title: travel
#output: true
#permalink: /travel/:path/
#path: /travel
#philosophy:
#title: philosophy
#output: true
#permalink: /philosophy/:path/
#path: /philosophy
contentsLabel: "Table of Contents" contentsLabel: "Table of Contents"
showToggleButton: true showToggleButton: true

View File

@ -1,7 +0,0 @@
<div class="share-page">
Share in
<a href="https://twitter.com/intent/tweet?text={{ page.title }}&url={{ site.url }}{{ page.url }}&via={{ site.twitter_username }}&related={{ site.twitter_username }}" rel="nofollow" target="_blank" title="Share on Twitter">Twitter</a>
<a href="https://facebook.com/sharer.php?u={{ site.url }}{{ page.url }}" rel="nofollow" target="_blank" title="Share on Facebook">Facebook</a>
<a href="https://plus.google.com/share?url={{ site.url }}{{ page.url }}" rel="nofollow" target="_blank" title="Share on Google+">Google+</a>
</div>

View File

@ -12,6 +12,7 @@ layout: default
<span>{{ page.date | date: "%b %-d, %Y" }}</span> <span>{{ page.date | date: "%b %-d, %Y" }}</span>
{% if page.meta %} • <span>{{ page.meta }}</span>{% endif %} {% if page.meta %} • <span>{{ page.meta }}</span>{% endif %}
<span>Reading time: {{ content | reading_time }}</span> <span>Reading time: {{ content | reading_time }}</span>
<span><a href="/raw{{ page.url }}">raw</a></span>
</p> </p>
</div> </div>
@ -19,8 +20,6 @@ layout: default
{{ content }} {{ content }}
</article> </article>
{% include share.html %}
<div id="commento"></div> <div id="commento"></div>
<script defer <script defer
src="//commento.mahdi.blog/js/commento.js"> src="//commento.mahdi.blog/js/commento.js">

5
_layouts/raw.html Normal file
View File

@ -0,0 +1,5 @@
<pre>
# {{ page.title }}
{{ page.content }}
</pre>

30
_plugins/raw.rb Normal file
View File

@ -0,0 +1,30 @@
module RawGenerator
class Generator < Jekyll::Generator
priority :lowest
def generate(site)
existing_posts = site.posts.docs.to_a
for i in 0..(existing_posts.size - 1) do
post = existing_posts[i]
new_page = RawPage.new(site, post)
site.pages << new_page
end
end
end
class RawPage < Jekyll::Page
def initialize(site, post)
@site = site # the current site instance.
@base = site.source # path to the source directory.
@dir = "raw" # the directory the page will reside in.
@name = post.name # basically @basename + @ext.
@content = post.content
@data = post.data.clone
@relative_path = post.relative_path.sub("_posts", "raw")
data["permalink"] = 'raw/%{permalink}' % {permalink: post.permalink}
@ext = '.md'
data["layout"] = 'raw'
end
end
end

View File

@ -7,20 +7,32 @@ categories: programming
author: Mahdi 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. 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. 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. 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/)). CSS Filters are supported by most modern browsers ([Can I Use CSS
Filters](http://caniuse.com/#feat=css-filters)), if your browser doesn't
I don't like long-bla-bla-articles, so let's get to it. support this, please change your browser (I recommend
[Firefox](https://www.mozilla.org/en-US/firefox/new/)).
Introduction 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. 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): A simple demo showing blur, contrast and brightness combined (hover over image):
@ -34,9 +46,11 @@ Length
Percentage 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. 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, I'm not going to repeat \`Adjusts ${x} level\` like a parrot. Most filters explain themselves:
* brightness * brightness
* contrast * contrast
@ -48,19 +62,28 @@ Percentage
### invert ### 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. 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> <iframe width="100%" height="100" src="//jsfiddle.net/mdibaiee/373dnby8/embedded/result,css" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
### opacity ### 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. 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 Angle
----- -----
hue-rotate is the only function to accept an angle value (degree / radian). hue-rotate is the only function to accept an angle value (degree / radian).
###hue-rotate ###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). 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> <iframe width="100%" height="300" src="//jsfiddle.net/mdibaiee/smk922fh/embedded/result,css" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
@ -69,13 +92,20 @@ Special
These filter's don't fit in any of the groups above, they have special/mixed values. These filter's don't fit in any of the groups above, they have special/mixed values.
### drop-shadow ### 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. 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. 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 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 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) ![drop-shadow explained](/img/dropshadow.gif)
@ -84,7 +114,9 @@ Special
<iframe width="100%" height="150" src="//jsfiddle.net/mdibaiee/z077vbs0/embedded/result,css" allowfullscreen="allowfullscreen" frameborder="0"></iframe> <iframe width="100%" height="150" src="//jsfiddle.net/mdibaiee/z077vbs0/embedded/result,css" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
### url ### 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: 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 %} {% highlight css %}
filter: url(/example.svg#filter) filter: url(/example.svg#filter)
@ -99,7 +131,9 @@ filter: url(/example.svg#filter)
{% include caption.html text='Source: http://www.adobe.com/devnet/archive/html5/articles/css-shaders.html' %} {% 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: 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) * [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) * [Introducing CSS shaders: Cinematic effects for the web](http://www.adobe.com/devnet/archive/html5/articles/css-shaders.html)
@ -108,7 +142,8 @@ filter: url(/example.svg#filter)
Gotchas Gotchas
======= =======
You now have a basic understanding of filters, good. Here are a few gotchas you'd better know. You now have a basic understanding of filters, good. Here are a few gotchas
you'd better know.
Order matters Order matters
------------- -------------
@ -118,13 +153,15 @@ The order in which filters are applied matters. Take this example:
filter: blur(10px) contrast(2); filter: blur(10px) contrast(2);
{% endhighlight %} {% endhighlight %}
Hey, browser, please blur the element, then double the contrast of the blurred element. (blurred parts have their contrast affected) Hey, browser, please blur the element, then double the contrast of the blurred
element. (blurred parts have their contrast affected)
{% highlight css %} {% highlight css %}
filter: contrast(2) blur(10px); filter: contrast(2) blur(10px);
{% endhighlight %} {% endhighlight %}
Hey browser, please double the contrast of my element, then blur it out. (high contrast image is blurred normally) Hey browser, please double the contrast of my element, then blur it out. (high
contrast image is blurred normally)
Here is the actual comparison: Here is the actual comparison:
@ -133,14 +170,22 @@ Here is the actual comparison:
Inheritance 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. 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> <iframe width="100%" height="300" src="//jsfiddle.net/mdibaiee/o40d7cs7/embedded/result,css" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
Implementation 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). 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 Go Wild
======= =======

View File

@ -12,9 +12,12 @@ is a new API used to communicate between same-origin tabs opened by the same use
Why Why
=== ===
Let's say you open two GitHub tabs, the [rust repository](https://github.com/rust-lang/rust) and [your stars](https://github.com/stars) page. You decide to star the awesome rust repository, but then you have to Let's say you open two GitHub tabs, the [rust
refresh your stars page to see your new star. That's sad. There must be a way for GitHub to refresh repository](https://github.com/rust-lang/rust) and [your
your stars page in case you star something in another tab, right? stars](https://github.com/stars) page. You decide to star the awesome rust
repository, but then you have to refresh your stars page to see your new star.
That's sad. There must be a way for GitHub to refresh your stars page in case
you star something in another tab, right?
![Broadcast Channels, SATISFIED](/img/broadcast-channels.jpg) ![Broadcast Channels, SATISFIED](/img/broadcast-channels.jpg)
@ -48,11 +51,14 @@ BroadcastChannels are pretty easy, here I'm going over the small details.
Creating channels Creating channels
----------------- -----------------
BroadcastChannels are constructed with a single argument, their name. Browsing contexts should use BroadcastChannels are constructed with a single argument, their name. Browsing
this name to communicate over a specified channel. There's no limit to how many channels you can create. contexts should use this name to communicate over a specified channel. There's
no limit to how many channels you can create.
In the first sentence of article I said it's used to communicate between tabs, but it's actually "browsing contexts". In the first sentence of article I said it's used to communicate between tabs,
[Browsing contexts](http://www.w3.org/TR/html5/browsers.html#browsing-context) are any environments owning a `Document`, e.g. tabs, windows, iframes, etc. but it's actually "browsing contexts". [Browsing
contexts](http://www.w3.org/TR/html5/browsers.html#browsing-context) are any
environments owning a `Document`, e.g. tabs, windows, iframes, etc.
{% highlight javascript %} {% highlight javascript %}
var channel = new BroadcastChannel('star'); var channel = new BroadcastChannel('star');
@ -79,7 +85,9 @@ Channels inherit from [`EventTarget`](https://developer.mozilla.org/en-US/docs/W
Channels have only one event: Channels have only one event:
### message ### message
The event object passed to this event is a [`MessageEvent`](https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent) with the `data` property set to the actual message sent using `postMessage`. The event object passed to this event is a
[`MessageEvent`](https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent)
with the `data` property set to the actual message sent using `postMessage`.
--- ---
@ -88,7 +96,9 @@ Another example
Let's Fix GitHub Let's Fix GitHub
---------------- ----------------
Okay, let's try something cool, I promise you will love it. Open a browser with [BroadcastChannel support](http://caniuse.com/#feat=broadcastchannel) and Install [GreaseMonkey](http://www.greasespot.net/). Okay, let's try something cool, I promise you will love it. Open a browser with
[BroadcastChannel support](http://caniuse.com/#feat=broadcastchannel) and
Install [GreaseMonkey](http://www.greasespot.net/).
You have to add two scripts, one for repository pages, and one for the stars page. You have to add two scripts, one for repository pages, and one for the stars page.
@ -134,4 +144,5 @@ is open, and your stars page will refresh immediately.
That's it, I really like this API as it's best of both worlds, simple and useful. That's it, I really like this API as it's best of both worlds, simple and useful.
There are a lot of things which can be done with help of BroadcastChannels, I would love to hear your feedback on this API. There are a lot of things which can be done with help of BroadcastChannels, I
would love to hear your feedback on this API.

View File

@ -7,16 +7,25 @@ categories: programming
author: Mahdi author: Mahdi
--- ---
Array comprehension is a new feature proposed for ES7, with a new syntax Array comprehension is a new feature proposed for ES7, with a new syntax to
to create new arrays from existing [iterables](http://www.2ality.com/2015/02/es6-iteration.html), create new arrays from existing
comprehensions can replace map and filter. [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 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. 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. 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). 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 Syntax
====== ======
@ -83,12 +92,15 @@ console.table(Array.from(nested));
Laziness Laziness
======== ========
This is one of the most important advantages of generators over arrays and things alike. This is one of the most important advantages of generators over arrays and
The reason why I'm including this here is to give you a good reason to write generators instead of arrays things alike. The reason why I'm including this here is to give you a good
while generator comprehensions make it extremely easy to write them — this is a proof of their usefulness. 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. In programming, laziness means doing nothing until the results are requested or
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. 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: Take this example:
@ -102,11 +114,14 @@ let first = bigArray.map(n => n * n)[0];
console.log(first); console.log(first);
{% endhighlight %} {% endhighlight %}
You know what happens here, first, map is evaluated, returning thousands of squared numbers, then You know what happens here, first, map is evaluated, returning thousands of
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. 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 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? temporary arrays in memory? Can we get the first number directly without
consuming a big chunk of memory?
Yes, using generators, Look at this: Yes, using generators, Look at this:
@ -122,11 +137,17 @@ let squared = ( for (n of bigGenerator()) n * n );
console.log(squared.next()); console.log(squared.next());
{% endhighlight %} {% endhighlight %}
Let's see what happens in this case. Let's see what happens in this case. Here, we create a generator which will
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()`. yield numbers 0...100000, nothing is actually allocated or evaluated, we just
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. 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. 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) ![Generator diagram](/img/generator-diagram.png)

View File

@ -7,7 +7,8 @@ categories: programming
author: Mahdi 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. 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
==== ====
@ -76,20 +77,27 @@ class Trie {
} }
} }
{% endhighlight %} {% endhighlight %}
Every Trie must have a root node with empty value, that's how our single-character nodes follow the rule of Tries. 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. Ok, our first method, `add` handles adding a value to the trie, creating
At each iteration, we compare the `i`th character of our value, with `i`th character of current node's children's value, necessary parent nodes for our value. At each iteration, we compare the `i`th
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. 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: 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) [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. 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 # Example
========
That's it for our simple Trie class, now let's create an actual input with autocomplete functionality using our Trie. That's it for our simple Trie class, now let's create an actual input with
autocomplete functionality using our Trie.
{% highlight html %} {% highlight html %}
<input> <input>
@ -137,12 +145,15 @@ input.addEventListener('keyup', () => {
{% endhighlight %} {% endhighlight %}
[Autocomplete 1](https://mdibaiee.github.io/autocomplete-trie/1.html) [Autocomplete 1](https://mdibaiee.github.io/autocomplete-trie/1.html)
![Autocomplete 1](/img/autocomplete-1.png) ![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? 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 First, we need a way to detect complete words, we can have a flag to recognize
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, complete words, we can modify our `add` method to automatically flag whole 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 or we can manually add the flag after adding the node, as we did by setting a
whole words. 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 %} {% highlight javascript %}
... ...
@ -205,4 +216,6 @@ That's it! We have an input with autocomplete and tab-to-next-char. Isn't it awe
[Final Result](https://mdibaiee.github.io/autocomplete-trie/2.html) [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)* *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

@ -7,44 +7,58 @@ categories: programming
author: Mahdi author: Mahdi
--- ---
I have been doing Open-source for a while, I don't call myself an "expert" or something like that, I have been doing Open-source for a while, I don't call myself an "expert" or
but I'd like to share my opinion and experience on contributing to, and maintaining open-source code. 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, So, I've been following and contributing to open-source projects for quite a
and I have had different experiences every time. There are always good and bad experiences time, and I have had different experiences every time. There are always good and
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 bad experiences along a road, it's never a heaven, never a hell. I've had
as adding a new feature to Firefox Developer Tools or refactoring a whole repository! 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 Here I'm going to share my experiences and what I've learned along the way that
if you want to take this road. you should consider if you want to take this road.
The Good # 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.
I love open-source, it's awesome how people share their efforts with others, and others give feedback to It's an always-growing system, even if a maintainer stops maintaining, it's
the maintainer to make the software better. It's an always-growing system, even if a maintainer stops maintaining, possible to _fork_ a repository and continue it, although not as easy, but
it's possible to _fork_ a repository and continue it, although not as easy, but possible. possible.
The best part of doing open-source, in my opinion, is building connections and learning from others. 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. 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, If you are a maintainer of a repository with a countable amount of users, you
finding these mistakes by yourself is really hard, because you can't easily look at a subject _the other way_, are going to constantly learn your mistakes from others, finding these mistakes
but users have this potential to look at your code with their eyes, seeing mistakes you can't see. 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, If you are contributing, following or just exploring projects, you are
the way they communicate, etc. definitely going to learn, the solutions people suggest to a problem, the way
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 they communicate, etc. Usually, not always, the maintainer has a better
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. 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 # 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
First off, the most annoying thing about open-source contributions is that people (I'm looking at you, maintainers) think jobless bored people who don't know how to spend their time and have come to
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. 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. 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: 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?"_ _"- Okay, I'm interested, what **exactly** has to be done?"_
@ -54,34 +68,49 @@ _... some time later_
_"- Here is x, y and z, please review and merge" _"- 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." _"- 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: and I'm like:
<!-- ![Are you kidding me?](/img/are-you-kidding-me.jpg) --> <!-- ![Are you kidding me?](/img/are-you-kidding-me.jpg) --> <img alt='Are you
<img alt='Are you kidding me?' src='/img/are-you-kidding-me.jpg' /> kidding me?' src='/img/are-you-kidding-me.jpg' />
{% include caption.html text='Are you kidding me?' %} {% 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. 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. 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 It happened to me, just like the past discussion, except he didn't tell me
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, _"Please do x, y, z"_, he made himself look too busy and said: _"The title says
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. 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 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
The sad part about open-source is, if the maintainer decides not to support the project anymore, abandons the project, the project is *almost* doomed, as forking and continuing
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. 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 If I personally lose interest in a project I've made, I'll abandon it, I will
don't offer as much support, I have more important things to do, it's really sad, but true. 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 To prevent this from happening, you must be able to make money out of your
and challenging to keep you working on it. 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). 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

@ -7,67 +7,78 @@ excerpt_separator: <!--more-->
author: Mahdi author: Mahdi
--- ---
We are all going to die, we all know that well.<br /><br /> We are all going to die, we all know that well.<br /><br /> Now I want to take
Now I want to take you to a world of immortals where humans don't die, you to a world of immortals where humans don't die, they live and live and live
they live and live and live and... you know, live. From now on, pretend I'm a human and... you know, live. From now on, pretend I'm a human on this world of
on this world of immortals, I'm immortal bitches. immortals, I'm immortal bitches.
![immortals chatting](/img/immortals.jpg) ![immortals chatting](/img/immortals.jpg) {% include caption.html text='There is
{% include caption.html text='There is no campfire because they don\'t need it' %} no campfire because they don\'t need it' %}
<!--more--> <!--more--> ---
---
In this world, there is no excitement in jumping from a cliff or doing flips over walls In this world, there is no excitement in jumping from a cliff or doing flips
or pretending to be a bird or even loving each other, in general, there is no over walls or pretending to be a bird or even loving each other, in general,
excitement in any experience, because there is nothing to miss if I don't do that right now, there is no excitement in any experience, because there is nothing to miss if I
I will always have another chance to do that again, even if that's going to be a thousand years from now, don't do that right now, I will always have another chance to do that again,
because you know, we're all good at waiting here. even if that's going to be a thousand years from now, because you know, we're
all good at waiting here.
There is no technology and no fast transportation system here, There is no technology and no fast transportation system here, because, hell,
because, hell, who gives a fuck about fast transportation systems. who gives a fuck about fast transportation systems.
Who gives a shit about tools to harvest more food, or something you can write with, Who gives a shit about tools to harvest more food, or something you can write
you can know about our meaningless past as much as you want, there are always people to tell you about that. with, you can know about our meaningless past as much as you want, there are
always people to tell you about that.
Who cares if 2 + 2 = 4 or 5, I'm not going to die if the non-existing plane crashes because of an error, Who cares if 2 + 2 = 4 or 5, I'm not going to die if the non-existing plane
none of that is needed. crashes because of an error, none of that is needed.
We have an infinite amount of time to explore the globe, but we don't, We have an infinite amount of time to explore the globe, but we don't, because
because there is no fun in doing that, how is that, you might ask. Someone from your world told me there is no fun in doing that, how is that, you might ask. Someone from your
I should explain it this way: world told me I should explain it this way:
> Simple mathematics we know says, in an infinite timespan, no other timespan is significant, basically, > Simple mathematics we know says, in an infinite timespan, no other timespan is
any number divided by infinity yields zero. Your neighbour could tell you about how he spent a thousand years significant, basically, any number divided by infinity yields zero. Your
exploring Earth, eating bugs and trying different methods to kill himself, and you could tell him neighbour could tell you about how he spent a thousand years exploring Earth,
he literally spent 0% of his life doing all that, same as you, who just stood there. eating bugs and trying different methods to kill himself, and you could tell him
> he literally spent 0% of his life doing all that, same as you, who just stood
> ![any fucking number / infinity = 0](/img/division-by-infinity.jpg) there. > > ![any fucking number / infinity = 0](/img/division-by-infinity.jpg)
Now I don't understand much of that, but I had enough time, and nothing else to do, to repeat this to myself Now I don't understand much of that, but I had enough time, and nothing else to
since he told me that until now. do, to repeat this to myself since he told me that until now.
Here, in this world, we can't suicide, if that was an option, we know well that we would go extinct Here, in this world, we can't suicide, if that was an option, we know well that
soon after finding out the fact that we are immortals, we really don't like this numb life. we would go extinct soon after finding out the fact that we are immortals, we
really don't like this numb life.
--- ---
_Pooof_ _Pooof_
Alright I'm back. You see, we need death, we really do, without death our lives Alright I'm back. You see, we need death, we really do, without death our lives
would be meaningless, we would have no purpose. Okay we would probably still [contribute to increase of entropy of the universe](https://www.youtube.com/watch?v=HxTnqKuNygE), but that's not what we _want_ to be here for, we want a higher purpose in life, and it's death that gifts us this would be meaningless, we would have no purpose. Okay we would probably still
higher purpose. [contribute to increase of entropy of the
universe](https://www.youtube.com/watch?v=HxTnqKuNygE), but that's not what we
_want_ to be here for, we want a higher purpose in life, and it's death that
gifts us this higher purpose.
When I was a kid, I was told that in order to stay alive after death, you have to submit your name on this planet, and When I was a kid, I was told that in order to stay alive after death, you have
in this universe if possible. I know, that might sound ridiculous, but aren't we all fighting for the same thing, but in our own to submit your name on this planet, and in this universe if possible. I know,
ways? Maybe you just want to be remembered between a specific group of people (and that's perfectly fine) or you might that might sound ridiculous, but aren't we all fighting for the same thing, but
actually want to become a global role model, like Gandhi, Albert Einstein and people alike, it doesn't matter, what matters is, in our own ways? Maybe you just want to be remembered between a specific group
we all want to be remembered for what we've done in our way to the end. of people (and that's perfectly fine) or you might actually want to become a
global role model, like Gandhi, Albert Einstein and people alike, it doesn't
matter, what matters is, we all want to be remembered for what we've done in our
way to the end.
Immortals go extinct, but mortals find a mission to accomplish before the Immortals go extinct, but mortals find a mission to accomplish before the
deadline. Be grateful for this gift of death. deadline. Be grateful for this gift of death.
<!--It's not all about being famous, it's about being role model for a lot of people, there are lots of famous people and celebrities--> <!--It's not all about being famous, it's about being role model for a lot of
<!--that will be forgotten after a decade or two, but some people are remembered forever, either for doing very good or very bad to others,--> people, there are lots of famous people and celebrities--> <!--that will be
<!--I don't think Albert Einstein, Gandhi and Hitler will be forgotten in the near future (near as in thousand years).--> forgotten after a decade or two, but some people are remembered forever, either
<!--They are global role models, we want to be like some of them and avoid being like others (okay, maybe not absolutely global, but you get it).--> for doing very good or very bad to others,--> <!--I don't think Albert Einstein,
Gandhi and Hitler will be forgotten in the near future (near as in thousand
years).--> <!--They are global role models, we want to be like some of them and
avoid being like others (okay, maybe not absolutely global, but you get it).-->

View File

@ -9,64 +9,88 @@ author: Mahdi
**High-Frequency Fuck-Ups**: **High-Frequency Fuck-Ups**:
> The cyclic process of "pushing yourself hard for a week, getting something done, and then feeling depressed and fucked up > The cyclic process of "pushing yourself hard for a week, getting something
for the next week" done, and then feeling depressed and fucked up for the next week"
Sounds familiar? Read on. Sounds familiar? Read on.
![High-Frequency Fuck-ups](/img/productivity-chart.jpg) ![High-Frequency Fuck-ups](/img/productivity-chart.jpg) {% include caption.html
{% include caption.html text='Visual demonstration of High-Frequency Fuck-ups' %} text='Visual demonstration of High-Frequency Fuck-ups' %}
<!--more--> <!--more-->
Basically, you push yourself so fucking hard that you become a superstar in a week, and then all of a sudden Basically, you push yourself so fucking hard that you become a superstar in a
you are under a rain of hopelessness. All depression triggers start clicking and you are week, and then all of a sudden you are under a rain of hopelessness. All
lost. At best, you spend a week of depression and start rising to productivity again, but that's it, depression triggers start clicking and you are lost. At best, you spend a week
it's a cycle you never exit and it gets worse and worse with every iteration, your depressions become longer of depression and start rising to productivity again, but that's it, it's a
and longer unless you understand you don't need to climb a slope of 89° to become a superstar, cycle you never exit and it gets worse and worse with every iteration, your
you can do it on a 45°, or even 20°, or even 1°, only it takes patience, but works out much better! depressions become longer and longer unless you understand you don't need to
climb a slope of 89° to become a superstar, you can do it on a 45°, or even 20°,
or even 1°, only it takes patience, but works out much better!
I used to be on High-Frequency Fuck-ups for almost a year, after entering college and getting a job at the same time, I used to be on High-Frequency Fuck-ups for almost a year, after entering
I was under a lot of pressure, I wanted to be best in my work, and in my college, and in everything! Okay, that's not college and getting a job at the same time, I was under a lot of pressure, I
bad on it's own, but I was on the wrong road, I thought that's the way it has to work, you push yourself for some time, wanted to be best in my work, and in my college, and in everything! Okay, that's
get 5% of the road down, and then you get depressed, but you just have to go through it. But I was wrong, badly wrong. not bad on it's own, but I was on the wrong road, I thought that's the way it
has to work, you push yourself for some time, get 5% of the road down, and then
you get depressed, but you just have to go through it. But I was wrong, badly
wrong.
I only got more and more frustrated with my life, I started hating my job, hating my college and everything in between. I only got more and more frustrated with my life, I started hating my job,
My depressions used to be a few days at max after each iteration of superstar-ism at first, but it got worse until I reached depressions hating my college and everything in between. My depressions used to be a few
of two weeks. I couldn't attend to my exercise anymore, I wouldn't read the books I wanted to, even my social life was days at max after each iteration of superstar-ism at first, but it got worse
breaking apart, I was dead, I only knew how to work some stuff out in short spans of time, but I couldn't control the until I reached depressions of two weeks. I couldn't attend to my exercise
side effect it brought, the depression. anymore, I wouldn't read the books I wanted to, even my social life was breaking
apart, I was dead, I only knew how to work some stuff out in short spans of
time, but I couldn't control the side effect it brought, the depression.
To be honest, those superstar peaks felt really good as I would actually accomplish things I couldn't do before, in a just week! To be honest, those superstar peaks felt really good as I would actually
That's why I kept this habit for a year, but at some point I realised this is not going to work long-term, with the rate of accomplish things I couldn't do before, in a just week! That's why I kept this
depressions getting longer and longer, I was risking _my life_, who knows what would've happened once I got to a whole month, habit for a year, but at some point I realised this is not going to work
or even two months of depression, and I couldn't be saved, I was in a state of denial, I thought long-term, with the rate of depressions getting longer and longer, I was risking
"These people don't understand! That's the path you have to take to be great!", so I wouldn't listen to anyone telling me to slow the fuck down. _my life_, who knows what would've happened once I got to a whole month, or even
two months of depression, and I couldn't be saved, I was in a state of denial, I
thought "These people don't understand! That's the path you have to take to be
great!", so I wouldn't listen to anyone telling me to slow the fuck down.
At the time, I had two roommates, and they knew about my state, it was so visible, I would work like robots for a week, bumped up At the time, I had two roommates, and they knew about my state, it was so
and excited, and then I would go down for the next week, feeling groggy and sad the whole time. visible, I would work like robots for a week, bumped up and excited, and then I
would go down for the next week, feeling groggy and sad the whole time.
One night I and one of my roommates, Saeed, started talking, not directly about this topic, but we got there and he told me One night I and one of my roommates, Saeed, started talking, not directly about
I should slow down and move at a more controllable pace. He was not the only one telling me that, I was told this a lot, this topic, but we got there and he told me I should slow down and move at a
either directly or indirectly, but I always denied it. This time, I thought about it, a lot, because I was tired of my High-Frequency Fuck-ups, more controllable pace. He was not the only one telling me that, I was told this
yet I was not sure if he was right or I was, so I continued my High-Frequency Fuck-ups for another two or three months a lot, either directly or indirectly, but I always denied it. This time, I
before deciding I should at least _try_ slowing down. thought about it, a lot, because I was tired of my High-Frequency Fuck-ups, yet
I was not sure if he was right or I was, so I continued my High-Frequency
Fuck-ups for another two or three months before deciding I should at least _try_
slowing down.
I slowly slowed down, the depressions went away, I would accomplish the things I wanted, only slightly longer, but damn, it was great! I slowly slowed down, the depressions went away, I would accomplish the things I
I could continue getting stuff done without feeling fucked up and crying whole days and nights in my bed, I could do the things I loved wanted, only slightly longer, but damn, it was great! I could continue getting
without any fucking side effects! stuff done without feeling fucked up and crying whole days and nights in my bed,
I could do the things I loved without any fucking side effects!
At first, I had the doubt "Am I becoming one of _those_ people? People who don't get things done and don't grow?", but after some time, At first, I had the doubt "Am I becoming one of _those_ people? People who don't
I realised I am actually getting things done much better! It was easy to see for me and the people around me that I was much happier, get things done and don't grow?", but after some time, I realised I am actually
I was in control of my life and I was enjoying it. The only difference was patience, instead of rushing to get the next big thing done getting things done much better! It was easy to see for me and the people around
in a short amount of time, I took patience in checking my list off, and suddenly everything was much more fun. me that I was much happier, I was in control of my life and I was enjoying it.
The only difference was patience, instead of rushing to get the next big thing
done in a short amount of time, I took patience in checking my list off, and
suddenly everything was much more fun.
Now I study, play an instrument, exercise everyday, go running, read books, watch movies, write, eat and sleep well all at the same time, Now I study, play an instrument, exercise everyday, go running, read books,
and I don't feel a bit depressed. Sadness is something, depression is another, I do get sad, but not depressed. I feel alive and active. watch movies, write, eat and sleep well all at the same time, and I don't feel a
bit depressed. Sadness is something, depression is another, I do get sad, but
not depressed. I feel alive and active.
I've become much better socially, my interactions with my friends are much more alive now. I could see it in my friends' eyes when I used to I've become much better socially, my interactions with my friends are much more
be a robot, they were like "What the fuck is going on with you man?", yes, exactly that phrase, but now I'm no longer a slave of High-Frequency Fuck-ups, alive now. I could see it in my friends' eyes when I used to be a robot, they
I have so much fun with my friends. were like "What the fuck is going on with you man?", yes, exactly that phrase,
but now I'm no longer a slave of High-Frequency Fuck-ups, I have so much fun
with my friends.
The takeaway is, stop High-Frequency Fuck-ups, slow down, take things one bite at a time and you will eventually accomplish what you are aiming for, The takeaway is, stop High-Frequency Fuck-ups, slow down, take things one bite
if only with a little more patience, you won't have depression blocking your way and fogging your brain every other week. at a time and you will eventually accomplish what you are aiming for, if only
with a little more patience, you won't have depression blocking your way and
fogging your brain every other week.

View File

@ -7,20 +7,23 @@ excerpt_separator: <!--more-->
author: Mahdi author: Mahdi
--- ---
When it comes to relationships, most (unsuccessful) people are _chasing_ the good ones. When it comes to relationships, most (unsuccessful) people are _chasing_ the
They spend time trying to find their dream partner, the perfect match, but hey, do you qualify good ones. They spend time trying to find their dream partner, the perfect
as the dream partner of your dream partner? You fantasize about your dream partner, but have you ever match, but hey, do you qualify as the dream partner of your dream partner? You
thought what kind of partner does he/she dream of? fantasize about your dream partner, but have you ever thought what kind of
partner does he/she dream of?
![I want an angel with...](/img/angel.jpg) ![I want an angel with...](/img/angel.jpg) {% include caption.html text='I want
{% include caption.html text='I want an angel with...' %} an angel with...' %}
<!--more--> <!--more-->
It seems to be pretty acceptable in the society to start _looking_ for a _good_ partner once you It seems to be pretty acceptable in the society to start _looking_ for a _good_
reach a certain age (depending on the country), and that's when people start defining for themselves what partner once you reach a certain age (depending on the country), and that's when
a _good_ partner means. What do they want out of a relationship? Well, most beginners just want sex, that's one thing, people start defining for themselves what a _good_ partner means. What do they
but I'm talking about real, intimate relationships. The definition usually goes like this: want out of a relationship? Well, most beginners just want sex, that's one
thing, but I'm talking about real, intimate relationships. The definition
usually goes like this:
I want him/her to have I want him/her to have
* Money * Money
@ -29,28 +32,45 @@ I want him/her to have
* Empathy * Empathy
* ... * ...
Alright fine, that's a good and necessary step while thinking about a relationship. Alright fine, that's a good and necessary step while thinking about a
relationship.
Now there are two groups of people after this step, let's call them Group A and Group B. Now there are two groups of people after this step, let's call them Group A and
Group B.
Group A's next step is to start looking for partners, which usually follows by installing Tinder, OkCupid and a bunch of other Group A's next step is to start looking for partners, which usually follows by
dating apps, spending more time in the bar, etc. Well it makes sense to start looking for a partner at first glance, but people in Group A installing Tinder, OkCupid and a bunch of other dating apps, spending more time
are missing an important point here, they defined what a _good partner_ means in their dictionary of life, but they haven't in the bar, etc. Well it makes sense to start looking for a partner at first
really looked into their _good partner_'s dictionary to see what he/she wants out of a relationship, because if you don't qualify her requirements, glance, but people in Group A are missing an important point here, they defined
it's not a deal. what a _good partner_ means in their dictionary of life, but they haven't really
looked into their _good partner_'s dictionary to see what he/she wants out of a
relationship, because if you don't qualify her requirements, it's not a deal.
Now there is a sub-group of Group A, too, and it includes the people who faced with the question "am I what she dreams of?", they Now there is a sub-group of Group A, too, and it includes the people who faced
try to cheat and modify their definition of a good partner, adding a line that goes "Loves me however I am", sorry buddy, but what if I with the question "am I what she dreams of?", they try to cheat and modify their
tell you she could add the same line to her dictionary? That's not a deal, you want a good partner as you defined it, you have to be a good partner definition of a good partner, adding a line that goes "Loves me however I am",
as she defines it. sorry buddy, but what if I tell you she could add the same line to her
dictionary? That's not a deal, you want a good partner as you defined it, you
have to be a good partner as she defines it.
On the other hand, Group B doesn't follow the same path as Group A. Group B starts by trying to predict what his dream partner would want On the other hand, Group B doesn't follow the same path as Group A. Group B
out of a relationship. Empathy? Loyalty? Knowledge? Body? They take a pen and a paper out and write a list of what they think their dream partner starts by trying to predict what his dream partner would want out of a
would want them to have, what would she want them to be, and they start working on those, and I bet it's not going to be easy, knowledge doesn't pop up relationship. Empathy? Loyalty? Knowledge? Body? They take a pen and a paper out
after a good night's sleep, you have to spend years reading books and learning to get it. A good body doesn't _poof_ out if you wish it to, you have and write a list of what they think their dream partner would want them to have,
to spend years being committed to exercise and eating well, and that's not easy. After all, what you define as a good partner ain't easy either, is it? what would she want them to be, and they start working on those, and I bet it's
not going to be easy, knowledge doesn't pop up after a good night's sleep, you
have to spend years reading books and learning to get it. A good body doesn't
_poof_ out if you wish it to, you have to spend years being committed to
exercise and eating well, and that's not easy. After all, what you define as a
good partner ain't easy either, is it?
Now do you want your dream partner to fall for you the way you fall for her, without having to chase her with a net? Write down a list of Now do you want your dream partner to fall for you the way you fall for her,
qualifications you expect your dream partner to look for, and start working your ass off reaching them, and I tell you, you will have a much easier _next step_ after this. You won't have to chase girls hoping the 34th one doesn't reject you because "she likes you however you are". without having to chase her with a net? Write down a list of qualifications you
expect your dream partner to look for, and start working your ass off reaching
them, and I tell you, you will have a much easier _next step_ after this. You
won't have to chase girls hoping the 34th one doesn't reject you because "she
likes you however you are".
If I know one thing about life, it's the fact that you have to work your ass off in order to reach your dreams, dreams aren't easy, and a deep, intimate relationship really is a dream. If I know one thing about life, it's the fact that you have to work your ass off
in order to reach your dreams, dreams aren't easy, and a deep, intimate
relationship really is a dream.

View File

@ -12,9 +12,14 @@ author: Mahdi
![general view of the forest](/img/primitive-living-0.jpg) ![general view of the forest](/img/primitive-living-0.jpg)
So I just went on my first primitive living practice trip in the woods, alone, with only a pocket knife. So I just went on my first primitive living practice trip in the woods, alone,
with only a pocket knife.
I decided I'm going to share the lessons I've learned in each trip as they are certainly going to be useful if you want to practice primitive living, I would find these useful if I could find them anywhere. I spend a lot of time reading and watching primitive living guides and experience reports, but they are never exhaustive, and this series is not meant to be exhaustive either. I decided I'm going to share the lessons I've learned in each trip as they are
certainly going to be useful if you want to practice primitive living, I would
find these useful if I could find them anywhere. I spend a lot of time reading
and watching primitive living guides and experience reports, but they are never
exhaustive, and this series is not meant to be exhaustive either.
<!--more--> <!--more-->
@ -22,21 +27,40 @@ Here we go:
# What I did know # What I did know
I spent a lot of time studying about edible wild plants, how to butcher and cook different kinds of animals and insects. I also had practiced fire by friction and read a lot and watched videos about theory of making cordages, making a bow-drill and so on. I also knew and had already built shelters for the night. So you can assume I had a basic, broad understanding of the necessary skills, but experience? Not so much. I spent a lot of time studying about edible wild plants, how to butcher and cook
different kinds of animals and insects. I also had practiced fire by friction
and read a lot and watched videos about theory of making cordages, making a
bow-drill and so on. I also knew and had already built shelters for the night.
So you can assume I had a basic, broad understanding of the necessary skills,
but experience? Not so much.
# Setup # Setup
I had a pocket knife, a Garmin GPS and a pocket first aid kid, I would expect something to go wrong along the way, so I thought I want to be safe, but not comfortable, that's why I brought emergency necessities, but not any comfort tools and materials. I also had a canned tuna for my first breakfast, but nothing more. I had a pocket knife, a Garmin GPS and a pocket first aid kid, I would expect
something to go wrong along the way, so I thought I want to be safe, but not
comfortable, that's why I brought emergency necessities, but not any comfort
tools and materials. I also had a canned tuna for my first breakfast, but
nothing more.
Now for what is worth, I'm going in around summer's end, September 5th, in a forest in northern Iran, Mazandaran Province. The forest starts from foothills, covering a few mounts from both sides, so it's pretty large but also mountaneous, so I it's hard to move in the forest. Now for what is worth, I'm going in around summer's end, September 5th, in a
forest in northern Iran, Mazandaran Province. The forest starts from foothills,
covering a few mounts from both sides, so it's pretty large but also
mountaneous, so I it's hard to move in the forest.
# Arrival: First Night # Arrival: First Night
So I arrived at the entrace of the forest at night, it was already dark and I couldn't build a shelter or do much, I just slept on the open ground, it was my first night in the woods alone. I was quite scared at first, lots of cracks and movements in bushes by unknown creatures, but after a few hours I figured out all these creatures are small ones that can't be harmful to me. A few hours before dawn it got bitter cold, and I woke up, unable to go back to sleep. The first night was not the best, but could be worse. So I arrived at the entrace of the forest at night, it was already dark and I
couldn't build a shelter or do much, I just slept on the open ground, it was my
first night in the woods alone. I was quite scared at first, lots of cracks and
movements in bushes by unknown creatures, but after a few hours I figured out
all these creatures are small ones that can't be harmful to me. A few hours
before dawn it got bitter cold, and I woke up, unable to go back to sleep. The
first night was not the best, but could be worse.
# First Day # First Day
I woke early at dawn and started moving into the forest, looking for a place to build my shelter in. I decided I'm going to follow these steps: I woke early at dawn and started moving into the forest, looking for a place to
build my shelter in. I decided I'm going to follow these steps:
1. Build a shelter 1. Build a shelter
2. Find water source 2. Find water source
@ -49,60 +73,153 @@ But as was expected, it didn't go according to the plan.
## Shelter ## Shelter
I found a nice place to stay which had a stream passing by, the stream was running and from what I knew about the area, the water was safe to drink, so water was no longer an issue. I started building my shelter, got the base wooden structure down first, but there was a catch: I couldn't find any dry debris to put on top or inside. Last time I had built the same shelter it was autumn's end/early spring, so there were lots of dry, fallen leaves on the ground; But this time it's in the summer and there very few, scattered dry leaves on the ground, uncollectable. I found a nice place to stay which had a stream passing by, the stream was
running and from what I knew about the area, the water was safe to drink, so
water was no longer an issue. I started building my shelter, got the base wooden
structure down first, but there was a catch: I couldn't find any dry debris to
put on top or inside. Last time I had built the same shelter it was autumn's
end/early spring, so there were lots of dry, fallen leaves on the ground; But
this time it's in the summer and there very few, scattered dry leaves on the
ground, uncollectable.
I decided I'm going with leaves of a small tree I had found nearby which seemed to be abundant around the area and the branches had lots of close leaves on them, looked like a good choice, but it was green. I didn't find out what I was doing wrong until I tried to sleep at night. The green leaves attracted lots of flies and insects and all sorts of annoying disturbances, and the smell wasn't helping either. I had to endure the insects throughout the night, because sleeping outside the shelter was a no-go, the dirt beneath was too cold. I hadn't put as much leaves on the ground, and the leaves were green (which also means they take more heat away), but still, it was much better than sleeping directly on the ground. I decided I'm going with leaves of a small tree I had found nearby which seemed
to be abundant around the area and the branches had lots of close leaves on
them, looked like a good choice, but it was green. I didn't find out what I was
doing wrong until I tried to sleep at night. The green leaves attracted lots of
flies and insects and all sorts of annoying disturbances, and the smell wasn't
helping either. I had to endure the insects throughout the night, because
sleeping outside the shelter was a no-go, the dirt beneath was too cold. I
hadn't put as much leaves on the ground, and the leaves were green (which also
means they take more heat away), but still, it was much better than sleeping
directly on the ground.
What I learned was, **do not use green leaves for covering your shelter**. This rule applies to small shelters in which you are close to the covering, as well as the leaves you use as bedding. I've seen people using green leaves for covering big shelters which have a high ceiling, though I don't have any experience with those myself. What I learned was, **do not use green leaves for covering your shelter**. This
rule applies to small shelters in which you are close to the covering, as well
as the leaves you use as bedding. I've seen people using green leaves for
covering big shelters which have a high ceiling, though I don't have any
experience with those myself.
![friction fire tries](/img/primitive-living-0-friction-fire.jpg) ![friction fire tries](/img/primitive-living-0-friction-fire.jpg)
## Friction Fire ## Friction Fire
The most important part of primitive living is fire, without fire you can't cook, you can't stay warm and you can't defy nocturnal predators. You also can't repel insects. You can't make a torch, so there goes an infinite list of fire applications that you will miss. The most important part of primitive living is fire, without fire you can't
cook, you can't stay warm and you can't defy nocturnal predators. You also can't
repel insects. You can't make a torch, so there goes an infinite list of fire
applications that you will miss.
I knew the theory of friction fire in and out, how and why it works, but what I had missed was, **you are going to be in _real trouble_ if you can't find softwood**. To my surprise, searching portions of the forest, I couldn't find any softwood tree. Oaks were everywhere, as well as quite some other species of trees, but all of them were hardwood. I knew the theory of friction fire in and out, how and why it works, but what I
had missed was, **you are going to be in _real trouble_ if you can't find
softwood**. To my surprise, searching portions of the forest, I couldn't find
any softwood tree. Oaks were everywhere, as well as quite some other species of
trees, but all of them were hardwood.
I tried different combinations of the softer woods I could find, but none of them resulted in an ember, I got smoke with one combination, but that was it. After about 5-6 hours of trying, I got real tired and gave up. By the way, I tried hand-drills, I couldn't succeed with bow-drills as I couldn't find suitable cordage, I tried with a promising bark that was pretty strong, but it would break as soon as I put some pressure on it, It's also possible that I might've gone wrong in making the bow itself, so it would cause the breakage. I tried different combinations of the softer woods I could find, but none of
them resulted in an ember, I got smoke with one combination, but that was it.
After about 5-6 hours of trying, I got real tired and gave up. By the way, I
tried hand-drills, I couldn't succeed with bow-drills as I couldn't find
suitable cordage, I tried with a promising bark that was pretty strong, but it
would break as soon as I put some pressure on it, It's also possible that I
might've gone wrong in making the bow itself, so it would cause the breakage.
So the lesson was **make sure the material you are going to practice with is available in your practice area**, had I known there were no softwood in that particular forest, I would change my destination and probably succeed somewhere else. Sure, a professional survivalist must be able to start a fire in almost all situations, but this is practice and you have to start with easier steps. So the lesson was **make sure the material you are going to practice with is
available in your practice area**, had I known there were no softwood in that
particular forest, I would change my destination and probably succeed somewhere
else. Sure, a professional survivalist must be able to start a fire in almost
all situations, but this is practice and you have to start with easier steps.
I ended up shaking for 2 hours before the dawn, not a pleasant experience at all. :D I ended up shaking for 2 hours before the dawn, not a pleasant experience at
all. :D
## Food ## Food
The difficulties didn't end there, without a fire, my only hope for food was specific edible plants which can be eaten raw, or fruits. Unlucky as I was, I couldn't find a single fruit-bearing tree in the forest (I found quite a few fruit-bearing trees along the roads and paths to the forest, but not inside the forest itself), and I also couldn't find any of the other edible plants (I was mostly looking for the onion family) that I knew of. The difficulties didn't end there, without a fire, my only hope for food was
specific edible plants which can be eaten raw, or fruits. Unlucky as I was, I
couldn't find a single fruit-bearing tree in the forest (I found quite a few
fruit-bearing trees along the roads and paths to the forest, but not inside the
forest itself), and I also couldn't find any of the other edible plants (I was
mostly looking for the onion family) that I knew of.
One of the greatest complications when starting primitive living practice anywhere other than the U.S. is that **almost all guides and materials on the topic are from, and for Northern America**. [The Falcon Guide to Edible Wild Plants](https://www.amazon.com/Edible-Wild-Plants-Falcon-Field/dp/0762774215) that I read is all about northern american plants. I knew it, but it's also the case that the Northern Hemisphere of the Earth have more common of an ecology, so most of the plants found in Northern America can also be found in places like Iran, but they have their differences. Most of the tips and tricks provided in different resources are for Northern American forests, which do not always work in other places. One of the greatest complications when starting primitive living practice
anywhere other than the U.S. is that **almost all guides and materials on the
topic are from, and for Northern America**. [The Falcon Guide to Edible Wild
Plants](https://www.amazon.com/Edible-Wild-Plants-Falcon-Field/dp/0762774215)
that I read is all about northern american plants. I knew it, but it's also the
case that the Northern Hemisphere of the Earth have more common of an ecology,
so most of the plants found in Northern America can also be found in places like
Iran, but they have their differences. Most of the tips and tricks provided in
different resources are for Northern American forests, which do not always work
in other places.
So all in all, I ended up not eating anything for the next 24 hours, until I got out of the forest. So all in all, I ended up not eating anything for the next 24 hours, until I got
out of the forest.
## Psychology ## Psychology
Apart from all the physical failures that I faced, which in turn caused frustration, I also had strong feelings of loneliness, boredom, and fear upon me. It was after failing to start a fire that I really felt the psychological burden on me. I had read about similar experiences, but believe me, the experience is hardly transmittable by words. A local rancher passing by the forest telling me about the leopard in the forest didn't make things any easier. Apart from all the physical failures that I faced, which in turn caused
frustration, I also had strong feelings of loneliness, boredom, and fear upon
me. It was after failing to start a fire that I really felt the psychological
burden on me. I had read about similar experiences, but believe me, the
experience is hardly transmittable by words. A local rancher passing by the
forest telling me about the leopard in the forest didn't make things any easier.
The psychological pressure was above all other difficulties, at some point I was bursting into tears, but I couldn't associate it with any one specific feeling, it was a mix of anger, loneliness and fear. The psychological pressure was above all other difficulties, at some point I was
bursting into tears, but I couldn't associate it with any one specific feeling,
it was a mix of anger, loneliness and fear.
Anger and frustration because I couldn't succeed in what I was trying to do. I also cut my finger at some point while carving the woods, so there was that. Anger and frustration because I couldn't succeed in what I was trying to do. I
also cut my finger at some point while carving the woods, so there was that.
Loneliness because I was all by myself and I had no company to talk to. You can really actually go insane, as seen in [Cast Away](https://en.wikipedia.org/wiki/Cast_Away), after prolonged sessions of loneliness in situations like that. Mine wasn't long, it was only two days, but I still experienced the thought-fog, I couldn't think straight. Loneliness because I was all by myself and I had no company to talk to. You can
really actually go insane, as seen in [Cast
Away](https://en.wikipedia.org/wiki/Cast_Away), after prolonged sessions of
loneliness in situations like that. Mine wasn't long, it was only two days, but
I still experienced the thought-fog, I couldn't think straight.
Fear because I felt weak compared to the power of nature, my fear was doubled by the fact that I was alone. I felt like being in a place where everything seems to know what it is doing, but I don't; I felt lost, not knowing what to do after my basic plans had failed. Fear because I felt weak compared to the power of nature, my fear was doubled by
the fact that I was alone. I felt like being in a place where everything seems
to know what it is doing, but I don't; I felt lost, not knowing what to do after
my basic plans had failed.
Now I don't know if there is much you can do about the psychological part of it, I think experience is the remedy, at least I felt how different it was between the nights, the first night, even though I wasn't even _inside_ the forest much, I was almost at the border of it, it was much more creepy because it was my first time, but the second night, I was in the forest and now I had a _leopard_ in my mind pouncing on me, but I felt less fear and was more comfortable. Now I don't know if there is much you can do about the psychological part of it,
I think experience is the remedy, at least I felt how different it was between
the nights, the first night, even though I wasn't even _inside_ the forest much,
I was almost at the border of it, it was much more creepy because it was my
first time, but the second night, I was in the forest and now I had a _leopard_
in my mind pouncing on me, but I felt less fear and was more comfortable.
But in the end, what helped me was that *I knew I was going to face a huge mental challenge along the way*, so I was more prepared. I think it's utterly important to be prepared for such psychological situations, knowing the reason behind your psychological challenges can help you overcome it to some extend. But in the end, what helped me was that *I knew I was going to face a huge
mental challenge along the way*, so I was more prepared. I think it's utterly
important to be prepared for such psychological situations, knowing the reason
behind your psychological challenges can help you overcome it to some extend.
# Second Night # Second Night
The second and last night was not all that much interesting, but it was damn sure cold and hard. At first I had to deal with the insects biting me everywhere and my feet scratching while trying to sleep in the shelter that I had wrongly built. After getting over that one and sleeping for what seemed to be ~2 hours, I woke up and felt the air temperature decreasing. I still got to sleep in intervals of 30 minutes until I woke up at around ~4 AM and my whole body was shaking. I couldn't do much, all I did was gather the leaves underneath a little closer and more dense, and crunch my body into a ball so I felt just a little warmer, but still shaking. It took ages for the last two and a half hours to pass until dawn. At dawn I got up quickly and walked around a little to warm myself up, and then waited until I could barely see my surroundings, then I started walking out of the forest. The second and last night was not all that much interesting, but it was damn
sure cold and hard. At first I had to deal with the insects biting me everywhere
and my feet scratching while trying to sleep in the shelter that I had wrongly
built. After getting over that one and sleeping for what seemed to be ~2 hours,
I woke up and felt the air temperature decreasing. I still got to sleep in
intervals of 30 minutes until I woke up at around ~4 AM and my whole body was
shaking. I couldn't do much, all I did was gather the leaves underneath a little
closer and more dense, and crunch my body into a ball so I felt just a little
warmer, but still shaking. It took ages for the last two and a half hours to
pass until dawn. At dawn I got up quickly and walked around a little to warm
myself up, and then waited until I could barely see my surroundings, then I
started walking out of the forest.
Initially I had decided to stay for longer, but the weather forecast had predicted a heavy rain and storm for the next night, there was no way I could withstand that. :D Initially I had decided to stay for longer, but the weather forecast had
predicted a heavy rain and storm for the next night, there was no way I could
withstand that. :D
# Bottom Line # Bottom Line
It was a hard trip, I lost about 2kg (4lb) weight, but all in all the experience was a good one, I certainly learned a lot and I'm not going to make the same mistakes again. I should definitly practice more and keep working on my skills. It was a hard trip, I lost about 2kg (4lb) weight, but all in all the experience
was a good one, I certainly learned a lot and I'm not going to make the same
mistakes again. I should definitly practice more and keep working on my skills.
If you are looking forward to practicing primitive living, please make sure you are safe and start small. If you are looking forward to practicing primitive living, please make sure you
are safe and start small.
> Success is going from failure to failure without losing your enthusiasm. —Winston Churchill > Success is going from failure to failure without losing your enthusiasm.
—Winston Churchill

View File

@ -7,24 +7,33 @@ excerpt_separator: <!--more-->
author: Mahdi author: Mahdi
--- ---
I just want to leave this here as I often tend to look it up myself and the first time it was not as easy to figure out. I just want to leave this here as I often tend to look it up myself and the
first time it was not as easy to figure out.
When using Travis CI along with GitHub (or other git integrations), Travis runs two tests: <code>pr</code> and <code>push</code>. When using Travis CI along with GitHub (or other git integrations), Travis runs
two tests: <code>pr</code> and <code>push</code>.
![travis-pr-push-github](/img/travis-ci-pr-push-github.jpg) ![travis-pr-push-github](/img/travis-ci-pr-push-github.jpg)
Most of the time you see both tests passing and you do not have to even wonder how they are different, but it has Most of the time you see both tests passing and you do not have to even wonder
happened to me that one of the tests fails while the other passes and I started to wonder why. how they are different, but it has happened to me that one of the tests fails
while the other passes and I started to wonder why.
### pr ### pr The <code>pr</code> test is a test run on the result of a merge between
The <code>pr</code> test is a test run on the result of a merge between the pull-request branch and the main branch. the pull-request branch and the main branch. As an example, let's say your
As an example, let's say your pull-request's branch is called <code>fix-user-auth</code> and your main branch is <code>master</code>, pull-request's branch is called <code>fix-user-auth</code> and your main branch
in this case, <code>pr</code> merges <code>fix-user-auth</code> into <code>master</code> and then runs the tests on the result of the merge. is <code>master</code>, in this case, <code>pr</code> merges
<code>fix-user-auth</code> into <code>master</code> and then runs the tests on
the result of the merge.
### push ### push On the other hand, <code>push</code> is run on the pull-request branch
On the other hand, <code>push</code> is run on the pull-request branch itself, without merging. So in our example above, Travis would checkout to <code>fix-user-auth</code> and run the tests. itself, without merging. So in our example above, Travis would checkout to
<code>fix-user-auth</code> and run the tests.
### A case of difference ### A case of difference
A case in which this difference might be more apparent is when your pull-request is based on a branch other than <code>master</code>, and some changes that your pull-request depends on are missing from <code>master</code>, in this case the <code>push</code> test may pass, but the <code>pr</code> test will fail. A case in which this difference might be more apparent is when your pull-request
is based on a branch other than <code>master</code>, and some changes that your
pull-request depends on are missing from <code>master</code>, in this case the
<code>push</code> test may pass, but the <code>pr</code> test will fail.

View File

@ -11,20 +11,34 @@ author: Mahdi
![a view of the stand + kindle](/img/kindle-stand/1.jpg) ![a view of the stand + kindle](/img/kindle-stand/1.jpg)
I've had a Kindle for more than a year now, but I've only recently started to read books on it frequently, I used to read paperworks before that, and I still do sometimes prefer paperbooks if available. Anyways, my Kindle has helped me to fall asleep without struggling with all my thoughts, all I have to do is read until I fall asleep, so in a way, it has also been a remedy for my insomnia. I've had a Kindle for more than a year now, but I've only recently started to
read books on it frequently, I used to read paperworks before that, and I still
do sometimes prefer paperbooks if available. Anyways, my Kindle has helped me to
fall asleep without struggling with all my thoughts, all I have to do is read
until I fall asleep, so in a way, it has also been a remedy for my insomnia.
Now to read the Kindle in bed, you would have to hold it using your hands or buy a stand or make one, motivated by [The Pursuit of Laziness](https://blog.xkcd.com/2009/04/13/the-pursuit-of-laziness/) I set to create mine, but I didn't use a piece of steel, instead I used a single box of cardboard I had in home to create one in minutes. :D Now to read the Kindle in bed, you would have to hold it using your hands or buy
a stand or make one, motivated by [The Pursuit of
Laziness](https://blog.xkcd.com/2009/04/13/the-pursuit-of-laziness/) I set to
create mine, but I didn't use a piece of steel, instead I used a single box of
cardboard I had in home to create one in minutes. :D
<!--more--> <!--more-->
It's too easy to need much of an instruction, a few pictures and some explanation will do: It's too easy to need much of an instruction, a few pictures and some
explanation will do:
![a view of the stand without kindle](/img/kindle-stand/0.jpg) ![a view of the stand without kindle](/img/kindle-stand/0.jpg)
So this part shows a simple piece of cardboard cut using scissors on the front, with the sides taped to the bottom (actually if your piece of cardboard is a box, it might already be taped in that way, mine was). So this part shows a simple piece of cardboard cut using scissors on the front,
with the sides taped to the bottom (actually if your piece of cardboard is a
box, it might already be taped in that way, mine was).
![a view of the stand's back side](/img/kindle-stand/2.jpg) ![a view of the stand's back side](/img/kindle-stand/2.jpg)
On the back, there is another piece of cardboard (I took the opening of it which already had a notch line, and the size fit perfectly). I used a stapler to to attach the two sides toghether, and that's it! On the back, there is another piece of cardboard (I took the opening of it which
already had a notch line, and the size fit perfectly). I used a stapler to to
attach the two sides toghether, and that's it!
I tried it last night to make sure it's convenient before posting here, and I tell you, it is totally comfortable and much better than holding with a hand. I tried it last night to make sure it's convenient before posting here, and I
tell you, it is totally comfortable and much better than holding with a hand.

View File

@ -11,9 +11,17 @@ toc: true
author: Mahdi author: Mahdi
--- ---
I wanted to get proficient in Haskell so I decided to follow [An [Essential] Haskell Reading List](http://www.stephendiehl.com/posts/essential_haskell.html). There I stumbled upon [Typoclassopedia](https://wiki.haskell.org/Typeclassopedia), while the material is great, I couldn't find solutions for the exercises to check against, so I decided I would write my own and hopefully the solutions would get fixed in case I have gone wrong by others. So if you think a solution is wrong, let me know in the comments! I wanted to get proficient in Haskell so I decided to follow [An [Essential]
Haskell Reading List](http://www.stephendiehl.com/posts/essential_haskell.html).
There I stumbled upon
[Typoclassopedia](https://wiki.haskell.org/Typeclassopedia), while the material
is great, I couldn't find solutions for the exercises to check against, so I
decided I would write my own and hopefully the solutions would get fixed in case
I have gone wrong by others. So if you think a solution is wrong, let me know in
the comments!
In each section below, I left some reference material for the exercises and then the solutions. In each section below, I left some reference material for the exercises and then
the solutions.
Note: The post will be updated as I progress in Typoclassopedia myself Note: The post will be updated as I progress in Typoclassopedia myself
@ -34,9 +42,19 @@ instance Functor Maybe where
fmap g (Just a) = Just (g a) fmap g (Just a) = Just (g a)
``` ```
> ((,) e) represents a container which holds an “annotation” of type e along with the actual value it holds. It might be clearer to write it as (e,), by analogy with an operator section like (1+), but that syntax is not allowed in types (although it is allowed in expressions with the TupleSections extension enabled). However, you can certainly think of it as (e,). > ((,) e) represents a container which holds an “annotation” of type e along
with the actual value it holds. It might be clearer to write it as (e,), by
analogy with an operator section like (1+), but that syntax is not allowed in
types (although it is allowed in expressions with the TupleSections extension
enabled). However, you can certainly think of it as (e,).
> ((->) e) (which can be thought of as (e ->); see above), the type of functions which take a value of type e as a parameter, is a Functor. As a container, (e -> a) represents a (possibly infinite) set of values of a, indexed by values of e. Alternatively, and more usefully, ((->) e) can be thought of as a context in which a value of type e is available to be consulted in a read-only fashion. This is also why ((->) e) is sometimes referred to as the reader monad; more on this later. > ((->) e) (which can be thought of as (e ->); see above), the type of functions
which take a value of type e as a parameter, is a Functor. As a container, (e ->
a) represents a (possibly infinite) set of values of a, indexed by values of e.
Alternatively, and more usefully, ((->) e) can be thought of as a context in
which a value of type e is available to be consulted in a read-only fashion.
This is also why ((->) e) is sometimes referred to as the reader monad; more on
this later.
### Exercises ### Exercises
@ -66,7 +84,9 @@ instance Functor Maybe where
``` ```
Their similarity is in the fact that they both represent types of two values. Their similarity is in the fact that they both represent types of two values.
Their difference is that `((,) e)` (tuples of two) can have values of different types (kind of `(,)` is `* -> *`) while both values of `Pair` have the same type `a`, so `Pair` has kind `*`. Their difference is that `((,) e)` (tuples of two) can have values of
different types (kind of `(,)` is `* -> *`) while both values of `Pair` have
the same type `a`, so `Pair` has kind `*`.
3. Implement a `Functor` instance for the type `ITree`, defined as 3. Implement a `Functor` instance for the type `ITree`, defined as
@ -105,7 +125,8 @@ instance Functor Maybe where
[16, 12, 12] [16, 12, 12]
``` ```
4. Give an example of a type of kind `* -> *` which cannot be made an instance of `Functor` (without using `undefined`). 4. Give an example of a type of kind `* -> *` which cannot be made an instance
of `Functor` (without using `undefined`).
I don't know the answer to this one yet! I don't know the answer to this one yet!
@ -113,7 +134,8 @@ instance Functor Maybe where
> The composition of two `Functor`s is also a `Functor`. > The composition of two `Functor`s is also a `Functor`.
If false, give a counterexample; if true, prove it by exhibiting some appropriate Haskell code. If false, give a counterexample; if true, prove it by exhibiting some
appropriate Haskell code.
**Solution**: **Solution**:
@ -141,7 +163,10 @@ fmap (g . h) = (fmap g) . (fmap h)
### Exercises ### Exercises
1. Although it is not possible for a Functor instance to satisfy the first Functor law but not the second (excluding undefined), the reverse is possible. Give an example of a (bogus) Functor instance which satisfies the second law but not the first. 1. Although it is not possible for a Functor instance to satisfy the first
Functor law but not the second (excluding undefined), the reverse is
possible. Give an example of a (bogus) Functor instance which satisfies the
second law but not the first.
**Solution**: **Solution**:
@ -161,7 +186,8 @@ fmap (g . h) = (fmap g) . (fmap h)
λ: fmap (+1) . fmap (+2) $ [1,2] -- [4, 5] λ: fmap (+1) . fmap (+2) $ [1,2] -- [4, 5]
``` ```
2. Which laws are violated by the evil Functor instance for list shown above: both laws, or the first law alone? Give specific counterexamples. 2. Which laws are violated by the evil Functor instance for list shown above:
both laws, or the first law alone? Give specific counterexamples.
```haskell ```haskell
-- Evil Functor instance -- Evil Functor instance
@ -178,7 +204,9 @@ fmap (g . h) = (fmap g) . (fmap h)
Category Theory Category Theory
=============== ===============
The Functor section links to [Category Theory](https://en.wikibooks.org/wiki/Haskell/Category_theory), so here I'm going to cover the exercises of that page, too. The Functor section links to [Category
Theory](https://en.wikibooks.org/wiki/Haskell/Category_theory), so here I'm
going to cover the exercises of that page, too.
## Introduction to categories ## Introduction to categories
@ -188,17 +216,26 @@ The Functor section links to [Category Theory](https://en.wikibooks.org/wiki/Has
$f \circ (g \circ h) = (f \circ g) \circ h$ $f \circ (g \circ h) = (f \circ g) \circ h$
2. The category needs to be **closed** under the composition operator. So if $f : B \to C$ and $g: A \to B$, then there must be some $h: A \to C$ in the category such that $h = f \circ g$. 2. The category needs to be **closed** under the composition operator. So if $f
3. Every object $A$ in a category must have an identity morphism, $id_A : A \to A$ that is an identity of composition with other morphisms. So for every morphism $g: A \to B$: : B \to C$ and $g: A \to B$, then there must be some $h: A \to C$ in the
category such that $h = f \circ g$.
3. Every object $A$ in a category must have an identity morphism, $id_A : A \to
A$ that is an identity of composition with other morphisms. So for every
morphism $g: A \to B$:
$g \circ id_A = id_B \circ g = g$. $g \circ id_A = id_B \circ g = g$.
### Exercises ### Exercises
1. As was mentioned, any partial order $(P, \leq)$ is a category with objects as the elements of P and a morphism between elements a and b iff $a \leq b$. Which of the above laws guarantees the transitivity of $\leq$? 1. As was mentioned, any partial order $(P, \leq)$ is a category with objects as
the elements of P and a morphism between elements a and b iff $a \leq b$.
Which of the above laws guarantees the transitivity of $\leq$?
**Solution**: **Solution**:
The second law, which states that the category needs to be closed under the composition operator guarantess that because we have a morphism $a \leq b$, and another morphism $b \leq c$, there must also be some other morphism such that $a \leq c$. The second law, which states that the category needs to be closed under the
composition operator guarantess that because we have a morphism $a \leq b$,
and another morphism $b \leq c$, there must also be some other morphism such
that $a \leq c$.
2. If we add another morphism to the above example, as illustrated below, it fails to be a category. Why? Hint: think about associativity of the composition operation. 2. If we add another morphism to the above example, as illustrated below, it fails to be a category. Why? Hint: think about associativity of the composition operation.
@ -226,7 +263,8 @@ The Functor section links to [Category Theory](https://en.wikibooks.org/wiki/Has
### Functor laws: ### Functor laws:
1. Given an identity morphism $id_A$ on an object $A$, $F(id_A)$ must be the identity morphism on $F(A)$, so: 1. Given an identity morphism $id_A$ on an object $A$, $F(id_A)$ must be the
identity morphism on $F(A)$, so:
$F(id_A) = id_{F(A)}$ $F(id_A) = id_{F(A)}$
2. Functors must distribute over morphism composition: 2. Functors must distribute over morphism composition:
@ -240,9 +278,13 @@ The Functor section links to [Category Theory](https://en.wikibooks.org/wiki/Has
**Solution**: **Solution**:
The first law is obvious as it's directly written, the pale blue dotted arrows from $id_C$ to $F(id_C) = id_{F(C)}$ and $id_A$ and $id_B$ to $F(id_A) = F(id_B) = id_{F(A)} = id_{F(B)}$ show this. The first law is obvious as it's directly written, the pale blue dotted
arrows from $id_C$ to $F(id_C) = id_{F(C)}$ and $id_A$ and $id_B$ to
$F(id_A) = F(id_B) = id_{F(A)} = id_{F(B)}$ show this.
The second law also holds, the only compositions in category $C$ are between $f$ and identities, and $g$ and identities, there is no composition between $f$ and $g$. The second law also holds, the only compositions in category $C$ are between
$f$ and identities, and $g$ and identities, there is no composition between
$f$ and $g$.
(Note: The second law always hold as long as the first one does, as was seen in Typoclassopedia) (Note: The second law always hold as long as the first one does, as was seen in Typoclassopedia)
@ -299,7 +341,9 @@ Applicative
pure f <*> pure x = pure (f x) pure f <*> pure x = pure (f x)
``` ```
Intuitively, applying a non-effectful function to a non-effectful argument in an effectful context is the same as just applying the function to the argument and then injecting the result into the context with pure. Intuitively, applying a non-effectful function to a non-effectful argument
in an effectful context is the same as just applying the function to the
argument and then injecting the result into the context with pure.
3. Interchange: 3. Interchange:
@ -307,7 +351,9 @@ Applicative
u <*> pure y = pure ($ y) <*> u u <*> pure y = pure ($ y) <*> u
``` ```
Intuitively, this says that when evaluating the application of an effectful function to a pure argument, the order in which we evaluate the function and its argument doesn't matter. Intuitively, this says that when evaluating the application of an effectful
function to a pure argument, the order in which we evaluate the function and
its argument doesn't matter.
4. Composition: 4. Composition:
@ -315,11 +361,15 @@ Applicative
u <*> (v <*> w) = pure (.) <*> u <*> v <*> w u <*> (v <*> w) = pure (.) <*> u <*> v <*> w
``` ```
This one is the trickiest law to gain intuition for. In some sense it is expressing a sort of associativity property of (`<*>`). The reader may wish to simply convince themselves that this law is type-correct. This one is the trickiest law to gain intuition for. In some sense it is
expressing a sort of associativity property of (`<*>`). The reader may wish
to simply convince themselves that this law is type-correct.
### Exercises ### Exercises
(Tricky) One might imagine a variant of the interchange law that says something about applying a pure function to an effectful argument. Using the above laws, prove that (Tricky) One might imagine a variant of the interchange law that says something
about applying a pure function to an effectful argument. Using the above laws,
prove that
```haskell ```haskell
pure f <*> x = pure (flip ($)) <*> x <*> pure f pure f <*> x = pure (flip ($)) <*> x <*> pure f
@ -338,13 +388,25 @@ pure (flip ($)) <*> x <*> pure f
``` ```
Explanation of the last transformation: Explanation of the last transformation:
`flip ($)` has type `a -> (a -> c) -> c`, intuitively, it first takes an argument of type `a`, then a function that accepts that argument, and in the end it calls the function with the first argument. So `(flip ($) 5)` takes as argument a function which gets called with `5` as it's argument. If we pass `(+ 2)` to `(flip ($) 5)`, we get `(flip ($) 5) (+2)` which is equivalent to the expression `(+2) $ 5`, evaluating to `7`. `flip ($)` has type `a -> (a -> c) -> c`, intuitively, it first takes an
argument of type `a`, then a function that accepts that argument, and in the end
it calls the function with the first argument. So `(flip ($) 5)` takes as
argument a function which gets called with `5` as it's argument. If we pass `(+
2)` to `(flip ($) 5)`, we get `(flip ($) 5) (+2)` which is equivalent to the
expression `(+2) $ 5`, evaluating to `7`.
`flip ($) f` is equivalent to `\x -> x $ f`, that means, it takes as input a function and calls it with the function `f` as argument. `flip ($) f` is equivalent to `\x -> x $ f`, that means, it takes as input a
function and calls it with the function `f` as argument.
The composition of these functions works like this: First `flip ($)` takes `x` as it's first argument, and returns a function `(flip ($) x)`, this function is awaiting a function as it's last argument, which will be called with `x` as it's argument. Now this function `(flip ($) x)` is passed to `flip ($) f`, or to write it's equivalent `(\x -> x $ f) (flip ($) x)`, this results in the expression `(flip ($) x) f`, which is equivalent to `f $ x`. The composition of these functions works like this: First `flip ($)` takes `x`
as it's first argument, and returns a function `(flip ($) x)`, this function is
awaiting a function as it's last argument, which will be called with `x` as it's
argument. Now this function `(flip ($) x)` is passed to `flip ($) f`, or to
write it's equivalent `(\x -> x $ f) (flip ($) x)`, this results in the
expression `(flip ($) x) f`, which is equivalent to `f $ x`.
You can check the type of `(flip ($) f) . (flip ($))` is something like this (depending on your function `f`): You can check the type of `(flip ($) f) . (flip ($))` is something like this
(depending on your function `f`):
```haskell ```haskell
λ: let f = sqrt λ: let f = sqrt
@ -352,7 +414,9 @@ You can check the type of `(flip ($) f) . (flip ($))` is something like this (de
(flip ($) f) . (flip ($)) :: Floating c => c -> c (flip ($) f) . (flip ($)) :: Floating c => c -> c
``` ```
Also see [this question on Stack Overflow](https://stackoverflow.com/questions/46503793/applicative-prove-pure-f-x-pure-flip-x-pure-f/46505868#46505868) which includes alternative proofs. Also see [this question on Stack
Overflow](https://stackoverflow.com/questions/46503793/applicative-prove-pure-f-x-pure-flip-x-pure-f/46505868#46505868)
which includes alternative proofs.
## Instances ## Instances
@ -397,7 +461,9 @@ instance Applicative [] where
(Just f) <*> (Just x) = Just (f x) (Just f) <*> (Just x) = Just (f x)
``` ```
2. Determine the correct definition of `pure` for the `ZipList` instance of `Applicative`—there is only one implementation that satisfies the law relating `pure` and `(<*>)`. 2. Determine the correct definition of `pure` for the `ZipList` instance of
`Applicative`—there is only one implementation that satisfies the law
relating `pure` and `(<*>)`.
**Solution**: **Solution**:
@ -421,7 +487,9 @@ instance Applicative [] where
1. Implement a function 1. Implement a function
`sequenceAL :: Applicative f => [f a] -> f [a]` `sequenceAL :: Applicative f => [f a] -> f [a]`
There is a generalized version of this, `sequenceA`, which works for any `Traversable` (see the later section on `Traversable`), but implementing this version specialized to lists is a good exercise. There is a generalized version of this, `sequenceA`, which works for any
`Traversable` (see the later section on `Traversable`), but implementing
this version specialized to lists is a good exercise.
**Solution**: **Solution**:
@ -434,11 +502,18 @@ instance Applicative [] where
Explanation: Explanation:
First, `createList` is a simple function for creating a list of a single element, e.g. `createList 2 == [2]`. First, `createList` is a simple function for creating a list of a single
element, e.g. `createList 2 == [2]`.
Now let's take `sequenceAL` apart, first, it does a fold over the list `[f a]`, and `b` is initialized to `pure []`, which results in `f [a]` as required by the function's output. Now let's take `sequenceAL` apart, first, it does a fold over the list `[f
a]`, and `b` is initialized to `pure []`, which results in `f [a]` as
required by the function's output.
Inside the function, `createList <$> x` applies `createList` to the value inside `f a`, resulting in `f [a]`, and then `(++)` is applied to the value again, so it becomes `f ((++) [a])`, now we can apply the function `(++) [a]` to `b` by `((++) . createList <$> x) <*> b`, which results in `f ([a] ++ b)`. Inside the function, `createList <$> x` applies `createList` to the value
inside `f a`, resulting in `f [a]`, and then `(++)` is applied to the value
again, so it becomes `f ((++) [a])`, now we can apply the function `(++)
[a]` to `b` by `((++) . createList <$> x) <*> b`, which results in `f ([a]
++ b)`.
## Alternative formulation ## Alternative formulation
@ -504,7 +579,8 @@ In the laws above, `≅` refers to isomorphism rather than equality. In particul
f <*> a = fmap (uncurry ($)) (f ** a) = fmap (\(f, a) -> f a) (f ** a) f <*> a = fmap (uncurry ($)) (f ** a) = fmap (\(f, a) -> f a) (f ** a)
``` ```
2. Are there any `Applicative` instances for which there are also functions `f () -> ()` and `f (a,b) -> (f a, f b)`, satisfying some "reasonable" laws? 2. Are there any `Applicative` instances for which there are also functions `f
() -> ()` and `f (a,b) -> (f a, f b)`, satisfying some "reasonable" laws?
The [`Arrow`](https://wiki.haskell.org/Typeclassopedia#Arrow) type class seems to satisfy these criteria. The [`Arrow`](https://wiki.haskell.org/Typeclassopedia#Arrow) type class seems to satisfy these criteria.
@ -514,7 +590,8 @@ In the laws above, `≅` refers to isomorphism rather than equality. In particul
(id *** f) (a, b) = (f a, f b) (id *** f) (a, b) = (f a, f b)
``` ```
3. (Tricky) Prove that given your implementations from the first exercise, the usual Applicative laws and the Monoidal laws stated above are equivalent. 3. (Tricky) Prove that given your implementations from the first exercise, the
usual Applicative laws and the Monoidal laws stated above are equivalent.
1. Identity Law 1. Identity Law
@ -618,7 +695,8 @@ instance Monad Maybe where
| Node (f (Free f a)) | Node (f (Free f a))
``` ```
You may assume that `f` has a `Functor` instance. This is known as the _free monad_ built from the functor f. You may assume that `f` has a `Functor` instance. This is known as the _free
monad_ built from the functor f.
**Solution**: **Solution**:
@ -675,7 +753,8 @@ g >=> return = g
### Exercises ### Exercises
1. Given the definition `g >=> h = \x -> g x >>= h`, prove the equivalence of the above laws and the standard monad laws. 1. Given the definition `g >=> h = \x -> g x >>= h`, prove the equivalence of
the above laws and the standard monad laws.
**Solution**: **Solution**:
@ -714,14 +793,16 @@ class MonadTrans t where
**Solution**: **Solution**:
`t` is of the kind `(* -> *) -> * -> *`, as we see in `(t m) a`, `t` accepts a `Monad` first, which is of type `* -> *`, and then `t` is of the kind `(* -> *) -> * -> *`, as we see in `(t m) a`, `t` accepts
another argument of kind `*`. a `Monad` first, which is of type `* -> *`, and then another argument of
kind `*`.
## Composing Monads ## Composing Monads
### Exercises ### Exercises
1. Implement `join :: M (N (M (N a))) -> M (N a)` given `distrib :: N (M a) -> M (N a)` and assuming `M` and `N` are instances of `Monad`. 1. Implement `join :: M (N (M (N a))) -> M (N a)` given `distrib :: N (M a) -> M
(N a)` and assuming `M` and `N` are instances of `Monad`.
```haskell ```haskell
join :: M (N (M (N a))) -> M (N a) join :: M (N (M (N a))) -> M (N a)
@ -848,7 +929,9 @@ class Foldable t where
toList = foldMap (replicate 1) toList = foldMap (replicate 1)
``` ```
2. Show how one could implement the generic version of `foldr` in terms of `toList`, assuming we had only the list-specific `foldr :: (a -> b -> b) -> b -> [a] -> b`. 2. Show how one could implement the generic version of `foldr` in terms of
`toList`, assuming we had only the list-specific `foldr :: (a -> b -> b) -> b
-> [a] -> b`.
**Solution**: **Solution**:
@ -856,7 +939,11 @@ class Foldable t where
foldr f b c = foldr f b (toList c) foldr f b c = foldr f b (toList c)
``` ```
3. Pick some of the following functions to implement: `concat`, `concatMap`, `and`, `or`, `any`, `all`, `sum`, `product`, `maximum(By)`, `minimum(By)`, `elem`, `notElem`, and `find`. Figure out how they generalize to `Foldable` and come up with elegant implementations using `fold` or `foldMap` along with appropriate `Monoid` instances. 3. Pick some of the following functions to implement: `concat`, `concatMap`,
`and`, `or`, `any`, `all`, `sum`, `product`, `maximum(By)`, `minimum(By)`,
`elem`, `notElem`, and `find`. Figure out how they generalize to `Foldable`
and come up with elegant implementations using `fold` or `foldMap` along with
appropriate `Monoid` instances.
**Solution**: **Solution**:
@ -902,13 +989,22 @@ class Foldable t where
## Utility functions ## Utility functions
- `sequenceA_ :: (Applicative f, Foldable t) => t (f a) -> f ()` takes a container full of computations and runs them in sequence, discarding the results (that is, they are used only for their effects). Since the results are discarded, the container only needs to be Foldable. (Compare with `sequenceA :: (Applicative f, Traversable t) => t (f a) -> f (t a)`, which requires a stronger Traversable constraint in order to be able to reconstruct a container of results having the same shape as the original container.) - `sequenceA_ :: (Applicative f, Foldable t) => t (f a) -> f ()` takes a
container full of computations and runs them in sequence, discarding the
results (that is, they are used only for their effects). Since the results are
discarded, the container only needs to be Foldable. (Compare with `sequenceA
:: (Applicative f, Traversable t) => t (f a) -> f (t a)`, which requires a
stronger Traversable constraint in order to be able to reconstruct a container
of results having the same shape as the original container.)
- `traverse_ :: (Applicative f, Foldable t) => (a -> f b) -> t a -> f ()` applies the given function to each element in a foldable container and sequences the effects (but discards the results). - `traverse_ :: (Applicative f, Foldable t) => (a -> f b) -> t a -> f ()`
applies the given function to each element in a foldable container and
sequences the effects (but discards the results).
### Exercises ### Exercises
1. Implement `traverse_` in terms of `sequenceA_` and vice versa. One of these will need an extra constraint. What is it? 1. Implement `traverse_` in terms of `sequenceA_` and vice versa. One of these
will need an extra constraint. What is it?
**Solution**: **Solution**:
@ -920,7 +1016,9 @@ class Foldable t where
traverse_ f c = sequenceA_ (fmap f c) traverse_ f c = sequenceA_ (fmap f c)
``` ```
The additional constraint for implementing `traverse_` in terms of `sequenceA_` is the requirement of the `Foldable` instance `t` to be a `Functor` as well. The additional constraint for implementing `traverse_` in terms of
`sequenceA_` is the requirement of the `Foldable` instance `t` to be a
`Functor` as well.
Traversable Traversable
=========== ===========
@ -936,11 +1034,17 @@ sequenceA :: Applicative f => t (f a) -> f (t a)
1. There are at least two natural ways to turn a tree of lists into a list of trees. What are they, and why? 1. There are at least two natural ways to turn a tree of lists into a list of trees. What are they, and why?
Note: I'm not really sure whether my solution is _natural_, I think the question is rather ambiguous in the sense that it's not clear whether the trees in the final list of trees can have lists as their values, i.e. `Tree [Int] -> [Tree [Int]]` is valid or only `Tree [Int] -> [Tree Int]` is, but let me know if you think otherwise. Note: I'm not really sure whether my solution is _natural_, I think the
question is rather ambiguous in the sense that it's not clear whether the
trees in the final list of trees can have lists as their values, i.e. `Tree
[Int] -> [Tree [Int]]` is valid or only `Tree [Int] -> [Tree Int]` is, but
let me know if you think otherwise.
**Solution**: **Solution**:
One way is to put each `Node`, `Leaf` or `Empty` in a list in-order, this way the structure of the tree can be recovered from the list, here is a quick sketch (`[]` is an arbitrary list): One way is to put each `Node`, `Leaf` or `Empty` in a list in-order, this
way the structure of the tree can be recovered from the list, here is a
quick sketch (`[]` is an arbitrary list):
![tree to list](/img/typoclassopedia/tree.jpg) ![tree to list](/img/typoclassopedia/tree.jpg)
@ -953,7 +1057,9 @@ sequenceA :: Applicative f => t (f a) -> f (t a)
**Solution**: **Solution**:
To recover the original tree from the list of trees, whenever we encounter a `Node` in the list, we catch the next three values as left, value, and right nodes of the original node. To recover the original tree from the list of trees, whenever we encounter a
`Node` in the list, we catch the next three values as left, value, and right
nodes of the original node.
3. What is the type of `traverse . traverse`? What does it do? 3. What is the type of `traverse . traverse`? What does it do?
@ -979,7 +1085,9 @@ sequenceA :: Applicative f => t (f a) -> f (t a)
### Exercises ### Exercises
1. Implement `fmap` and `foldMap` using only the `Traversable` methods. (Note that the `Traversable` module provides these implementations as `fmapDefault` and `foldMapDefault`.) 1. Implement `fmap` and `foldMap` using only the `Traversable` methods. (Note
that the `Traversable` module provides these implementations as `fmapDefault`
and `foldMapDefault`.)
**Solution**: **Solution**:
@ -1034,14 +1142,22 @@ sequenceA :: Applicative f => t (f a) -> f (t a)
**Solution**: **Solution**:
First, in terms of laws, `Set` is not a `Functor`, thus it cannot be made into a `Traversable` instance, since `Traversable` instances require `Functor` superclasses. First, in terms of laws, `Set` is not a `Functor`, thus it cannot be made
into a `Traversable` instance, since `Traversable` instances require
`Functor` superclasses.
Second, on an intuitive level: In `Foldable`, the goal is not to keep the shape/structure of the original container, we are trying to reduce the container into some value, and the shape of the final result doesn't matter, but in `Traversable`, we ought to keep the structure of the final result, but we can't guarantee this while using `Set`s, because we can define some transformation `f :: Set a -> Set a` which reduces the length of the `Set`. Second, on an intuitive level: In `Foldable`, the goal is not to keep the
shape/structure of the original container, we are trying to reduce the
container into some value, and the shape of the final result doesn't matter,
but in `Traversable`, we ought to keep the structure of the final result,
but we can't guarantee this while using `Set`s, because we can define some
transformation `f :: Set a -> Set a` which reduces the length of the `Set`.
See [Foldable vs. Traversable](https://stackoverflow.com/questions/35857733/foldable-vs-traversable) and [Sets, Functors and Eq confusion](https://stackoverflow.com/questions/19177125/sets-functors-and-eq-confusion). and [Foldable and Traversable](https://wiki.haskell.org/Foldable_and_Traversable) for more details. See [Foldable vs. Traversable](https://stackoverflow.com/questions/35857733/foldable-vs-traversable) and [Sets, Functors and Eq confusion](https://stackoverflow.com/questions/19177125/sets-functors-and-eq-confusion). and [Foldable and Traversable](https://wiki.haskell.org/Foldable_and_Traversable) for more details.
4. Show that `Traversable` functors compose: that is, implement an instance for `Traversable (Compose f g)` given `Traversable` instances for `f` and `g`. 4. Show that `Traversable` functors compose: that is, implement an instance for
`Traversable (Compose f g)` given `Traversable` instances for `f` and `g`.
**Solution**: **Solution**:

View File

@ -8,40 +8,66 @@ math: true
author: Mahdi author: Mahdi
--- ---
On my way towards self-taught data science, I've stumbled upon the need to be proficient with mathematical proofs, so I picked up the amazing [How To Prove It: A Structured Approach](https://www.amazon.com/How-Prove-It-Structured-Approach/dp/0521675995) by Daniel J. Velleman; and I've been fascinated by mathematical proofs since then. On my way towards self-taught data science, I've stumbled upon the need to be
proficient with mathematical proofs, so I picked up the amazing [How To Prove
It: A Structured
Approach](https://www.amazon.com/How-Prove-It-Structured-Approach/dp/0521675995)
by Daniel J. Velleman; and I've been fascinated by mathematical proofs since
then.
One of the uses for [Mathematical Induction](https://en.wikipedia.org/wiki/Mathematical_induction) which I've found to be pretty cool is proving methods for tiling shapes. One of the uses for [Mathematical
Induction](https://en.wikipedia.org/wiki/Mathematical_induction) which I've
found to be pretty cool is proving methods for tiling shapes.
Here is an example: Here is an example:
Suppose $n$ is a positive integer. An equilateral triangle is cut into $4^n$ congruent equilateral triangles, and one corner is removed. Show that the remaining area can be covered by trapezoidal tiles like this: <img src='/img/tiling/trapezoidal.jpg' class='inline' width='30'/> Suppose $n$ is a positive integer. An equilateral triangle is cut into $4^n$
congruent equilateral triangles, and one corner is removed. Show that the
remaining area can be covered by trapezoidal tiles like this: <img
src='/img/tiling/trapezoidal.jpg' class='inline' width='30'/>
<canvas id='tiling-triangle' width='200' height='200' class='centered'></canvas> <canvas id='tiling-triangle' width='200' height='200' class='centered'></canvas>
{% include caption.html text='An example of n = 2. The dark tile is removed.' %} {% include caption.html text='An example of n = 2. The dark tile is removed.' %}
Just to be clear, by _cover_ we mean covering without any overlaps, so you can't have two overlapping trapezoidal tiles. Just to be clear, by _cover_ we mean covering without any overlaps, so you can't
have two overlapping trapezoidal tiles.
As with any mathematical induction solution, we start with the base case, which is $n = 1$, in that case the triangle looks like this: As with any mathematical induction solution, we start with the base case, which
is $n = 1$, in that case the triangle looks like this:
<canvas id='base-case' width='100' height='100' class='centered'></canvas> <canvas id='base-case' width='100' height='100' class='centered'></canvas>
In this case, it's obvious that we can cover the leftover area using trapezoidal tiles consisting of three equilateral triangles (the second row), so: In this case, it's obvious that we can cover the leftover area using trapezoidal
tiles consisting of three equilateral triangles (the second row), so:
---- ----
Base case: $n = 1$ then the triangle has $4^1 = 4$ tiles, and by removing the top-most tile, the second row can be covered using a single trapezoidal tile. Base case: $n = 1$ then the triangle has $4^1 = 4$ tiles, and by removing the
top-most tile, the second row can be covered using a single trapezoidal tile.
---- ----
Now for the induction step, we have to somehow show that after adding 1 to $n$, that is, by multiplying the tiles by $4$, we can still cover the triangle by trapezoidal tiles. To show this, we start by assuming we have a triangle with $4^n$ tiles, which we know can be covered by trapezoidal tiles, then we add the new tiles and show that they, too, can be covered by trapezoidal tiles. Now for the induction step, we have to somehow show that after adding 1 to $n$,
that is, by multiplying the tiles by $4$, we can still cover the triangle by
trapezoidal tiles. To show this, we start by assuming we have a triangle with
$4^n$ tiles, which we know can be covered by trapezoidal tiles, then we add the
new tiles and show that they, too, can be covered by trapezoidal tiles.
---- ----
Induction Step: Suppose we have a triangle split into $4^n$ tiles, and we know by induction hypothesis that it can be covered by trapezoidal tiles. Induction Step: Suppose we have a triangle split into $4^n$ tiles, and we know
by induction hypothesis that it can be covered by trapezoidal tiles.
Now suppose we have another triangle with $4^{n+1}$ tiles, that means, $4$ times as many triangles as our original triangle. We can then group the new bigger triangle into 4 congruent triangles, one of which we know can be split into trapezoidal tiles by removing one of it's tiles. Now suppose we have another triangle with $4^{n+1}$ tiles, that means, $4$ times
as many triangles as our original triangle. We can then group the new bigger
triangle into 4 congruent triangles, one of which we know can be split into
trapezoidal tiles by removing one of it's tiles.
For the three left triangles, we can find a neighbouring corner and assume the tile on that corner to be removed, and then cover the rest by trapezoidal tiles. Afterwards, since we had three such corners, and they are neighbouring corners, we can cover these three corners with one trapezoidal tile, thus completing the triangle. For the three left triangles, we can find a neighbouring corner and assume the
tile on that corner to be removed, and then cover the rest by trapezoidal tiles.
Afterwards, since we had three such corners, and they are neighbouring corners,
we can cover these three corners with one trapezoidal tile, thus completing the
triangle.
---- ----
@ -53,21 +79,29 @@ First, we split the whole triangle into 4 smaller groups:
<canvas id='n-2-grouped' width='200' height='200' class='centered'></canvas> <canvas id='n-2-grouped' width='200' height='200' class='centered'></canvas>
Then, we know that one of the triangles can be covered by trapezoidal tiles if we remove one of it's tiles, that's the induction hypothesis (the case for $4^n$ which is proved in the base case): Then, we know that one of the triangles can be covered by trapezoidal tiles if
we remove one of it's tiles, that's the induction hypothesis (the case for $4^n$
which is proved in the base case):
<canvas id='n-2-grouped-removed' width='200' height='200' class='centered'></canvas> <canvas id='n-2-grouped-removed' width='200' height='200' class='centered'></canvas>
Leaving the top triangle behind, we now find neighbouring corners among the three left triangles, and we assume the tiles in those corners to be removed (they are not actually removed as we are constrained to remove only one tile): Leaving the top triangle behind, we now find neighbouring corners among the
three left triangles, and we assume the tiles in those corners to be removed
(they are not actually removed as we are constrained to remove only one tile):
<canvas id='n-2-grouped-neighbours' width='200' height='200' class='centered'></canvas> <canvas id='n-2-grouped-neighbours' width='200' height='200' class='centered'></canvas>
Now we can cover the rest of these triangles by a single trapezoidal tile, similar to the case of $n = 1$. Now we can cover the rest of these triangles by a single trapezoidal tile,
similar to the case of $n = 1$.
Afterwards, we see that the three neighbouring tiles form a trapezoidal tile, therefore we can now put the last piece there to complete the tiles. Afterwards, we see that the three neighbouring tiles form a trapezoidal tile,
therefore we can now put the last piece there to complete the tiles.
<canvas id='final' width='200' height='200' class='centered'></canvas> <canvas id='final' width='200' height='200' class='centered'></canvas>
This procedure can be applied recursively on larger values of $n$ as well, so this concludes a proof of tiling an equilateral triangle divided into $4^n$ equilateral triangles using trapezoidal tiles after removing a single piece. This procedure can be applied recursively on larger values of $n$ as well, so
this concludes a proof of tiling an equilateral triangle divided into $4^n$
equilateral triangles using trapezoidal tiles after removing a single piece.
<script> <script>
(function() { (function() {

View File

@ -8,76 +8,164 @@ excerpt_separator: <!--more-->
author: Mahdi author: Mahdi
--- ---
Since 3 years ago, I have always been eager to move away from Google and other privacy-invading companies. I have had my successes and failures in doing so, here I'm going to put out my stack of tools for moving away from Google and going self-hosted. Since 3 years ago, I have always been eager to move away from Google and other
privacy-invading companies. I have had my successes and failures in doing so,
here I'm going to put out my stack of tools for moving away from Google and
going self-hosted.
<!--more--> <!--more-->
I first tried to move away from Google 3 years ago, and at the time, I did not have enough resources to self-host much. I started by creating my own email server, but I couldn't afford a cloud storage. I also did not know about the alternatives available to Google Calendar, Google Keep, and other tools I was using at the time, so it was pretty hard keeping up that way. I first tried to move away from Google 3 years ago, and at the time, I did not
have enough resources to self-host much. I started by creating my own email
server, but I couldn't afford a cloud storage. I also did not know about the
alternatives available to Google Calendar, Google Keep, and other tools I was
using at the time, so it was pretty hard keeping up that way.
After a year and a half, after my phone was stolen, I decided I will stick with Google apps with the coming of my new phone. I kept using Google services for less than a year, but I was frustrated. I had given up my privacy and control over my data for convenience, but that's not what I wanted. So I decided I'm going to switch away again, and I will self-host the tools necessary. After a year and a half, after my phone was stolen, I decided I will stick with
Google apps with the coming of my new phone. I kept using Google services for
less than a year, but I was frustrated. I had given up my privacy and control
over my data for convenience, but that's not what I wanted. So I decided I'm
going to switch away again, and I will self-host the tools necessary.
A lot has changed since the first time I switched away, I will sketch below the tools that I have replaced and how. A lot has changed since the first time I switched away, I will sketch below the
tools that I have replaced and how.
# microG # microG
If you want to avoid using Google Services on your Android phone, there is [microG](https://microg.org/) for that. I flashed my phone with an [AEX](http://aospextended.com/) ROM which supports microG, so it was not particularly hard to set-up on my phone, but I've heard it can be hard to set it up since it's doing some trickery to replace Google's services on your phone. If you want to avoid using Google Services on your Android phone, there is
[microG](https://microg.org/) for that. I flashed my phone with an
[AEX](http://aospextended.com/) ROM which supports microG, so it was not
particularly hard to set-up on my phone, but I've heard it can be hard to set it
up since it's doing some trickery to replace Google's services on your phone.
This also means you have to flash a custom ROM and root your device in order to do this, so maybe this option is not for everyone, but I think with Google Services active in your phone, you can't really be sure what's going on behind the curtains. This also means you have to flash a custom ROM and root your device in order to
do this, so maybe this option is not for everyone, but I think with Google
Services active in your phone, you can't really be sure what's going on behind
the curtains.
# Email # Email
One of the most common means of communication for us in the digital world, we exchange a lot of information through email, including personal and work-related information. As such, I deem email an important piece of privacy-sensitive information. One of the most common means of communication for us in the digital world, we
exchange a lot of information through email, including personal and work-related
information. As such, I deem email an important piece of privacy-sensitive
information.
My solution for email is a self-hosted Postfix + Dovecot + SpamAssassin on my server. It is not the most straightforward thing to set up, by [this DigitalOcean tutorial](https://www.digitalocean.com/community/tutorials/how-to-configure-a-mail-server-using-postfix-dovecot-mysql-and-spamassassin) makes it all the easier. My solution for email is a self-hosted Postfix + Dovecot + SpamAssassin on my
server. It is not the most straightforward thing to set up, by [this
DigitalOcean
tutorial](https://www.digitalocean.com/community/tutorials/how-to-configure-a-mail-server-using-postfix-dovecot-mysql-and-spamassassin)
makes it all the easier.
I have also heard of [Mail-in-a-Box](https://mailinabox.email/) which is supposed to make setting up your own mail server a breeze! I didn't know about this at the time I set up my server, but it could be a better choice, so perhaps give it a try and let me know. I have also heard of [Mail-in-a-Box](https://mailinabox.email/) which is
supposed to make setting up your own mail server a breeze! I didn't know about
this at the time I set up my server, but it could be a better choice, so perhaps
give it a try and let me know.
# Cloud Storage # Cloud Storage
A cloud storage is necessary for syncng your data among your devices and keeping your information safe from physical loss. I chose [Nextcloud](https://nextcloud.com/) and I couldn't be more satisfied. It has clients for every major operating system, and I use it to back up my files, synchronize my calendar and contacts between my Linux and my Android devices. A cloud storage is necessary for syncng your data among your devices and keeping
your information safe from physical loss. I chose
[Nextcloud](https://nextcloud.com/) and I couldn't be more satisfied. It has
clients for every major operating system, and I use it to back up my files,
synchronize my calendar and contacts between my Linux and my Android devices.
The installation and activation is fairly straightforward, and again, I followed a [DigitalOcean tutorial](https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-nextcloud-on-ubuntu-16-04) to set up the service and have been using it since. The installation and activation is fairly straightforward, and again, I followed
a [DigitalOcean
tutorial](https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-nextcloud-on-ubuntu-16-04)
to set up the service and have been using it since.
I also bought a DigitalOcean Space for $5/month, with a capacity of 250G, which is a fairly good price and worth its value. See [this discussion](https://www.digitalocean.com/community/questions/is-it-possible-to-mount-do-spaces-as-external-storage-in-nextcloud-as-i-mount-aws-s3-storage) about attaching a DigitalOcean space to Nextcloud. I also bought a DigitalOcean Space for $5/month, with a capacity of 250G, which
is a fairly good price and worth its value. See [this
discussion](https://www.digitalocean.com/community/questions/is-it-possible-to-mount-do-spaces-as-external-storage-in-nextcloud-as-i-mount-aws-s3-storage)
about attaching a DigitalOcean space to Nextcloud.
# Contacts and Calendar # Contacts and Calendar
I learned about [DAVx](https://f-droid.org/packages/at.bitfire.davdroid/) and [ICSx](https://f-droid.org/en/packages/at.bitfire.icsdroid/), which are tools for syncing your contacts and calendar, with support for Google Calendar as well. This means that I can still have access to my workplace calendar which is on Google, and have my own personal calendars synchronized using Nextcloud. I learned about [DAVx](https://f-droid.org/packages/at.bitfire.davdroid/) and
[ICSx](https://f-droid.org/en/packages/at.bitfire.icsdroid/), which are tools
for syncing your contacts and calendar, with support for Google Calendar as
well. This means that I can still have access to my workplace calendar which is
on Google, and have my own personal calendars synchronized using Nextcloud.
These tools integrate with whatever Calendar and Contacts application you are using on your phone, so you are free to choose whatever calendar and contacts application you like. These tools integrate with whatever Calendar and Contacts application you are
using on your phone, so you are free to choose whatever calendar and contacts
application you like.
# Notes # Notes
For note-taking, I use a simple Markdown/todo.txt editor called [Markor](https://f-droid.org/en/packages/net.gsantner.markor/) while Nextcloud handles the synchronization so I have access to my notes both on my computer and my phone. I use [vimwiki](https://github.com/vimwiki/vimwiki) to organize and edit my notes on my computer. Nextcloud also provides extra applications for editing Markdown files on the web interface, which is great if you like doing everything in your browser. For note-taking, I use a simple Markdown/todo.txt editor called
[Markor](https://f-droid.org/en/packages/net.gsantner.markor/) while Nextcloud
handles the synchronization so I have access to my notes both on my computer and
my phone. I use [vimwiki](https://github.com/vimwiki/vimwiki) to organize and
edit my notes on my computer. Nextcloud also provides extra applications for
editing Markdown files on the web interface, which is great if you like doing
everything in your browser.
# Application Store # Application Store
For downloading applications, I default to searching through [F-Droid](https://f-droid.org/en/), and in case I don't find the tool I'm looking for (which I mostly do!), or I'm looking for a properietary application, such as Slack, I use [Aurora Store](https://f-droid.org/en/packages/com.dragons.aurora/) or [Yalp Store](https://f-droid.org/en/packages/com.github.yeriomin.yalpstore/), which lets you search through all Google Play applications and install applications without a fuss. For downloading applications, I default to searching through
[F-Droid](https://f-droid.org/en/), and in case I don't find the tool I'm
looking for (which I mostly do!), or I'm looking for a properietary application,
such as Slack, I use [Aurora
Store](https://f-droid.org/en/packages/com.dragons.aurora/) or [Yalp
Store](https://f-droid.org/en/packages/com.github.yeriomin.yalpstore/), which
lets you search through all Google Play applications and install applications
without a fuss.
Of course, you can install the official Google Play store as well if you would like to, but I personally am cautious about using any of Google's applications. Of course, you can install the official Google Play store as well if you would
like to, but I personally am cautious about using any of Google's applications.
# Two-factor Authentication # Two-factor Authentication
I use [andOTP](https://github.com/andOTP/andOTP/) instead of Google Authenticator. One feature I love about andOTP is the ability to take an encrypted backup of your OTP keys, so you do not have to re-set all your two-factor authentications across all services if you ever want to switch your phone. I use [andOTP](https://github.com/andOTP/andOTP/) instead of Google
Authenticator. One feature I love about andOTP is the ability to take an
encrypted backup of your OTP keys, so you do not have to re-set all your
two-factor authentications across all services if you ever want to switch your
phone.
# Password Manager # Password Manager
I switched from LastPass, with its ugly, broken and distorted user experience to [BitWarden](https://bitwarden.com/), and I couldn't ask for more! The user experience is far superior compared to LastPass, the extension doesn't kill my browser's performance and the Android application is great, too! I switched from LastPass, with its ugly, broken and distorted user experience to
[BitWarden](https://bitwarden.com/), and I couldn't ask for more! The user
experience is far superior compared to LastPass, the extension doesn't kill my
browser's performance and the Android application is great, too!
# Firefox Containers # Firefox Containers
Lastly, it's natural that we can't completely avoid using Google's tools, we can just try to limit Google's access to our data and avoid being tracked as much as possible. For this purpose, I started using Firefox Containers, and God, this is a killer feature! Lastly, it's natural that we can't completely avoid using Google's tools, we can
just try to limit Google's access to our data and avoid being tracked as much as
possible. For this purpose, I started using Firefox Containers, and God, this is
a killer feature!
So now, I have a few containers set up: So now, I have a few containers set up:
- Personal: This one includes my personal accounts on websites other than Google that I want to stay logged-in on. - Personal: This one includes my personal accounts on websites other than Google
- Work: I'm logged into services that I use for work here, and it includes Google as well, but only for work. that I want to stay logged-in on.
- Google: This one, I use for accessing a personal Google Account I keep for YouTube and other services, but I'm not a serious user. - Work: I'm logged into services that I use for work here, and it includes
- [Temporary Containers](https://addons.mozilla.org/en-US/firefox/addon/temporary-containers/): Any websites that I have not explicitly chosen to be opened in one of the above containers, opens up in a new, temporary container, which means it doesn't have access to any cookies or information from the other containers. I may sometimes choose to open Google or other services in Temporary Containers as well if I don't see the necessity to be logged in. Google as well, but only for work.
- Google: This one, I use for accessing a personal Google Account I keep for
YouTube and other services, but I'm not a serious user.
- [Temporary
Containers](https://addons.mozilla.org/en-US/firefox/addon/temporary-containers/):
Any websites that I have not explicitly chosen to be opened in one of the
above containers, opens up in a new, temporary container, which means it
doesn't have access to any cookies or information from the other containers. I
may sometimes choose to open Google or other services in Temporary Containers
as well if I don't see the necessity to be logged in.
This means Google will not be able to track me using my account when I'm logged in to other services since they live in a different container, even though other methods such as [device fingerprinting](https://clearcode.cc/blog/device-fingerprinting/) are still possible. With Firefox's Tracking Protection and [uBlock](https://addons.mozilla.org/en-US/firefox/addon/ublock/) always turned on, I am less concerned about tracking. This means Google will not be able to track me using my account when I'm logged
in to other services since they live in a different container, even though other
methods such as [device
fingerprinting](https://clearcode.cc/blog/device-fingerprinting/) are still
possible. With Firefox's Tracking Protection and
[uBlock](https://addons.mozilla.org/en-US/firefox/addon/ublock/) always turned
on, I am less concerned about tracking.
# Not the easiet thing # Not the easiet thing
I have to admit, it's not the easiest thing to move your digital life away from the giants, their products are built for maximum convenience, so you can't expect to have that maximum convenience if you stop using those products, and I think it's a far-fetched ideal to expect the same level of convenience using free applications and tools, but I personally think it's worth it. I have to admit, it's not the easiest thing to move your digital life away from
the giants, their products are built for maximum convenience, so you can't
expect to have that maximum convenience if you stop using those products, and I
think it's a far-fetched ideal to expect the same level of convenience using
free applications and tools, but I personally think it's worth it.

View File

@ -7,9 +7,15 @@ categories: life, iran
author: Mahdi author: Mahdi
--- ---
Let me take you through a story on what it feels like to be isolated from the world, not by choice, but rather, by force. This is a story of discrimination, of monopoly, of people shrugging to these issues and of utterances that affect lives of millions. Let me take you through a story on what it feels like to be isolated from the
world, not by choice, but rather, by force. This is a story of discrimination,
of monopoly, of people shrugging to these issues and of utterances that affect
lives of millions.
Living in Iran, or any sanctioned country for that matter, you learn to read "anyone, anywhere" with an appendix of "except you". You soon learn "worldwide shipping" excludes you, that's when you start wondering, are you not living in "the world"? Where is this "world" they talk about? Living in Iran, or any sanctioned country for that matter, you learn to read
"anyone, anywhere" with an appendix of "except you". You soon learn "worldwide
shipping" excludes you, that's when you start wondering, are you not living in
"the world"? Where is this "world" they talk about?
Here is an example of a beautiful, hopeful message from Khan Academy: Here is an example of a beautiful, hopeful message from Khan Academy:
@ -17,81 +23,189 @@ Here is an example of a beautiful, hopeful message from Khan Academy:
{% include caption.html text='"Were a nonprofit with the mission to provide a free, world-class education for anyone, anywhere."' %} {% include caption.html text='"Were a nonprofit with the mission to provide a free, world-class education for anyone, anywhere."' %}
No one probably realizes that this is not true, but yes, Khan Academy is not available to Iranians, Cubans, Syrians, people of Crimea, and some others. That's because [they run on Google Cloud](https://cloud.google.com/customers/khan-academy/), an infrastructure provider that completely blocks all sanctioned countries from accessing any application hosted on it. Who else hosts their service there? Take a look at [342 notable customers](https://cloud.google.com/customers/) of Google Cloud, but remember, there are thousands more customers of Google Cloud and similar American infrastructure providers. No one probably realizes that this is not true, but yes, Khan Academy is not
available to Iranians, Cubans, Syrians, people of Crimea, and some others.
That's because [they run on Google
Cloud](https://cloud.google.com/customers/khan-academy/), an infrastructure
provider that completely blocks all sanctioned countries from accessing any
application hosted on it. Who else hosts their service there? Take a look at
[342 notable customers](https://cloud.google.com/customers/) of Google Cloud,
but remember, there are thousands more customers of Google Cloud and similar
American infrastructure providers.
But the story doesn't end here, of course. Let's go through the effects of sanctions on everyday lives of people, who have nothing to do with the politics of the country they are living in, and who are being discriminated only because they were born in geographical coordinates that lie in a certain boundary defined by people they don't even know. But the story doesn't end here, of course. Let's go through the effects of
sanctions on everyday lives of people, who have nothing to do with the politics
of the country they are living in, and who are being discriminated only because
they were born in geographical coordinates that lie in a certain boundary
defined by people they don't even know.
# The Internet # The Internet
The internet, the tool of the global society for communicating across the planet, _the_ tool for sharing knowledge with the human population across the world. The internet, the tool of the global society for communicating across the
planet, _the_ tool for sharing knowledge with the human population across the
world.
As if the Iranian government's blockage and censorship of the internet wasn't enough, we now have to deal with external sanctions blocking our access as well. Here's a gallery of blocked access messages we see on a daily basis: As if the Iranian government's blockage and censorship of the internet wasn't
enough, we now have to deal with external sanctions blocking our access as well.
Here's a gallery of blocked access messages we see on a daily basis:
![Various websites and their respective webpages seen only by sanctioned countries](/img/discrimination/403-forbidden-iran-sanctions.jpg) ![Various websites and their respective webpages seen only by sanctioned countries](/img/discrimination/403-forbidden-iran-sanctions.jpg)
{% include caption.html text='Various websites and their respective webpages seen only by sanctioned countries' %} {% include caption.html text='Various websites and their respective webpages seen only by sanctioned countries' %}
These websites include GitHub, Slack, Kaggle, Docker, GitLab, Amazon AWS, Twitter, Bluemix, Khan Academy and more. Here is a longer, developer-oriented (but definitely not exhaustive) list of hosts blocking our access: [freedomofdevelopers/domains](https://raw.githubusercontent.com/freedomofdevelopers/fod/master/domains). These websites include GitHub, Slack, Kaggle, Docker, GitLab, Amazon AWS,
Twitter, Bluemix, Khan Academy and more. Here is a longer, developer-oriented
(but definitely not exhaustive) list of hosts blocking our access:
[freedomofdevelopers/domains](https://raw.githubusercontent.com/freedomofdevelopers/fod/master/domains).
The websites that blocked our access mostly did it without prior notice, they just disabled our accounts, took our data from us, and did not let us even backup or export our data afterwards, in other words, lost messages, lost files and credentials. The websites that blocked our access mostly did it without prior notice, they
just disabled our accounts, took our data from us, and did not let us even
backup or export our data afterwards, in other words, lost messages, lost files
and credentials.
This, in part, is caused by the global monopoly of American companies such as Google, Amazon, GitHub and alike in their respective fields. This means if The United States decides to pressure a specific target, the target population is likely to be left without much of an alternative or option, since a great proportion of the land is covered by American companies. This, in part, is caused by the global monopoly of American companies such as
Google, Amazon, GitHub and alike in their respective fields. This means if The
United States decides to pressure a specific target, the target population is
likely to be left without much of an alternative or option, since a great
proportion of the land is covered by American companies.
Iranian users rely heavily on use of VPN services and proxy servers to bypass censorship, but now with most Cloud Providers blocking access of Iranians, we are left with limited, usually more expensive options for setting up these servers. Iranian users rely heavily on use of VPN services and proxy servers to bypass
censorship, but now with most Cloud Providers blocking access of Iranians, we
are left with limited, usually more expensive options for setting up these
servers.
This is a clear discrimination based on nationality and a breach of [Internet Freedom](https://en.wikipedia.org/wiki/Internet_freedom). These websites do not block us because we acted in a wrong way, or even, at cases, because we live in Iran, but because we were _born_ in Iran. Now, you may say this is because of the law and they have no choice. That's true in some cases, though most of the time the implementation of these laws seem to go further than what the laws actually require. The companies seem to go the _easy_ way by blocking access as much as they can to avoid holes in their system. This is a clear discrimination based on nationality and a breach of [Internet Freedom](https://en.wikipedia.org/wiki/Internet_freedom).
These websites do not block us because we acted in a wrong way, or even, at
cases, because we live in Iran, but because we were _born_ in Iran. Now, you may
say this is because of the law and they have no choice. That's true in some
cases, though most of the time the implementation of these laws seem to go
further than what the laws actually require. The companies seem to go the _easy_
way by blocking access as much as they can to avoid holes in their system.
# Drugs, Medicine, and Medical Devices # Drugs, Medicine, and Medical Devices
There are various sources and articles on how the U.S. sanctions have affected Iranian patients by limiting exports of drugs, medical devices or by indirectly disrupting the pharmaceutical industry by cutting exports of raw material used by these companies to produce medical drugs. Almost every person living in Iran can consciously feel the shortage of drugs and their growing price, but I will refer to an article on NCBI as a proof. There are various sources and articles on how the U.S. sanctions have affected
Iranian patients by limiting exports of drugs, medical devices or by indirectly
disrupting the pharmaceutical industry by cutting exports of raw material used
by these companies to produce medical drugs. Almost every person living in Iran
can consciously feel the shortage of drugs and their growing price, but I will
refer to an article on NCBI as a proof.
Quoting from [NCBI: Addressing the impact of economic sanctions on Iranian drug shortages in the joint comprehensive plan of action: promoting access to medicines and health diplomacy](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC4897941/): Quoting from [NCBI: Addressing the impact of economic sanctions on Iranian drug shortages in the joint comprehensive plan of action: promoting access to medicines and health diplomacy](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC4897941/):
<blockquote> <blockquote>
Although the revised and current Iranian sanctions regime does not specifically prohibit the export of humanitarian goods and pharmaceuticals, many of the administrative and regulatory processes have made it difficult to export life-saving medicines to Iran. This includes the need to navigate a complex export control regulatory process, the inability of Iranian banks to do business with the international banking system and U.S. corporations, currency shortages, and the inability to secure terms of shipping, insurance and other services needed to facilitate medicines trade [4]. As a result, millions of Iranians that suffer from life-threatening diseases have experienced “exorbitant prices”, stock outs of medicines, and are often forced to purchase drugs from the black market. Although the revised and current Iranian sanctions regime does not specifically
prohibit the export of humanitarian goods and pharmaceuticals, many of the
administrative and regulatory processes have made it difficult to export
life-saving medicines to Iran. This includes the need to navigate a complex
export control regulatory process, the inability of Iranian banks to do business
with the international banking system and U.S. corporations, currency shortages,
and the inability to secure terms of shipping, insurance and other services
needed to facilitate medicines trade [4]. As a result, millions of Iranians that
suffer from life-threatening diseases have experienced “exorbitant prices”,
stock outs of medicines, and are often forced to purchase drugs from the black
market.
[...] [...]
Severe medication shortages in Iran are diverse and span several therapeutic classes and disease states. This includes drug shortages for other critical areas of healthcare delivery, including organ transplant drugs, and even vaccine shortages. Severe medication shortages in Iran are diverse and span several therapeutic
classes and disease states. This includes drug shortages for other critical
areas of healthcare delivery, including organ transplant drugs, and even vaccine
shortages.
</blockquote> </blockquote>
And on the topic of weakening of the pharmaceutical companies: And on the topic of weakening of the pharmaceutical companies:
<blockquote> <blockquote>
Inaccessibility of vital medications and their raw ingredients combined with Irans weakening domestic pharmaceutical industry has also resulted in an influx of counterfeit, fraudulent, and substandard medicines into Irans health care system. An unregulated black market has developed as a byproduct of drug shortages, introducing medications whose origins and authenticity are often unknown, and has led to expired medications distribution and sale, even at potentially very high prices [8]. Hence, the global counterfeit medicines trade, recognized as a serious public health concern, is one that is currently being enabled as a consequence of drug shortages and ongoing Iranian economic sanctions Inaccessibility of vital medications and their raw ingredients combined with
Irans weakening domestic pharmaceutical industry has also resulted in an influx
of counterfeit, fraudulent, and substandard medicines into Irans health care
system. An unregulated black market has developed as a byproduct of drug
shortages, introducing medications whose origins and authenticity are often
unknown, and has led to expired medications distribution and sale, even at
potentially very high prices [8]. Hence, the global counterfeit medicines trade,
recognized as a serious public health concern, is one that is currently being
enabled as a consequence of drug shortages and ongoing Iranian economic
sanctions
</blockquote> </blockquote>
Foreign Policy also writes [U.S. Sanctions Are Killing Cancer Patients in Iran](https://foreignpolicy.com/2019/08/14/u-s-sanctions-are-killing-cancer-patients-in-iran/): Foreign Policy also writes [U.S. Sanctions Are Killing Cancer Patients in Iran](https://foreignpolicy.com/2019/08/14/u-s-sanctions-are-killing-cancer-patients-in-iran/):
> Washington claims that maximum pressure wont stop the supply of medicine and other humanitarian necessities, but banking sanctions are driving up import prices, blocking supply chains, and creating deadly drug shortages. > Washington claims that maximum pressure wont stop the supply of medicine and
other humanitarian necessities, but banking sanctions are driving up import
prices, blocking supply chains, and creating deadly drug shortages.
> Although U.S. sanctions are engineered in a way that may appear not to target humanitarian access to food and medicine, in practice U.S. sanctions function as a tool of economic war. > Although U.S. sanctions are engineered in a way that may appear not to target
humanitarian access to food and medicine, in practice U.S. sanctions function as
a tool of economic war.
[Health is a fundamental human right](https://www.who.int/mediacentre/news/statements/fundamental-human-right/en/), but the embargo clearly goes against giving people access to life-saving medicine. It brings tears to my eyes to think about people losing a loved one over inability to access a drug or medical device that's no longer available in Iran. [Health is a fundamental human right](https://www.who.int/mediacentre/news/statements/fundamental-human-right/en/),
but the embargo clearly goes against giving people access to life-saving
medicine. It brings tears to my eyes to think about people losing a loved one
over inability to access a drug or medical device that's no longer available in
Iran.
# Currency Fluctuations: An Unpredictable Life # Currency Fluctuations: An Unpredictable Life
I'm pretty sure most of the people reading this blog post, unless they are Iranians, will not find this section familiar. It's [fortunately] not a common experience across the planet, but let me tell you about living a life of zero predictability. I'm pretty sure most of the people reading this blog post, unless they are
Iranians, will not find this section familiar. It's [fortunately] not a common
experience across the planet, but let me tell you about living a life of zero
predictability.
Imagine this: You sell your car today, and you start a hunt for a new car to buy as a replacement. For the sake of the example, you are looking for a second-hand car. Imagine this: You sell your car today, and you start a hunt for a new car to buy
I will use a dummy currency unit here to simplify the example. You sold your car for 1000 units, and during the week you are looking for a new car, you start to see the car you just sold and every other car on the market, is gaining price exponentially. After a week, the same car that you sold is priced at 1800 units of currency and it's growing. It's like putting a car on neutral in a downward slope and seeing it go up the hill! Now you are left with 1000 units of currency, and you are only able to buy the same car if you put in your extra 800 savings, otherwise you are going to ride a car with significantly less quality or no car at all. More on [Iran's inflation](https://www.reuters.com/article/us-iran-economy-imf-idUSKCN1S509Q) as a result of tighter sanctions. as a replacement. For the sake of the example, you are looking for a second-hand
car. I will use a dummy currency unit here to simplify the example. You sold
your car for 1000 units, and during the week you are looking for a new car, you
start to see the car you just sold and every other car on the market, is gaining
price exponentially. After a week, the same car that you sold is priced at 1800
units of currency and it's growing. It's like putting a car on neutral in a
downward slope and seeing it go up the hill! Now you are left with 1000 units of
currency, and you are only able to buy the same car if you put in your extra 800
savings, otherwise you are going to ride a car with significantly less quality
or no car at all. More on [Iran's inflation](https://www.reuters.com/article/us-iran-economy-imf-idUSKCN1S509Q) as
a result of tighter sanctions.
I am pretty sure no matter how much I try to help you visualize this, you can not comprehend what it means to live in such a situation. I always use the metaphor of being a circus actor trying to balance on a moving cylinder to describe what it means to survive the fluctuations of our currency, which in turn affects all your expenses, but not your income. I am pretty sure no matter how much I try to help you visualize this, you can
not comprehend what it means to live in such a situation. I always use the
metaphor of being a circus actor trying to balance on a moving cylinder to
describe what it means to survive the fluctuations of our currency, which in
turn affects all your expenses, but not your income.
![Circus actor balancing on cylinders](/img/discrimination/act04-1.jpg) ![Circus actor balancing on cylinders](/img/discrimination/act04-1.jpg)
This is also an effect of the sanctions on the economy that we people feel with our every inch and are pressured by. This in turn causes a [rippling effect](#a-weak-economys-rippling-effect) on every other part of the society. Quoting [Explainer: the collapse of the Iranian rial](https://www.thenational.ae/business/economy/explainer-the-collapse-of-the-iranian-rial-1.754707) This is also an effect of the sanctions on the economy that we people feel with
our every inch and are pressured by. This in turn causes a [rippling effect](#a-weak-economys-rippling-effect) on every other part of the society.
Quoting [Explainer: the collapse of the Iranian rial](https://www.thenational.ae/business/economy/explainer-the-collapse-of-the-iranian-rial-1.754707)
<blockquote> <blockquote>
Has the US decision made things worse? Has the US decision made things worse?
Yes. Mr Trumps decision to exit the US-Iran nuclear agreement signed in 2015 has dented Irans economic outlook and set in motion a cascade of damaging effects. It has deterred global companies from doing business with Iran, leading to a liquidity crunch and a lack of foreign exchange in the country. US measures also put pressure on a banking system already strained by the previous sanctions regime before the adoption of the JCPOA in January 2016. Yes. Mr Trumps decision to exit the US-Iran nuclear agreement signed in 2015
has dented Irans economic outlook and set in motion a cascade of damaging
effects. It has deterred global companies from doing business with Iran, leading
to a liquidity crunch and a lack of foreign exchange in the country. US measures
also put pressure on a banking system already strained by the previous sanctions
regime before the adoption of the JCPOA in January 2016.
A re-imposition of sanctions is expected to cause a drop in Iranian oil exports, with severe repercussions. Iran is home to the worlds largest reserves of gas and is the Middle Easts third-largest oil producer. In May, BMI downgraded its GDP growth forecast for Iran to 3.1 per cent in 2018 and 0.8 per cent in 2019, from 4.3 per cent and 4.5 per cent previously. A re-imposition of sanctions is expected to cause a drop in Iranian oil exports,
with severe repercussions. Iran is home to the worlds largest reserves of gas
and is the Middle Easts third-largest oil producer. In May, BMI downgraded its
GDP growth forecast for Iran to 3.1 per cent in 2018 and 0.8 per cent in 2019,
from 4.3 per cent and 4.5 per cent previously.
“Iran is likely to experience depreciatory pressures on the rial and rising inflation as a result of lower foreign currency inflows that will constrain domestic investment and consumption,” BMI said. “Iran is likely to experience depreciatory pressures on the rial and rising
inflation as a result of lower foreign currency inflows that will constrain
domestic investment and consumption,” BMI said.
</blockquote> </blockquote>
Unpredictability is only part of the story, in general a high inflation rate means a degradation of life quality over time, and a lower quality of life includes a lack of access to even the most basic needs. It means having to put your children in less qualified schools, it means avoiding doctor appointments by any means necessary, it means cutting corners in every section of your life, it means a less balanced environment to live in, an environment where people get angry more easily since they are under a constant pressure as a cause of their degrading lives. No matter how hard you try, your life quality only goes downhill, never up. Unpredictability is only part of the story, in general a high inflation rate
means a degradation of life quality over time, and a lower quality of life
includes a lack of access to even the most basic needs. It means having to put
your children in less qualified schools, it means avoiding doctor appointments
by any means necessary, it means cutting corners in every section of your life,
it means a less balanced environment to live in, an environment where people get
angry more easily since they are under a constant pressure as a cause of their
degrading lives. No matter how hard you try, your life quality only goes
downhill, never up.
# A Weak Economy's Rippling Effect # A Weak Economy's Rippling Effect
@ -99,49 +213,137 @@ You have probably heard of [Maslow's Hierarchy of Needs](https://en.wikipedia.or
![Maslow's Hierarchy of Needs. A pyramid, from top to bottom: Self-Actualization, Esteem, Love/Belonging, Safety, Physiological](/img/discrimination/maslow.jpg) ![Maslow's Hierarchy of Needs. A pyramid, from top to bottom: Self-Actualization, Esteem, Love/Belonging, Safety, Physiological](/img/discrimination/maslow.jpg)
At the bottom, there are physiological needs, like health, food, water, sleep, shelter and sex. Only once these needs are fulfilled properly, you get motivated to even think about the next level. That means, if your physiological needs are not properly safisfied, you will not even think about safety, love and belonging, self-esteem or self-actualization. At the bottom, there are physiological needs, like health, food, water, sleep,
shelter and sex. Only once these needs are fulfilled properly, you get motivated
to even think about the next level. That means, if your physiological needs are
not properly safisfied, you will not even think about safety, love and
belonging, self-esteem or self-actualization.
Now, what all these physiological needs have in common is that they are fulfilled when there is a stable economic backbone in the country you live in. Once the economic backbone is broken, you begin losing access to these physiological needs. Slowly, but surely, you lose your motivation for self-actualization, for self-esteem, for love and belonging and for safety and you hunt for your physiological needs. Once this happens for a whole population in a country, you are left with people with only one goal in their lives: to survive _by any means_. Now, what all these physiological needs have in common is that they are
fulfilled when there is a stable economic backbone in the country you live in.
Once the economic backbone is broken, you begin losing access to these
physiological needs. Slowly, but surely, you lose your motivation for
self-actualization, for self-esteem, for love and belonging and for safety and
you hunt for your physiological needs. Once this happens for a whole population
in a country, you are left with people with only one goal in their lives: to
survive _by any means_.
With no motivation for building strong friendships and relationships, no motivation for security and safety, for feeling of accomplishment and for creative acts, the population transitions towards becoming one unsafe, cold, threatening, untrustable environment with no sense of joy or creativity. With no motivation for building strong friendships and relationships, no
motivation for security and safety, for feeling of accomplishment and for
creative acts, the population transitions towards becoming one unsafe, cold,
threatening, untrustable environment with no sense of joy or creativity.
I'm driving from my friend's house back to mine, it's roughly 10pm and streets are a little crowded. I'm going through streets of Azadi District, when I see two children who are probably between 15 and 17, punching each other in the face and kicking each other's stomach over a large trash container at the side of the street. They are fighting, as if for their lives, with a ferocity you can hardly imagine to find in a child of their age. These children do not look anything like your children, their hands are black from their fingertips to their elbows from collecting trash all day long; their clothes are not new, they do not change their clothes or take showers daily, and their backs are arched for hauling a large bag of trash for a whole day over their shoulder and back. They are fighting to win a trash container. This is what happens when you put pressure on the economy of a country. This is what the media is not telling you about the effects of sanctions. This is what needs to stop about these sanctions. This is what needs action from every person knowledgable to do something to stop it. Abuse, rape and misuse of children and adults alike is a significant, visible effect of sanctions that's often overlooked. I'm driving from my friend's house back to mine, it's roughly 10pm and streets
are a little crowded. I'm going through streets of Azadi District, when I see
two children who are probably between 15 and 17, punching each other in the face
and kicking each other's stomach over a large trash container at the side of the
street. They are fighting, as if for their lives, with a ferocity you can hardly
imagine to find in a child of their age. These children do not look anything
like your children, their hands are black from their fingertips to their elbows
from collecting trash all day long; their clothes are not new, they do not
change their clothes or take showers daily, and their backs are arched for
hauling a large bag of trash for a whole day over their shoulder and back. They
are fighting to win a trash container. This is what happens when you put
pressure on the economy of a country. This is what the media is not telling you
about the effects of sanctions. This is what needs to stop about these
sanctions. This is what needs action from every person knowledgable to do
something to stop it. Abuse, rape and misuse of children and adults alike is a
significant, visible effect of sanctions that's often overlooked.
It's sad that I can not find any content regarding this matter in the media by searching. I think more content on these topics is necessary to help people be aware of the unethical and inhumane effects of sanctions on lives of innocent people. It's sad that I can not find any content regarding this matter in the media by
searching. I think more content on these topics is necessary to help people be
aware of the unethical and inhumane effects of sanctions on lives of innocent
people.
![A teenager collecting trash in Iran](/img/discrimination/trash-collecting.jpg) ![A teenager collecting trash in Iran](/img/discrimination/trash-collecting.jpg)
{% include caption.html text='A teenage collecting trash in the streets of Tehran.' %} {% include caption.html text='A teenage collecting trash in the streets of Tehran.' %}
The rippling effects of a weakening economy are far worse and far-reaching than what the sanctions are supposed to do. I think it's too optimistic to think sanctions to weaken an economy will prevent a country from spending money on something they want to spend on. What ends up happening, or at least has happened in case of Iran, is that the money is drained from places where it affects peoples lives, but I doubt anything has changed at the actual target. The rippling effects of a weakening economy are far worse and far-reaching than
what the sanctions are supposed to do. I think it's too optimistic to think
sanctions to weaken an economy will prevent a country from spending money on
something they want to spend on. What ends up happening, or at least has
happened in case of Iran, is that the money is drained from places where it
affects peoples lives, but I doubt anything has changed at the actual target.
# Of Rolling Eyes and Shrugs # Of Rolling Eyes and Shrugs
Often when similar stories of this kind are shared, I am ready to see comments of people shrugging to the issue with responses like "they have to comply because it's the law" or "that's how you respond to a country that wants to build nuclear weapons" or similar. They just roll their eyes and shrug it off like this is how it's supposed to be. Often when similar stories of this kind are shared, I am ready to see comments
of people shrugging to the issue with responses like "they have to comply
because it's the law" or "that's how you respond to a country that wants to
build nuclear weapons" or similar. They just roll their eyes and shrug it off
like this is how it's supposed to be.
Sometimes, that's true that it's the law and the companies have to comply (though most of the time the application of the law goes way beyond necessity). What these responses get wrong is that there is no involvement by us, the people, in the decisions and policies of our country. Solely because I live my daily life in a geographical location that resides in the boundaries of a place on Earth known as "Iran" doesn't mean I agree with the politics of this country, or that I should be isolated from the rest of the world because some people in my country make certain decisions. Sometimes, that's true that it's the law and the companies have to comply
(though most of the time the application of the law goes way beyond necessity).
What these responses get wrong is that there is no involvement by us, the
people, in the decisions and policies of our country. Solely because I live my
daily life in a geographical location that resides in the boundaries of a place
on Earth known as "Iran" doesn't mean I agree with the politics of this country,
or that I should be isolated from the rest of the world because some people in
my country make certain decisions.
What these replies get wrong is that in democratic countries, laws can change based on what people demand. Instead of shrugging these humanitarian issues off, please hear us out, and help echo our voice. You may not realize, but we, the people of Iran, do not have a say in what what politics our government follows or how it interacts with other countries, but you do have a say in yours. The only thing we can do is to spread the word. What these replies get wrong is that in democratic countries, laws can change
based on what people demand. Instead of shrugging these humanitarian issues off,
please hear us out, and help echo our voice. You may not realize, but we, the
people of Iran, do not have a say in what what politics our government follows
or how it interacts with other countries, but you do have a say in yours. The
only thing we can do is to spread the word.
What we feel when we see these responses is: "They are terrorists so let them be", but we are not. We are normal people like you, with less privileges, solely because of our living region. What we feel when we see these responses is: "They are terrorists so let them
be", but we are not. We are normal people like you, with less privileges, solely
because of our living region.
It seems like the Iranian people are now the common enemy of all sides of a global conflict. The ever-increasing pressure we feel is not from a single source, but rather, from all sides. We have internet censorship from the inside and restricted access from the outside. We have economic pressure from the inside, with a direct influence from the outside, and the same applies to every part of this conflict. It seems like the Iranian people are now the common enemy of all sides of a
global conflict. The ever-increasing pressure we feel is not from a single
source, but rather, from all sides. We have internet censorship from the inside
and restricted access from the outside. We have economic pressure from the
inside, with a direct influence from the outside, and the same applies to every
part of this conflict.
# Final Message # Final Message
[Racism](https://en.wikipedia.org/wiki/Racism) is defined as "prejudice, [discrimination](https://en.wikipedia.org/wiki/Discrimination), or antagonism directed towards other people because they are of a different race or ethnicity". Sanctions, likewise, are a clear case of prejudice, discrimination and antagonism directed towards people because they are born in a certain country, or reside in a certain part of the planet. [Racism](https://en.wikipedia.org/wiki/Racism) is defined as "prejudice,
[discrimination](https://en.wikipedia.org/wiki/Discrimination), or antagonism
directed towards other people because they are of a different race or
ethnicity". Sanctions, likewise, are a clear case of prejudice, discrimination
and antagonism directed towards people because they are born in a certain
country, or reside in a certain part of the planet.
If a person is jailed, or killed because of the color of their skin, you feel furious and protest against the act to show that racism has no place in your country. Sanctions are a case of jailing a whole country, killing the people inside by cutting their lifelines and causing lifetime distress for innocent people who didn't do anything wrong. It's discrimination on the scale of a whole population of millions. Although the people who are being effected by these sanctions are far away from your home, their misery is caused by your country's policies and actions, and you have the right to stand up against these discriminations. If a person is jailed, or killed because of the color of their skin, you feel
furious and protest against the act to show that racism has no place in your
country. Sanctions are a case of jailing a whole country, killing the people
inside by cutting their lifelines and causing lifetime distress for innocent
people who didn't do anything wrong. It's discrimination on the scale of a whole
population of millions. Although the people who are being effected by these
sanctions are far away from your home, their misery is caused by your country's
policies and actions, and you have the right to stand up against these
discriminations.
Ron Paul, former congressman [touches on topic in an interview](https://twitter.com/RonPaul/status/1162067004733476864): Ron Paul, former congressman [touches on topic in an
interview](https://twitter.com/RonPaul/status/1162067004733476864):
> I think sanctions are really really bad, because it brings people in to think that "well I'm not quite as violent as other people who would use a drone", well, hopefully it is a little bit less violent, but it's every bit as dangerous, it's still attacking personal liberties and it's undermining the principle of trying to get along with people with free trade. > I think sanctions are really really bad, because it brings people in to think
that "well I'm not quite as violent as other people who would use a drone",
well, hopefully it is a little bit less violent, but it's every bit as
dangerous, it's still attacking personal liberties and it's undermining the
principle of trying to get along with people with free trade.
[The Universal Declaration of Human Rights](https://en.wikipedia.org/wiki/Universal_Declaration_of_Human_Rights), Article 2, states: [The Universal Declaration of Human
Rights](https://en.wikipedia.org/wiki/Universal_Declaration_of_Human_Rights),
Article 2, states:
> Everyone is entitled to all the rights and freedoms set forth in this Declaration, without distinction of any kind, such as race, colour, sex, language, religion, political or other opinion, national or social origin, property, birth or other status. > Everyone is entitled to all the rights and freedoms set forth in this
> Furthermore, no distinction shall be made on the basis of the political, jurisdictional or international status of the country or territory to which a person belongs, whether it be independent, trust, non-self-governing or under any other limitation of sovereignty. Declaration, without distinction of any kind, such as race, colour, sex,
language, religion, political or other opinion, national or social origin,
property, birth or other status. > Furthermore, no distinction shall be made on
the basis of the political, jurisdictional or international status of the
country or territory to which a person belongs, whether it be independent,
trust, non-self-governing or under any other limitation of sovereignty.
That doesn't sound like what's happening now by enforcement of sanctions. Silence on this massive case of discrimination against people around the world must be broken, it must be recognized that discrimination, in any form, is not to be tolerated by humans. That doesn't sound like what's happening now by enforcement of sanctions.
Silence on this massive case of discrimination against people around the world
must be broken, it must be recognized that discrimination, in any form, is not
to be tolerated by humans.
--- ---

View File

@ -8,73 +8,165 @@ categories: philosophy
author: Mahdi author: Mahdi
--- ---
As a computer scientist and someone who loves [mathematics](/mathematical-induction-proving-tiling-methods) and [abstractions](/typoclassopedia-exercise-solutions), I was obsessed with the idea of rationality, that is, an _objective_ and absolute rationality, however I ended up in a philosophy course that showed me the opposite. As a computer scientist and someone who loves
[mathematics](/mathematical-induction-proving-tiling-methods) and
[abstractions](/typoclassopedia-exercise-solutions), I was obsessed with the
idea of rationality, that is, an _objective_ and absolute rationality, however I
ended up in a philosophy course that showed me the opposite.
I somehow stumbled upon Eliezer Yudkowsky's [Rationality: From AI to Zombies](https://www.readthesequences.com/) about 4 years ago, and it took me two years to go through it all but I was absolutely fascinated by this book. I _knew_ how to be rational now, and I could _prove_ it using mathematics, what else could I ask for! I somehow stumbled upon Eliezer Yudkowsky's [Rationality: From AI to
Zombies](https://www.readthesequences.com/) about 4 years ago, and it took me
two years to go through it all but I was absolutely fascinated by this book. I
_knew_ how to be rational now, and I could _prove_ it using mathematics, what
else could I ask for!
The book basically looks at the world as a probabilistic system, and everything that happens can be assigned probabilities, and using mathematical theorems such as Bayes Theorem, we can predict outcomes of certain actions and then decide between them. There is a lot of focus on [cognitive biases](https://en.wikipedia.org/wiki/List_of_cognitive_biases) as well. I was particularly very interested about these biases, and so I set out to learn more about them, and that's how I found my current course: [Cognitive Science at University College Dublin](https://cogsci.ucd.ie). The book basically looks at the world as a probabilistic system, and everything
that happens can be assigned probabilities, and using mathematical theorems such
as Bayes Theorem, we can predict outcomes of certain actions and then decide
between them. There is a lot of focus on [cognitive
biases](https://en.wikipedia.org/wiki/List_of_cognitive_biases) as well. I was
particularly very interested about these biases, and so I set out to learn more
about them, and that's how I found my current course: [Cognitive Science at
University College Dublin](https://cogsci.ucd.ie).
So I enter this course with this mindset: we can objectively analyse the world around us using probability and statistics (mathematics), but we are limited by our cognitive biases, so I want to learn about these cognitive biases: where do they come from, how can they be resisted to allow us to act more rationally and so on. These questions would mainly fall under the umbrella of psychology... So I enter this course with this mindset: we can objectively analyse the world
around us using probability and statistics (mathematics), but we are limited by
our cognitive biases, so I want to learn about these cognitive biases: where do
they come from, how can they be resisted to allow us to act more rationally and
so on. These questions would mainly fall under the umbrella of psychology...
However... I found myself to be more and more interested in the philosophy side of this course than the psychology side, hell I even started to not like the psychology side anymore, but fall in love with the philosophy. This is where I found the opposite of what I had come for: an alternative definition of objectivity, and an inherent subjectivity of some things. This is mainly inspired by Thomas Nagel's What Is It Like To Be A Bat {% cite nagel1974like %}. However... I found myself to be more and more interested in the philosophy side
of this course than the psychology side, hell I even started to not like the
psychology side anymore, but fall in love with the philosophy. This is where I
found the opposite of what I had come for: an alternative definition of
objectivity, and an inherent subjectivity of some things. This is mainly
inspired by Thomas Nagel's What Is It Like To Be A Bat {% cite nagel1974like %}.
What is Objectivity Anyway? What is Objectivity Anyway?
--------------------------- ---------------------------
This is probably the main question here. What is objectivity? I don't think dictionary definitions are particularly authoritative when it comes to philosophy discussions, but I found this dictionary definition interesting to open the topic with: This is probably the main question here. What is objectivity? I don't think
dictionary definitions are particularly authoritative when it comes to
philosophy discussions, but I found this dictionary definition interesting to
open the topic with:
> the quality or character of being objective : lack of favoritism toward one side or another : freedom from bias. {% cite objectivity-merriam-webster %} > the quality or character of being objective : lack of favoritism toward one
side or another : freedom from bias. {% cite objectivity-merriam-webster %}
This definition itself has ambiguous phrases such as "freedom from bias", what does that mean? When can we say that we are free from bias? Let's look at how bias is defined in the same dictionary: This definition itself has ambiguous phrases such as "freedom from bias", what
does that mean? When can we say that we are free from bias? Let's look at how
bias is defined in the same dictionary:
> an inclination of temperament or outlook {% cite bias-merriam-webster %} > an inclination of temperament or outlook {% cite bias-merriam-webster %}
But... is it really possible to have no inclination at all in our temperament and outlook? Let's look at the definition of subjective, that will help us here: But... is it really possible to have no inclination at all in our temperament
and outlook? Let's look at the definition of subjective, that will help us here:
> relating to the way a person experiences things in his or her own mind {% cite subjective-merriam-webster %} > relating to the way a person experiences things in his or her own mind {% cite
subjective-merriam-webster %}
Is it possible for us to have a view of something without it being part of our experience? It seems not. All that we do, all our views and expressions and our interactions are part of our experience as a person, and it relates to us on an intimate level, which means that everything that we do as individuals is subjective. In that sense, it seems impossible for any individual to be objective, since they will always have some form of inclination about everything. Is it possible for us to have a view of something without it being part of our
experience? It seems not. All that we do, all our views and expressions and our
interactions are part of our experience as a person, and it relates to us on an
intimate level, which means that everything that we do as individuals is
subjective. In that sense, it seems impossible for any individual to be
objective, since they will always have some form of inclination about
everything.
What does this leave us with then when we ask what is objectivity? A better definition of objectivity in my opinion is one given by Thomas Nagel: What does this leave us with then when we ask what is objectivity? A better
definition of objectivity in my opinion is one given by Thomas Nagel:
> It may be more accurate to think of objectivity as a direction in which the understanding can travel. [...] The process of reduction is a move in the direction of greater objectivity, toward a more accurate view of the real nature of things. This is accomplished by reducing our dependence on individual or species-specific points of view toward the object of investigation. We describe it not in terms of the impressions it makes on our senses, but in terms of its more general effects and of properties detectable by means other than the human senses. {% cite nagel1974like %} > It may be more accurate to think of objectivity as a direction in which the
understanding can travel. [...] The process of reduction is a move in the
direction of greater objectivity, toward a more accurate view of the real nature
of things. This is accomplished by reducing our dependence on individual or
species-specific points of view toward the object of investigation. We describe
it not in terms of the impressions it makes on our senses, but in terms of its
more general effects and of properties detectable by means other than the human
senses. {% cite nagel1974like %}
In this sense, there is no black-and-white distinction between subjectivity and objectivity, but rather it is a spectrum, a line on which we can walk from subjectivity towards objectivity. In this sense, there is no black-and-white distinction between subjectivity and
objectivity, but rather it is a spectrum, a line on which we can walk from
subjectivity towards objectivity.
![Subjective-Objective spectrum: On Subjective side we have Individual perception, in the middle Agreement with others, and on the Objective side Agreement with other apparatus](/img/inherent-subjectivity/subjective-objective.png) ![Subjective-Objective spectrum: On Subjective side we have Individual perception, in the middle Agreement with others, and on the Objective side Agreement with other apparatus](/img/inherent-subjectivity/subjective-objective.png)
We start with our individual perceptions as the most objective view and description, we then move towards descriptions that allow us to agree with other (human) beings, and finally we move towards descriptions that can be verified and agreed upon by other apparatus, although it is important to understand that even the apparatus that we may use to describe things are not necessarily free from bias, since they are created by biased individuals and groups. By now you may notice that if a measuring device is made to be agreeable between a large group of people, it is already more objective than a device made by a single individual! However, absolute objectivity, which we may call "a view from nowhere" may not be attainable by us, because we will always be viewing things from our own perspectives, even if it is a large, collective perspective that we agree on, it is not a view from nowhere. We start with our individual perceptions as the most objective view and
description, we then move towards descriptions that allow us to agree with other
(human) beings, and finally we move towards descriptions that can be verified
and agreed upon by other apparatus, although it is important to understand that
even the apparatus that we may use to describe things are not necessarily free
from bias, since they are created by biased individuals and groups. By now you
may notice that if a measuring device is made to be agreeable between a large
group of people, it is already more objective than a device made by a single
individual! However, absolute objectivity, which we may call "a view from
nowhere" may not be attainable by us, because we will always be viewing things
from our own perspectives, even if it is a large, collective perspective that we
agree on, it is not a view from nowhere.
![Subjective-Objective spectrum: A single person says a ball is 10cm radius, 1/4 objectivity. A group of people say it's 10cm radius, 1/2 objectivity. A group of people with a ruler say it's 10cm radius, 3/4 objectivity](/img/inherent-subjectivity/subjective-objective-example.png) ![Subjective-Objective spectrum: A single person says a ball is 10cm radius, 1/4 objectivity. A group of people say it's 10cm radius, 1/2 objectivity. A group of people with a ruler say it's 10cm radius, 3/4 objectivity](/img/inherent-subjectivity/subjective-objective-example.png)
Inherently Subjective Things Inherently Subjective Things
---------------------------- ----------------------------
With our definition of objectivity in place, now let's see: is there something that we cannot move towards objectivity about? Yes. That is our personal experiences. With our definition of objectivity in place, now let's see: is there something
that we cannot move towards objectivity about? Yes. That is our personal
experiences.
See, if there is an attempt to give a more objective description of _my_ personal experience, there will need to be either an agreement among a group of beings about this description of my personal experience, or there should be an apparatus that we can agree on that measures my personal experience. However, my personal experience is personal exactly because it is completely dependent and originated from my perspective alone, and no one else's; and as soon as you try to move towards objectivity by trying to describe this experience in a way that moves away from my person-specific and species-specific standpoint, towards a more agreeable and general description that even non-human beings or apparatus can agree with, you lose the initial personal experience in the process, so you end up with a non-personal description of the experience which misses the point of the actual subjective experience I have. See, if there is an attempt to give a more objective description of _my_
personal experience, there will need to be either an agreement among a group of
beings about this description of my personal experience, or there should be an
apparatus that we can agree on that measures my personal experience. However, my
personal experience is personal exactly because it is completely dependent and
originated from my perspective alone, and no one else's; and as soon as you try
to move towards objectivity by trying to describe this experience in a way that
moves away from my person-specific and species-specific standpoint, towards a
more agreeable and general description that even non-human beings or apparatus
can agree with, you lose the initial personal experience in the process, so you
end up with a non-personal description of the experience which misses the point
of the actual subjective experience I have.
So, you can come up with _some_ description of my experience, but you can't actually describe the subjective experience of being me as it really is. The walk towards objectivity requires you to drop the subjectivity of my experience, and hence, some inherently subjective things such as our personal experiences can't be objectified. So, you can come up with _some_ description of my experience, but you can't
actually describe the subjective experience of being me as it really is. The
walk towards objectivity requires you to drop the subjectivity of my experience,
and hence, some inherently subjective things such as our personal experiences
can't be objectified.
This is how Nagel puts it (I think this may be a bit hard to read without reading the whole paper): This is how Nagel puts it (I think this may be a bit hard to read without
reading the whole paper):
> Experience itself, however, does not seem to fit the pattern. The idea of moving from appearance to reality seems to make no sense here. What is the analogue in this case to pursuing a more objective understanding of the same phenomena by abandoning the initial subjective viewpoint toward them in favor of another that is more objective but concerns the same thing? Certainly it appears unlikely that we will get closer to the real nature of human experience by leaving behind the particularity of our human point of view and striving for a description in terms accessible to beings that could not imagine what it was like to be us. If the subjective character of experience is fully comprehensible only from one point of view, then any shift to greater objectivity that is, less attachment to a specific viewpoint does not take us nearer to the real nature of the phenomenon: it takes us farther away from it. {% cite nagel1974like %} > Experience itself, however, does not seem to fit the pattern. The idea of
moving from appearance to reality seems to make no sense here. What is the
analogue in this case to pursuing a more objective understanding of the same
phenomena by abandoning the initial subjective viewpoint toward them in favor of
another that is more objective but concerns the same thing? Certainly it appears
unlikely that we will get closer to the real nature of human experience by
leaving behind the particularity of our human point of view and striving for a
description in terms accessible to beings that could not imagine what it was
like to be us. If the subjective character of experience is fully comprehensible
only from one point of view, then any shift to greater objectivity that is, less
attachment to a specific viewpoint does not take us nearer to the real nature of
the phenomenon: it takes us farther away from it. {% cite nagel1974like %}
So What? (Or: Why is This Important?) So What? (Or: Why is This Important?)
---------------------- ----------------------
This realisation means that objectifying people's subjective experiences is not possible, we will never be able to decipher someone's subjective experience of something. This does not mean we should not try to _understand_ people, rather, it means we should always consider that our understanding of someone's subjective experience will never be objective, it will always be merely our perspective of it. When it comes to people's personal experiences, we can't be sure that we are right, the way we are confident we are right after measuring a distance using our agreed-upon metric ruler; when it comes to subjective experiences it's always only a crude approximation. "In the end one experiences only oneself." {% cite nietzsche2008thus %} This realisation means that objectifying people's subjective experiences is not
possible, we will never be able to decipher someone's subjective experience of
something. This does not mean we should not try to _understand_ people, rather,
it means we should always consider that our understanding of someone's
subjective experience will never be objective, it will always be merely our
perspective of it. When it comes to people's personal experiences, we can't be
sure that we are right, the way we are confident we are right after measuring a
distance using our agreed-upon metric ruler; when it comes to subjective
experiences it's always only a crude approximation. "In the end one experiences
only oneself." {% cite nietzsche2008thus %}
This video was sent to me by a friend today, and it is great timing, because it is very relevant: This video was sent to me by a friend today, and it is great timing, because it
is very relevant:
<iframe class="centered" width="560" height="315" src="https://www.youtube-nocookie.com/embed/oRG2jlQWCsY" title="Good Will Hunting | 'Your Move Chief' (HD) - Matt Damon, Robin Williams | MIRAMAX" frameborder="0" allow="picture-in-picture" allowfullscreen></iframe> <iframe class="centered" width="560" height="315" src="https://www.youtube-nocookie.com/embed/oRG2jlQWCsY" title="Good Will Hunting | 'Your Move Chief' (HD) - Matt Damon, Robin Williams | MIRAMAX" frameborder="0" allow="picture-in-picture" allowfullscreen></iframe>
<!--https://postcognitivism.wordpress.com/2021/04/06/the-great-escape-can-we-transcend-our-own-conceptual-frameworks/
https://gatelessgateblog.wordpress.com/
https://www.sciencedirect.com/science/article/pii/S0388000121000802
Distinctions and Common Ground in Collective Epistemology-->
References References
---------- ----------

View File

@ -8,17 +8,27 @@ categories: programming
author: Mahdi author: Mahdi
--- ---
Today I and a friend went down a rabbit hole about Rust and how it manages the heap when we use `Box`, or `String`, or `Vec`, and while we were at it, I found out there is such a thing as `Box<str>`, which might look a bit _strange_ to an untrained eye, since most of the time the `str` primitive type is passed around as `&str`. Today I and a friend went down a rabbit hole about Rust and how it manages the
heap when we use `Box`, or `String`, or `Vec`, and while we were at it, I found
out there is such a thing as `Box<str>`, which might look a bit _strange_ to an
untrained eye, since most of the time the `str` primitive type is passed around
as `&str`.
----- -----
TL;DR: TL;DR:
`Box<str>` is a primitive `str` allocated on the heap, whereas `String` is actually a `Vec<u8>`, also allocated on the heap, which allows for efficient removals and appends. `Box<str>` (16 bytes) uses less memory than `String` (24 bytes). `Box<str>` is a primitive `str` allocated on the heap, whereas `String` is
actually a `Vec<u8>`, also allocated on the heap, which allows for efficient
removals and appends. `Box<str>` (16 bytes) uses less memory than `String` (24
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). 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).
```bash ```bash
git clone https://git.mahdi.blog/mahdi/rust-memory-playground git clone https://git.mahdi.blog/mahdi/rust-memory-playground
@ -27,7 +37,9 @@ cd rust-memory-playground
# The Stack # The Stack
Most of the primitive data types used throughout a program, and the information about the program itself are usually allocated on the stack. Consider this simple program: Most of the primitive data types used throughout a program, and the information
about the program itself are usually allocated on the stack. Consider this
simple program:
```rust ```rust
fn add_ten(a: u8) -> u8 { fn add_ten(a: u8) -> u8 {
@ -41,7 +53,8 @@ fn main() {
} }
``` ```
Let's examine the stack when we are running `a + b` by setting a breakpoint on that line: Let's examine the stack when we are running `a + b` by setting a breakpoint on
that line:
``` ```
$ cargo build && rust-lldb target/debug/stack-program $ cargo build && rust-lldb target/debug/stack-program
@ -67,9 +80,24 @@ Process 65188 stopped
0x000000016fdfed7f: (unsigned char) b = 0x0A 0x000000016fdfed7f: (unsigned char) b = 0x0A
``` ```
Our program allocates two variables on the stack directly here. Notice that they are allocated right next to each other, their address only one bit apart. Most primitive types are allocated on the stack, and are copied when being passed around because they are small enough, so that copying them around is more reasonable than allocating them in the heap and passing around a pointer to them. In this case, `u8` can be allocated in a single byte, it would not make sense for us to allocate a pointer (which can vary in size, but are usually larger than 8 bytes). Every time you call a function, a copy of the values passed to it, along with the values defined in the function itself constitute the stack of that function. Our program allocates two variables on the stack directly here. Notice that they
are allocated right next to each other, their address only one bit apart. Most
primitive types are allocated on the stack, and are copied when being passed
around because they are small enough, so that copying them around is more
reasonable than allocating them in the heap and passing around a pointer to
them. In this case, `u8` can be allocated in a single byte, it would not make
sense for us to allocate a pointer (which can vary in size, but are usually
larger than 8 bytes). Every time you call a function, a copy of the values
passed to it, along with the values defined in the function itself constitute
the stack of that function.
The stack of a whole program includes more information though, such as the _backtrace_, which allows the program to know how to navigate: once I am done with this function, where should I return to? that information is available in the stack as well. Note the first couple of lines here, indicating that we are currently in `stack_program::add_then`, and we came here from `stack_program::main`, and so once we are finished with `add_then`, we will go back to `main`: The stack of a whole program includes more information though, such as the
_backtrace_, which allows the program to know how to navigate: once I am done
with this function, where should I return to? that information is available in
the stack as well. Note the first couple of lines here, indicating that we are
currently in `stack_program::add_then`, and we came here from
`stack_program::main`, and so once we are finished with `add_then`, we will go
back to `main`:
``` ```
(lldb) thread backtrace (lldb) thread backtrace
@ -95,11 +123,19 @@ The stack of a whole program includes more information though, such as the _back
# Box, String and Vec: Pointers to Heap # Box, String and Vec: Pointers to Heap
There are times when we are working with data types large enough that we would really like to avoid copying them when we are passing them around. Let's say you have just copied a file that is 1,000,000 bytes (1Mb) in size. In this case it is much more memory and compute efficient to have a pointer to this value (8 bytes) rather than copying all the 1,000,000 bytes. There are times when we are working with data types large enough that we would
really like to avoid copying them when we are passing them around. Let's say you
have just copied a file that is 1,000,000 bytes (1Mb) in size. In this case it
is much more memory and compute efficient to have a pointer to this value (8
bytes) rather than copying all the 1,000,000 bytes.
This is where types such as `Box`, `String` and `Vec` come into play: these types allow you to allocate something on heap, which is a chunk of memory separate from the stack that you can allocate on, and later reference those values using a pointer available on the stack. This is where types such as `Box`, `String` and `Vec` come into play: these
types allow you to allocate something on heap, which is a chunk of memory
separate from the stack that you can allocate on, and later reference those
values using a pointer available on the stack.
Let's start with `Box`, the most generic one, which allows you to allocate some data on the heap, consider this example: Let's start with `Box`, the most generic one, which allows you to allocate some
data on the heap, consider this example:
```rust ```rust
fn main() { fn main() {
@ -136,11 +172,22 @@ Process 67451 stopped
0x600000008010: 0x05 0x600000008010: 0x05
``` ```
Note that here, instead of `a` having the value `5`, has the value `0x0000600000008010`, which is a pointer to a location in memory! `lldb` is recognises that this is a pointer (note the `*` sign beside the variable type) and shows us what the memory location contains, but we can also directly read that memory location, and of course we find `5` there. The address of the heap-allocated `5` is far from the stack-allocated `10`, since stack and heap are separate parts of memory. Note that here, instead of `a` having the value `5`, has the value
`0x0000600000008010`, which is a pointer to a location in memory! `lldb` is
recognises that this is a pointer (note the `*` sign beside the variable type)
and shows us what the memory location contains, but we can also directly read
that memory location, and of course we find `5` there. The address of the
heap-allocated `5` is far from the stack-allocated `10`, since stack and heap
are separate parts of memory.
Using `Box` for an unsigned 8-bit value does not really make sense, the value itself is smaller than the pointer created by `Box`, however allocating on heap is useful when we have data that we need be able to pass around the program without copying it. Using `Box` for an unsigned 8-bit value does not really make sense, the value
itself is smaller than the pointer created by `Box`, however allocating on heap
is useful when we have data that we need be able to pass around the program
without copying it.
Turns out, `String` and `Vec` cover two of the most common cases where we may want to allocate something on heap! Let's look at what goes on behind allocating a variable of type `String`: Turns out, `String` and `Vec` cover two of the most common cases where we may
want to allocate something on heap! Let's look at what goes on behind allocating
a variable of type `String`:
```rust ```rust
fn main() { fn main() {
@ -176,7 +223,11 @@ Process 68317 stopped
} }
``` ```
This is a formatted output from `lldb`, and here you can see that the `String` type is basically a `Vec<unsigned char, alloc::Global>` (note that `unsigned char` is represented using `u8` in Rust, so in Rust terminology the type is `Vec<u8>`), let's now look at the same command but this time raw and unformatted (`-R`): This is a formatted output from `lldb`, and here you can see that the `String`
type is basically a `Vec<unsigned char, alloc::Global>` (note that `unsigned
char` is represented using `u8` in Rust, so in Rust terminology the type is
`Vec<u8>`), let's now look at the same command but this time raw and unformatted
(`-R`):
``` ```
(lldb) frame var -L -T -R (lldb) frame var -L -T -R
@ -195,7 +246,21 @@ This is a formatted output from `lldb`, and here you can see that the `String` t
} }
``` ```
Ah! I see the `ptr` field of `RawVec` with a value of `0x0000600000004010`, that is the memory address of the beginning of our string (namely the `h` of our `hello`)! There is also `cap` and `len`, which respectively stand for capacity and length, with the value 6, indicating that our string is of capacity and length 6; the difference between the two being that [you can have a `Vec` with a capacity of 10 while it has zero items](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#capacity-and-reallocation), this would allow you to append 10 items to the `Vec` without having a new allocation for each append, making the process more efficient, and also a [Vec is not automatically shrunk down](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#guarantees) in size when items are removed from it to avoid unnecessary deallocations, hence the length might be smaller than the capacity. So in a nutshell, our String is basically something like this (inspired by [std::vec::Vec](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#guarantees)): Ah! I see the `ptr` field of `RawVec` with a value of `0x0000600000004010`, that
is the memory address of the beginning of our string (namely the `h` of our
`hello`)! There is also `cap` and `len`, which respectively stand for capacity
and length, with the value 6, indicating that our string is of capacity and
length 6; the difference between the two being that [you can have a `Vec` with a
capacity of 10 while it has zero
items](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#capacity-and-reallocation),
this would allow you to append 10 items to the `Vec` without having a new
allocation for each append, making the process more efficient, and also a [Vec
is not automatically shrunk
down](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#guarantees) in
size when items are removed from it to avoid unnecessary deallocations, hence
the length might be smaller than the capacity. So in a nutshell, our String is
basically something like this (inspired by
[std::vec::Vec](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#guarantees)):
``` ```
Stack: Stack:
@ -211,9 +276,11 @@ Heap: v
----------------------------- -----------------------------
``` ```
Okay, so far so good. We have `String`, which uses a `Vec` under the hood, which is represented by a pointer, capacity and length triplet. Okay, so far so good. We have `String`, which uses a `Vec` under the hood, which
is represented by a pointer, capacity and length triplet.
If `String` is already heap-allocated, why would anyone want `Box<str>`!? Let's look at how `Box<str>` would be represented in memory: If `String` is already heap-allocated, why would anyone want `Box<str>`!? Let's
look at how `Box<str>` would be represented in memory:
```rust ```rust
fn main() { fn main() {
@ -232,7 +299,11 @@ And `lldb` tells us:
} }
``` ```
Okay, so a `Box<str>` is much simpler than a `String`: there is no `Vec`, and no `capacity`, and the underlying data is a primitive `str` that does not allow efficient appending or removing. It is a smaller representation as well, due to the missing `capacity` field, comparing their memory size on stack using [std::mem::size_of_val](https://doc.rust-lang.org/std/mem/fn.size_of_val.html): Okay, so a `Box<str>` is much simpler than a `String`: there is no `Vec`, and no
`capacity`, and the underlying data is a primitive `str` that does not allow
efficient appending or removing. It is a smaller representation as well, due to
the missing `capacity` field, comparing their memory size on stack using
[std::mem::size_of_val](https://doc.rust-lang.org/std/mem/fn.size_of_val.html):
```rust ```rust
let boxed_str: Box<str> = "hello".into(); let boxed_str: Box<str> = "hello".into();
@ -249,7 +320,10 @@ size of boxed_str on stack: 16
size of string on stack: 24 size of string on stack: 24
``` ```
Note that their size on heap is the same, because they are both storing the bytes for `hello` on the heap (the measurements below show all of the heap allocations of the program, and not only the string. What matters here is that these two programs have exact same heap size in total): Note that their size on heap is the same, because they are both storing the
bytes for `hello` on the heap (the measurements below show all of the heap
allocations of the program, and not only the string. What matters here is that
these two programs have exact same heap size in total):
``` ```
$ cargo run --bin string-dhat $ cargo run --bin string-dhat
@ -275,8 +349,15 @@ There is also `Box<[T]>` which is the fixed size counterpart to `Vec<T>`.
# Should I use `Box<str>` or `String`? # Should I use `Box<str>` or `String`?
The only use case for `Box<str>` over `String` that I can think of, is optimising for memory usage when the string is fixed and you do not intend to append or remove from it. I looked for examples of `Box<str>` being used, and I found a few examples: The only use case for `Box<str>` over `String` that I can think of, is
optimising for memory usage when the string is fixed and you do not intend to
append or remove from it. I looked for examples of `Box<str>` being used, and I
found a few examples:
- Hyper uses it in a part to reduce memory usage, since the string they have is read-only: [hyper#2727](https://github.com/hyperium/hyper/pull/2727) - Hyper uses it in a part to reduce memory usage, since the string they have is
- Rust-analyzer uses it to store some strings in their snippets data structre: [rust-lang/rust-analyzer/crates/ide-completion/src/snippet.rs](https://github.com/rust-lang/rust-analyzer/blob/5c88d9344c5b32988bfbfc090f50aba5de1db062/crates/ide-completion/src/snippet.rs#L123) read-only: [hyper#2727](https://github.com/hyperium/hyper/pull/2727)
- It is also used in some parts in the compiler itself, probably with the same aim of optimising memory usage: [rust-lang/rust/src/libsyntax/symbol.rs](https://github.com/rust-lang/rust/blob/7846610470392abc3ab1470853bbe7b408fe4254/src/libsyntax/symbol.rs#L82-L85) - Rust-analyzer uses it to store some strings in their snippets data structre:
[rust-lang/rust-analyzer/crates/ide-completion/src/snippet.rs](https://github.com/rust-lang/rust-analyzer/blob/5c88d9344c5b32988bfbfc090f50aba5de1db062/crates/ide-completion/src/snippet.rs#L123)
- It is also used in some parts in the compiler itself, probably with the same
aim of optimising memory usage:
[rust-lang/rust/src/libsyntax/symbol.rs](https://github.com/rust-lang/rust/blob/7846610470392abc3ab1470853bbe7b408fe4254/src/libsyntax/symbol.rs#L82-L85)

View File

@ -8,200 +8,254 @@ categories: programming
author: Mahdi author: Mahdi
--- ---
Videogames are a pervasive part of lives of children and adults alike, with 73% of Americans older than 2 years engaging with them {% cite npd2019videogames %}. Playing videogames can be seen as an activity that is done through our fingertips and with our visual apparatus focused on a screen, without involvement of the rest of our body, and it is usually considered as such from a cognitivist point of view {% cite campbell2012video %} {% cite gee2003video %} {% cite klimmt2006effectance %} however this raises the question of whether videogames can alternatively be thought of as an embodied experience, and if so, how can we formulate them as such, and what factors are at play? Videogames are a pervasive part of lives of children and adults alike, with 73%
of Americans older than 2 years engaging with them {% cite npd2019videogames %}.
Playing videogames can be seen as an activity that is done through our
fingertips and with our visual apparatus focused on a screen, without
involvement of the rest of our body, and it is usually considered as such from a
cognitivist point of view {% cite campbell2012video %} {% cite gee2003video %}
{% cite klimmt2006effectance %} however this raises the question of whether
videogames can alternatively be thought of as an embodied experience, and if so,
how can we formulate them as such, and what factors are at play?
Virtual reality videogames are more commonly studied from an embodied perspective, since they lend themselves to the framework more easily by being more engaging to the whole body and by the fact of their immersive experience, however the same question can be asked for non-virtual reality games, with keyboard and mouse or the controller, and the screen. Virtual reality videogames are more commonly studied from an embodied
perspective, since they lend themselves to the framework more easily by being
more engaging to the whole body and by the fact of their immersive experience,
however the same question can be asked for non-virtual reality games, with
keyboard and mouse or the controller, and the screen.
We will first talk about what do we mean by embodiment when we say playing videogames is an embodied experience, and this is a very important part of our discourse. We then continue to talk about what motivates us to think that videogames fit such notions of embodied experience, and from there we further ask questions about the factors at play, including, but not limited to, camera control and perspective and its relationship with peripersonal space and the social aspect of videogames. We will first talk about what do we mean by embodiment when we say playing
videogames is an embodied experience, and this is a very important part of our
discourse. We then continue to talk about what motivates us to think that
videogames fit such notions of embodied experience, and from there we further
ask questions about the factors at play, including, but not limited to, camera
control and perspective and its relationship with peripersonal space and the
social aspect of videogames.
# Did Somebody Say Embodiment? # Did Somebody Say Embodiment?
The question of whether we can think of playing videogames as an embodied experience is quite puzzling, and it requires unraveling questions that are unanswered about what embodiment means, how do we distinguish it from else, and how does something like playing videogames fit into this picture. There are different accounts of embodiment, and they stand in contrast to cognitive psychogolical accounts. Cognitive psychology accounts study mental processes, which are usually associated with the brain, and where the body is thought of as an input and output interface with the world that is controlled by the brain. {% cite neisser2014cognitive %} {% cite anderson1980cognitive %}. There are numerous accounts of embodied experience, we will review some of them and lay out our understanding of embodiment, one which allows us to discuss videogames in its light. The question of whether we can think of playing videogames as an embodied
experience is quite puzzling, and it requires unraveling questions that are
unanswered about what embodiment means, how do we distinguish it from else, and
how does something like playing videogames fit into this picture. There are
different accounts of embodiment, and they stand in contrast to cognitive
psychogolical accounts. Cognitive psychology accounts study mental processes,
which are usually associated with the brain, and where the body is thought of as
an input and output interface with the world that is controlled by the brain. {%
cite neisser2014cognitive %} {% cite anderson1980cognitive %}. There are
numerous accounts of embodied experience, we will review some of them and lay
out our understanding of embodiment, one which allows us to discuss videogames
in its light.
{% cite thelen2000grounded %} gives an account that focuses mostly on the fact {% cite thelen2000grounded %} gives an account that focuses mostly on the fact
that our experiences arise because we have a particular kind of body that our experiences arise because we have a particular kind of body with
with particular capacities and apparatus that lead to us experiencing particular capacities and apparatus that lead to us experiencing the world as we
the world as we do. This might be one of the most high-level accounts do. This might be one of the most high-level accounts that shares a considerable
that shares a considerable amount with most other embodiment accounts: amount with most other embodiment accounts:
> "\[T\]o say that cognition is embodied means that it arises from > "\[T\]o say that cognition is embodied means that it arises from > bodily
> bodily interactions with the world, from this point of view, cognition interactions with the world, from this point of view, cognition > depends on the
> depends on the kinds of experiences that come from having a body with kinds of experiences that come from having a body with > particular perceptual
> particular perceptual and motor capacities that are inseparably linked and motor capacities that are inseparably linked > and that together form the
> and that together form the matrix within which memory, emotion, matrix within which memory, emotion, > language, and all other aspects of live
> language, and all other aspects of live are meshed.\" are meshed.\"
With this account, it is necessary to consider the body as a constitutive part of cognition, not merely an input/output system controlled by the brain. Questions about cognition only make sense with consideration of the way we interact with the world with our bodies. With this account, it is necessary to consider the body as a constitutive part
of cognition, not merely an input/output system controlled by the brain.
Questions about cognition only make sense with consideration of the way we
interact with the world with our bodies.
Merleau-Ponty's phenomenological account unifies the body and the mind and instead of talking about them separately, he proposes talking about an intentional, lived body, that is continuously adapting to the world through formation of habits: Merleau-Ponty's phenomenological account unifies the body and the mind and
instead of talking about them separately, he proposes talking about an
intentional, lived body, that is continuously adapting to the world through
formation of habits:
> The body's orientation toward the world is essentially temporal, > The body's orientation toward the world is essentially temporal, > involving a
> involving a dialectic between the present body (characterized, after dialectic between the present body (characterized, after > Husserl, as an "I
> Husserl, as an "I can") and the habit body, the sedimentations of past can") and the habit body, the sedimentations of past > activities that take on a
> activities that take on a general, anonymous, and autonomous general, anonymous, and autonomous > character. \[..\] it has affective
> character. \[..\] it has affective experiences that are not merely experiences that are not merely > representations; and its kinesthetic sense of
> representations; and its kinesthetic sense of its own movements is its own movements is > given directly. > > This kinesthetic awareness is made
> given directly. possible by a pre-conscious system > of bodily movements and spatial
> equivalences that Merleau-Ponty terms > the "body schema". In contrast with the
> This kinesthetic awareness is made possible by a pre-conscious system "positional spatiality" of > things, the body has a "situational spatiality"
> of bodily movements and spatial equivalences that Merleau-Ponty terms that is oriented > toward actual or possible tasks. The body's existence as >
> the "body schema". In contrast with the "positional spatiality" of "being-toward-the-world", as a projection toward lived goals, is > therefore
> things, the body has a "situational spatiality" that is oriented expressed through its spatiality, which forms the background > against which
> toward actual or possible tasks. The body's existence as objective space is constituted. \[..\] > > The body's relationship with space is
> "being-toward-the-world", as a projection toward lived goals, is therefore intentional, although > as an "I can" rather than an "I think"; bodily
> therefore expressed through its spatiality, which forms the background space is a > multi-layered manner of relating to things, so that the body is not
> against which objective space is constituted. \[..\]
>
> The body's relationship with space is therefore intentional, although
> as an "I can" rather than an "I think"; bodily space is a
> multi-layered manner of relating to things, so that the body is not
> "in" space but lives or inhabits it. {% cite sep-merleau-ponty %} > "in" space but lives or inhabits it. {% cite sep-merleau-ponty %}
Merleau-Ponty's account requires substantial consideration when we talk Merleau-Ponty's account requires substantial consideration when we talk about
about embodiment in video-games, since his terminology and framework embodiment in video-games, since his terminology and framework make it easier to
make it easier to express what we are trying to affirm in this report. express what we are trying to affirm in this report. When we talk about
When we talk about embodiment, we are using Merleau-Ponty's framework, embodiment, we are using Merleau-Ponty's framework, along with anecdotes and
along with anecdotes and inspirations from other frameworks which we inspirations from other frameworks which we will mention.
will mention.
Let's consider one of the most important pillars of this account: our Let's consider one of the most important pillars of this account: our existence
existence in the world is intentional, and our body, with all of its in the world is intentional, and our body, with all of its habits and its
habits and its capabilities, shapes our intentional stance towards the capabilities, shapes our intentional stance towards the world, since it is our
world, since it is our body that limits our "I can\" from an endless body that limits our "I can\" from an endless list of possibilities down to the
list of possibilities down to the way we live right now. Cognition need way we live right now. Cognition need not be thought of as perceiving, thinking
not be thought of as perceiving, thinking (or processing), and then (or processing), and then acting, but rather, we live in direct interaction with
acting, but rather, we live in direct interaction with the world, and the world, and perception and thinking and acting are no longer separated, no
perception and thinking and acting are no longer separated, no longer longer representational, but through our long-formed habits, our spatial
representational, but through our long-formed habits, our spatial presence and a body schema that shapes our capabilities towards the world around
presence and a body schema that shapes our capabilities towards the us, the world appears to us directly with meanings and values.
world around us, the world appears to us directly with meanings and
values.
The body schema and our ability to morph this body schema through our The body schema and our ability to morph this body schema through our
interactions with tools and in different contexts is vital to our interactions with tools and in different contexts is vital to our discourse.
discourse. Merleau-Ponty's account allows for our body schema, which is Merleau-Ponty's account allows for our body schema, which is what shapes our
what shapes our intentional stance towards the world, to be changed as intentional stance towards the world, to be changed as we incorporate tools and
we incorporate tools and certain environments into our lives. His famous certain environments into our lives. His famous example of a blind man's stick
example of a blind man's stick is worth mentioning: is worth mentioning:
> "When the cane becomes a familiar instrument, the world of tactile > "When the cane becomes a familiar instrument, the world of tactile > objects
> objects expands, it no longer begins at the skin of the hand, but at expands, it no longer begins at the skin of the hand, but at > the tip of the
> the tip of the cane. cane. > > \[..\] the cane is no longer an object that the blind man would >
> perceive, it has become an instrument with which he perceives. It is > an
> \[..\] the cane is no longer an object that the blind man would appendage of the body, or an extension of the bodily synthesis.\" > {% cite
> perceive, it has become an instrument with which he perceives. It is merleau1962phenomenology %}
> an appendage of the body, or an extension of the bodily synthesis.\"
> {% cite merleau1962phenomenology %}
Andy Clark gives a similar account when talking about our embodied Andy Clark gives a similar account when talking about our embodied experience of
experience of using virtual reality headsets: using virtual reality headsets:
> The infant, like the VR-exploring adult, must learn how to use > The infant, like the VR-exploring adult, must learn how to use > internally
> internally unresponsive hands, arms and legs to obtain its goals. unresponsive hands, arms and legs to obtain its goals. > > \[..\] > > With time
> and practice, enough bodily fluency is achieved to make the > wider world itself
> \[..\] directly available as a kind of unmediated arena > for embodied action. At this
> point, the extrabodily world becomes > poised to present itself to the user not
> With time and practice, enough bodily fluency is achieved to make the just as a problem space > (though it is clearly that) but as a problem-solving
> wider world itself directly available as a kind of unmediated arena resource. For the > world, specially when encountered via inhabited interaction,
> for embodied action. At this point, the extrabodily world becomes is a > place in which we can act fluently in ways that simplify or transform >
> poised to present itself to the user not just as a problem space the problems that we want to solve. At such moments, the body has > become
> (though it is clearly that) but as a problem-solving resource. For the "transparent equipment\": equipment that is not the focus of > attention in use.
> world, specially when encountered via inhabited interaction, is a Instead the user "sees through\" the equipment to > the task in hand. When you
> place in which we can act fluently in ways that simplify or transform sign your name, the pen is not normally > your focus. The pen in use is no more
> the problems that we want to solve. At such moments, the body has the focus of your attention than > is the hand that grips it. Both are
> become "transparent equipment\": equipment that is not the focus of transparent equipment. > {% cite clark2008supersizing %}
> attention in use. Instead the user "sees through\" the equipment to
> the task in hand. When you sign your name, the pen is not normally
> your focus. The pen in use is no more the focus of your attention than
> is the hand that grips it. Both are transparent equipment.
> {% cite clark2008supersizing %}
To summarise what we mean by embodiment as we talk about it here: To summarise what we mean by embodiment as we talk about it here:
1. Cognition depends on our body as a whole, and our experiences that arise are specifically tailored by our body and its particular features. 1. Cognition depends on our body as a whole, and our experiences that arise are
specifically tailored by our body and its particular features.
2. Our body has an intentional stance towards the world, and this intentional stance is dependent on our habits, and is limited by the capacities of our body. 2. Our body has an intentional stance towards the world, and this intentional
stance is dependent on our habits, and is limited by the capacities of our
body.
3. The "body schema" is what allows for our pre-conscious kinaesthetic awareness of our body in a "situational" sense, oriented towards possible tasks. 3. The "body schema" is what allows for our pre-conscious kinaesthetic awareness
of our body in a "situational" sense, oriented towards possible tasks.
# Videogaming as an Embodied Activity # Videogaming as an Embodied Activity
This is not a simple question, and our discussion here is not to be taken as granted, of course. There are many complexities involved with attributing something as complex as "embodiment" to an activity as complex as playing videogames. This is a puzzling notion, but nevertheless, it is worth considering and thought. This is not a simple question, and our discussion here is not to be taken as
granted, of course. There are many complexities involved with attributing
something as complex as "embodiment" to an activity as complex as playing
videogames. This is a puzzling notion, but nevertheless, it is worth considering
and thought.
Given the framework described, we can now formulate videogaming as an embodied activity. A more trivial example of what we are trying to formulate is driving cars, which is a common example used when talking about embodiment in cognitive science. When we drive a car as a proficient driver, we manoeuvre by considering what we want to do, and acting towards that direct goal without focusing on how we do this by using the gears, the clutch, the brake, pedal and the wheel, etc. We might be taking 3 to 4 actions at the same time, e.g. when reverse turning: brake in, clutch in, wheel to one side, change gears to reverse, look in the mirrors, however we are mostly thinking about where we want to go, not all the details and specifics of our interactions with the car's interface. Similar to the example of the blind man and the stick, the apparatus has become transparent and now our body schema includes the car. We decide we want to reverse and turn to one side, and given our new intentional stance towards the world that is limited and extended using the car, we consider our self to be capable of doing so. The way we question and talk about the world changes, too, we ask "do I fit here?", wondering if we can pass through a narrow passage with the car, we are now embodying a new intentional stance towards the world, and this new body schema is what gets attribution for our action. Given the framework described, we can now formulate videogaming as an embodied
activity. A more trivial example of what we are trying to formulate is driving
cars, which is a common example used when talking about embodiment in cognitive
science. When we drive a car as a proficient driver, we manoeuvre by considering
what we want to do, and acting towards that direct goal without focusing on how
we do this by using the gears, the clutch, the brake, pedal and the wheel, etc.
We might be taking 3 to 4 actions at the same time, e.g. when reverse turning:
brake in, clutch in, wheel to one side, change gears to reverse, look in the
mirrors, however we are mostly thinking about where we want to go, not all the
details and specifics of our interactions with the car's interface. Similar to
the example of the blind man and the stick, the apparatus has become transparent
and now our body schema includes the car. We decide we want to reverse and turn
to one side, and given our new intentional stance towards the world that is
limited and extended using the car, we consider our self to be capable of doing
so. The way we question and talk about the world changes, too, we ask "do I fit
here?", wondering if we can pass through a narrow passage with the car, we are
now embodying a new intentional stance towards the world, and this new body
schema is what gets attribution for our action.
Videogames are similar, with the difference that instead of sitting inside a car that moves spatially in the world, our human body sits in one place, but we still go places in the game-world. A proficient gamer is not concerned with the buttons they press or how they move the mouse, for example, they are directly concerned with what they do in the game-world. A new intentional stance arises towards the game-world, that is defined by the avatar that we embody in the videogame. Videogames are similar, with the difference that instead of sitting inside a car
that moves spatially in the world, our human body sits in one place, but we
still go places in the game-world. A proficient gamer is not concerned with the
buttons they press or how they move the mouse, for example, they are directly
concerned with what they do in the game-world. A new intentional stance arises
towards the game-world, that is defined by the avatar that we embody in the
videogame.
Our body schema is now extended to include the avatar in the game-world, Our body schema is now extended to include the avatar in the game-world, and
and this new body-schema limits what our human body does (just like in this new body-schema limits what our human body does (just like in driving a car
driving a car where some of our body is not actively used towards our where some of our body is not actively used towards our goals), *we* now want to
goals), *we* now want to *climb* things with our new intentional body, *climb* things with our new intentional body, and *shoot* the monsters and we
and *shoot* the monsters and we feel real feelings of anxiety and stress feel real feelings of anxiety and stress (and we may even sweat) when we are
(and we may even sweat) when we are playing a stealth game and we are in playing a stealth game and we are in hiding. *We* are afraid of being found out,
hiding. *We* are afraid of being found out, and when we are getting hit and when we are getting hit by enemies or falling from a height, our human body
by enemies or falling from a height, our human body tenses, and we tenses, and we sometimes even get the feeling of falling dropping in our stomach
sometimes even get the feeling of falling dropping in our stomach (this (this can depend a lot on the camera of the video-game, which we will talk
can depend a lot on the camera of the video-game, which we will talk about). When playing a car or motorcycle racing game, our human body inevitably
about). When playing a car or motorcycle racing game, our human body leans in as we are turning in the game-world. video-games have structured
inevitably leans in as we are turning in the game-world. video-games worlds, with certain rules that make them predictable enough to an experienced
have structured worlds, with certain rules that make them predictable player, much like the real world, this can lead to us believing that we have
enough to an experienced player, much like the real world, this can lead control over the world and we can take guided actions towards certain ends. A
to us believing that we have control over the world and we can take high correspondence between our interactions with the interface that connects us
guided actions towards certain ends. A high correspondence between our to our extended body in the game-world (e.g. the game controller, or the
interactions with the interface that connects us to our extended body in keyboard and the mouse) and visual and proprioceptive feedback might be the key
the game-world (e.g. the game controller, or the keyboard and the mouse) to creating a strong sense of ownership of actions. {% cite martin1995bodily %}
and visual and proprioceptive feedback might be the key to creating a {% cite tsakiris2005experimenting %}
strong sense of ownership of actions.
{% cite martin1995bodily %} {% cite tsakiris2005experimenting %}
Besides the notion of embodiment that we have been discussing so far, Besides the notion of embodiment that we have been discussing so far, there are
there are other kinds of embodiment. Social embodiment seems to be a other kinds of embodiment. Social embodiment seems to be a slightly more
slightly more ambiguous and challenging notion that must be considered ambiguous and challenging notion that must be considered with care, but consider
with care, but consider {% cite barsalou2003social %}'s account of social {% cite barsalou2003social %}'s account of social embodiment effects:
embodiment effects:
> "First, perceived social stimuli do not just produce cognitive states, > "First, perceived social stimuli do not just produce cognitive states, > they
> they produce bodily states as well. Second, perceiving bodily states produce bodily states as well. Second, perceiving bodily states > in others
> in others produces bodily mimicry in the self. Third, bodily states in produces bodily mimicry in the self. Third, bodily states in > the self produce
> the self produce affective states. Fourth, the compatibility of bodily affective states. Fourth, the compatibility of bodily > states and cognitive
> states and cognitive states modulates performance effectiveness\" states modulates performance effectiveness\"
Real-time online video-games can exhibit similar effects, I may walk Real-time online video-games can exhibit similar effects, I may walk with my
with my avatar towards a friend's avatar in the gameworld and wave my avatar towards a friend's avatar in the gameworld and wave my hand, leading to
hand, leading to them waving their hand, and as I start walking away, them waving their hand, and as I start walking away, they might follow me and we
they might follow me and we may start an activity together without need may start an activity together without need for verbal or text communication,
for verbal or text communication, but rather only by the effect of our but rather only by the effect of our avatar's state of body. We have learned the
avatar's state of body. We have learned the affordances of our new affordances of our new environment and our new extended body, and that of our
environment and our new extended body, and that of our fellow players. fellow players.
# Camera, Avatar and Controller Relations # Camera, Avatar and Controller Relations
The camera-avatar relationship and the input interface are important The camera-avatar relationship and the input interface are important factors to
factors to be considered when asking questions about embodiment of the be considered when asking questions about embodiment of the experience, so it is
experience, so it is necessary to consider these factors more necessary to consider these factors more explicitly.
explicitly.
<figure id="fig:first-person" class="row"> <figure id="fig:first-person" class="row">
<img alt="First-person view" src="/img/embodying-the-avatar/first-person.jpg" width="30%"/> <img alt="First-person view" src="/img/embodying-the-avatar/first-person.jpg"
width="30%"/>
<img alt="Third-person view" src="/img/embodying-the-avatar/third-person.jpg" width="30%"/> <img alt="Third-person view" src="/img/embodying-the-avatar/third-person.jpg"
width="30%"/>
<img alt="Isometric view" src="/img/embodying-the-avatar/diablo-view.jpg" width="30%"/> <img alt="Isometric view" src="/img/embodying-the-avatar/diablo-view.jpg"
width="30%"/>
<div class="break"></div> <div class="break"></div>
<figcaption>Different video-game camera modes. From left to right: First-person view, Third-person view and Isometric view.</figcaption> <figcaption>Different video-game camera modes. From left to right:
First-person view, Third-person view and Isometric view.</figcaption>
</figure> </figure>
<figure id="fig:dota" class="row"> <figure id="fig:dota" class="row">
<img alt="Camera's independence from the avatar in Dota2" src="/img/embodying-the-avatar/dota-1.png" width="30%" /> <img alt="Camera's independence from the avatar in Dota2"
src="/img/embodying-the-avatar/dota-1.png" width="30%" />
<img alt="Camera's independence from the avatar in Dota2" src="/img/embodying-the-avatar/dota-2.png" width="30%" /> <img alt="Camera's independence from the avatar in Dota2"
src="/img/embodying-the-avatar/dota-2.png" width="30%" />
<img alt="Camera's independence from the avatar in Dota2" src="/img/embodying-the-avatar/dota-3.png" width="30%" /> <img alt="Camera's independence from the avatar in Dota2"
src="/img/embodying-the-avatar/dota-3.png" width="30%" />
<div class="break"></div> <div class="break"></div>
@ -209,115 +263,156 @@ explicitly.
</figure> </figure>
Most research around this subject seems to focus on a First-Person view, Most research around this subject seems to focus on a First-Person view, where
where the player is looking out through the avatar's eyes or head, only the player is looking out through the avatar's eyes or head, only able to see
able to see the avatar's arms most of the time. This is the view adopted the avatar's arms most of the time. This is the view adopted almost exclusively
almost exclusively by all Virtual Reality games and many shooter games. by all Virtual Reality games and many shooter games. The controller used with
The controller used with this type of view is either a dual-axis this type of view is either a dual-axis controller or mouse and keyboard where
controller or mouse and keyboard where the character is moved with keys the character is moved with keys on the keyboard and the camera (or rather, the
on the keyboard and the camera (or rather, the head of the avatar!) is head of the avatar!) is moved using the mouse. This camera-avatar relation and
moved using the mouse. This camera-avatar relation and interface seems interface seems to fit the research literature most of the time since it is
to fit the research literature most of the time since it is considered considered directly by researchers most of the time. (Figure
directly by researchers most of the time. (Figure [1](#fig:first-person)). [1](#fig:first-person)).
Another common view in video-games is the third-person view where the Another common view in video-games is the third-person view where the camera
camera moves along with the avatar as the avatar moves. The camera moves along with the avatar as the avatar moves. The camera usually has the
usually has the ability to look around the avatar by rotating in its ability to look around the avatar by rotating in its place, but never able to
place, but never able to move away from the avatar across any axis. This move away from the avatar across any axis. This view is also similarly
view is also similarly accompanied by either dual-axis controller or accompanied by either dual-axis controller or keyboard and mouse where the
keyboard and mouse where the keyboard is used to move the avatar and the keyboard is used to move the avatar and the camera while the mouse is used to
camera while the mouse is used to rotate the camera. (Figure rotate the camera. (Figure [2](#fig:third-person))
[2](#fig:third-person))
Note that these two camera modes, albeit similar in some aspects, lend Note that these two camera modes, albeit similar in some aspects, lend us
us completely different body schemas and they change our intentional completely different body schemas and they change our intentional stance
stance strongly. This is best illustrated by the online multi-player strongly. This is best illustrated by the online multi-player video-game Dead by
video-game Dead by Daylight, where in a post-apocalyptic setting, a Daylight, where in a post-apocalyptic setting, a group of survivors are trying
group of survivors are trying to survive against a killer who is trying to survive against a killer who is trying to kill them, both of which are played
to kill them, both of which are played by actual players. What is by actual players. What is interesting is that the survivors and the killer use
interesting is that the survivors and the killer use different camera different camera views, and this is an important distinction between the two.
views, and this is an important distinction between the two. Survivors Survivors have third-person camera which allows them to rotate the camera and
have third-person camera which allows them to rotate the camera and look look behind them as they are running away or as they are trying to fix a broken
behind them as they are running away or as they are trying to fix a engine to get their car running so they can run away, this also means that the
broken engine to get their car running so they can run away, this also survivors avatars do not move their head as the camera is moved. On the
means that the survivors avatars do not move their head as the camera is contrary, the killer has first-person camera, this means that the killer can
moved. On the contrary, the killer has first-person camera, this means only look in the direction that they are running in, and this allows survivors
that the killer can only look in the direction that they are running in, to be able to know where the killer is currently looking at by looking at them.
and this allows survivors to be able to know where the killer is There is a significant difference between how these two roles are played in this
currently looking at by looking at them. There is a significant video-game mostly because of the camera movement, each player has a different
difference between how these two roles are played in this video-game body schema depending on which camera mode they have.
mostly because of the camera movement, each player has a different body
schema depending on which camera mode they have.
A less common, but still discussed in the literature type of A less common, but still discussed in the literature type of camera-avatar
camera-avatar relation is that of isometric cameras locked on the relation is that of isometric cameras locked on the character, found in the
character, found in the Diablo game series. This kind of camera-avatar Diablo game series. This kind of camera-avatar relation is very similar to a
relation is very similar to a third-person view, with the difference third-person view, with the difference that the camera is taking an isometric
that the camera is taking an isometric angle and is not controlled by angle and is not controlled by the user at all, merely following the avatar. The
the user at all, merely following the avatar. The controls used for this controls used for this kind of game are usually either a dual-axis controller,
kind of game are usually either a dual-axis controller, or in case of or in case of keyboard and mouse, the mouse, rather than the keyboard, is used
keyboard and mouse, the mouse, rather than the keyboard, is used to move to move the avatar by issuing commands to move to a certain place. This type of
the avatar by issuing commands to move to a certain place. This type of
movement control might seem unintuitive, however {% cite klevjer2012enter %} movement control might seem unintuitive, however {% cite klevjer2012enter %}
proposes that "because the clicking happens so fast, the experience proposes that "because the clicking happens so fast, the experience nevertheless
nevertheless approaches a sense of "pulling\" the avatar through a approaches a sense of "pulling\" the avatar through a tangible interface.\" and
tangible interface.\" and as such, the control interface can still as such, the control interface can still create a sense of high correspondence
create a sense of high correspondence between the player's actions and between the player's actions and movements of the avatar, reaching a real-time
movements of the avatar, reaching a real-time synchrony as mastery of synchrony as mastery of the control interface is reached.
the control interface is reached.
What is common between these three camera-avatar relations is the What is common between these three camera-avatar relations is the tight coupling
tight coupling of the camera with the avatar: the camera always follows of the camera with the avatar: the camera always follows the avatar as the
the avatar as the avatar moves around the world. In some cases, the avatar moves around the world. In some cases, the camera can be rotated or moved
camera can be rotated or moved around slightly to peek around a box around slightly to peek around a box while crouching for example, but almost
while crouching for example, but almost always the camera and the avatar always the camera and the avatar are in tight synchrony. {% cite
are in tight synchrony. {% cite klevjer2012enter %} considers all of these klevjer2012enter %} considers all of these camera modes to fall under the same
camera modes to fall under the same umbrella of camera indirectly umbrella of camera indirectly controlled by the movements of the avatar, as if
controlled by the movements of the avatar, as if the camera is pulled by the camera is pulled by the avatar around with an invisible string.
the avatar around with an invisible string.
This group of camera-avatar relations can be considered to be intuitive This group of camera-avatar relations can be considered to be intuitive and
and similar to how we as humans almost always have a synchrony between similar to how we as humans almost always have a synchrony between our vision
our vision and our body, with exception of cases like out-of-body and our body, with exception of cases like out-of-body experiences where a
experiences where a person sees the world and their own body from a person sees the world and their own body from a place outside of their physical
place outside of their physical body. {% cite blanke2004out %} However, there body. {% cite blanke2004out %} However, there are video-games where something
are video-games where something analogous to an out-of-body experience analogous to an out-of-body experience happens, and these are video-games where
happens, and these are video-games where the camera is not automatically the camera is not automatically attached to the avatar, but rather, the player
attached to the avatar, but rather, the player has manual control of the has manual control of the camera. This camera-avatar relation is most
camera. This camera-avatar relation is most characteristic of MOBA characteristic of MOBA (Multiplayer online battle arena) games such as Dota 2,
(Multiplayer online battle arena) games such as Dota 2, where the camera where the camera angle in relation to the avatar is very similar to that of
angle in relation to the avatar is very similar to that of Diablo, with Diablo, with the difference that the mouse is not only used to move the avatar,
the difference that the mouse is not only used to move the avatar, but but also allows panning of the camera across the world. (Figure [6](#fig:dota))
also allows panning of the camera across the world. (Figure
[6](#fig:dota))
In these videogames you are allowed to look at the world and your avatar from any place, and given our framework, the camera is now a novel extension to our body-schema. Most embodied activities exhibit the same synchrony of vision and body, like walking, swimming, driving a car, and in most cases of playing videogames too, however in this case, we have a new range of intentional acts available to us, through movement of the camera around the world. Our body-schema now includes a different apparatus to work with, it's as if our vision is no longer limited to our body, but rather there is a drone above us that we can see from. In these videogames you are allowed to look at the world and your avatar from
any place, and given our framework, the camera is now a novel extension to our
body-schema. Most embodied activities exhibit the same synchrony of vision and
body, like walking, swimming, driving a car, and in most cases of playing
videogames too, however in this case, we have a new range of intentional acts
available to us, through movement of the camera around the world. Our
body-schema now includes a different apparatus to work with, it's as if our
vision is no longer limited to our body, but rather there is a drone above us
that we can see from.
This opens up the possibility of a new kind of vision interaction with the world. When the stakes are high, as is the case with e-sports, players strive for the ultimate proficiency with their new body-schema, and the result is ways of using vision that are not usual and can sometimes be cryptic for us. Camera movement of professional players tends to be very fast, and sometimes outright chaotic to an untrained eye since they want to optimise being able to scout for information while still keeping an eye on their avatar, since the avatar is still the most important part of the game, and the free-form camera movement is mostly used similar to a binocular: to scout for information. This opens up the possibility of a new kind of vision interaction with the
world. When the stakes are high, as is the case with e-sports, players strive
for the ultimate proficiency with their new body-schema, and the result is ways
of using vision that are not usual and can sometimes be cryptic for us. Camera
movement of professional players tends to be very fast, and sometimes outright
chaotic to an untrained eye since they want to optimise being able to scout for
information while still keeping an eye on their avatar, since the avatar is
still the most important part of the game, and the free-form camera movement is
mostly used similar to a binocular: to scout for information.
# Further Questions # Further Questions
There is a question to be asked here about how much this technical camera-avatar independence leads to actual camera-avatar independence: do players actually end up with their camera away from their avatar much, or is the camera still in synchrony with the avatar for the majority of the time, but in a manner directly controlled by the player rather than automatically. There is a question to be asked here about how much this technical camera-avatar
independence leads to actual camera-avatar independence: do players actually end
up with their camera away from their avatar much, or is the camera still in
synchrony with the avatar for the majority of the time, but in a manner directly
controlled by the player rather than automatically.
Does the camera-avatar independence affect the embodied experience of playing this videogame, perhaps by making it more difficult to be proficient in the game, it is initially harder to extend your body-schema with this new form of vision, but what happens once you are proficient? Does the camera-avatar independence affect the embodied experience of playing
this videogame, perhaps by making it more difficult to be proficient in the
game, it is initially harder to extend your body-schema with this new form of
vision, but what happens once you are proficient?
Competitive e-sports increase the stakes and are motivation for players to strive for utmost proficiency in a videogame, this usually leads to players being very creative and highly skilled in using the interface available to them (e.g. mouse and keyboard or a controller). In case of MOBA games with independent cameras, players reach very high action-per-minute numbers, in the last game of the largest competition for Dota 2, The International 10, the players averaged 303 actions per minute, which is about 5 actions per second, not including camera movements (camera movements are fluid and continuous and are not considered as discrete, hence their exclusion from a numerical value). {% cite dotabuff-true-sight %} Competitive e-sports increase the stakes and are motivation for players to
strive for utmost proficiency in a videogame, this usually leads to players
being very creative and highly skilled in using the interface available to them
(e.g. mouse and keyboard or a controller). In case of MOBA games with
independent cameras, players reach very high action-per-minute numbers, in the
last game of the largest competition for Dota 2, The International 10, the
players averaged 303 actions per minute, which is about 5 actions per second,
not including camera movements (camera movements are fluid and continuous and
are not considered as discrete, hence their exclusion from a numerical value).
{% cite dotabuff-true-sight %}
{% cite dolezal2009remote %} considers the question of action-ownership and stakes with regards to telesurgery and embodiment. She stresses the importance of a feeling of agency towards the task at hand, and proposes that high-fidelity technologies could help induce a sense of agency and ownership of action. {% cite dolezal2009remote %} considers the question of action-ownership and
stakes with regards to telesurgery and embodiment. She stresses the importance
of a feeling of agency towards the task at hand, and proposes that high-fidelity
technologies could help induce a sense of agency and ownership of action.
There is a place to ask a similar question about videogames, when the stakes are high, such as competitions with millions of dollars at stake, do players think of the actions they take in the game as their own, do they feel complete agency towards their actions in the game? What factors are at play here? There is a place to ask a similar question about videogames, when the stakes are
high, such as competitions with millions of dollars at stake, do players think
of the actions they take in the game as their own, do they feel complete agency
towards their actions in the game? What factors are at play here?
There is a place to ask a similar question about video-games, when the There is a place to ask a similar question about video-games, when the stakes
stakes are high, such as competitions with millions of dollars at stake, are high, such as competitions with millions of dollars at stake, do players
do players think of the actions they take in the game as their own, do think of the actions they take in the game as their own, do they feel complete
they feel complete agency towards their actions in the game? agency towards their actions in the game?
# Conclusion # Conclusion
Videogames are usually formulated under information-processing cognitive models when studied in cognitive science, however on a closer look, they can be considered an embodied activity given the right framework. Here we consider Merleau-Ponty's intentional stance and body schema as a framework to formulate how a videogame might be considered an embodied activity. Videogames are usually formulated under information-processing cognitive models
when studied in cognitive science, however on a closer look, they can be
considered an embodied activity given the right framework. Here we consider
Merleau-Ponty's intentional stance and body schema as a framework to formulate
how a videogame might be considered an embodied activity.
Camera-avatar relations are an important factor affecting our intentional stance in a videogame, and they lend us different body schemas, from first-person and third-person camera views to an independent isometric camera that is controlled by the player. Independent cameras in videogames allow for a novel extension to our body-schema, an apparatus for vision that can move independent of the body. Camera-avatar relations are an important factor affecting our intentional stance
in a videogame, and they lend us different body schemas, from first-person and
third-person camera views to an independent isometric camera that is controlled
by the player. Independent cameras in videogames allow for a novel extension to
our body-schema, an apparatus for vision that can move independent of the body.
There are still many questions left to be explored on the topic, and rightly so, as the notion of videogames as an embodied activity is fairly perplexing and requires a lot more exploration and study until we reach a more holistic understanding of it. There are still many questions left to be explored on the topic, and rightly so,
as the notion of videogames as an embodied activity is fairly perplexing and
requires a lot more exploration and study until we reach a more holistic
understanding of it.
{% bibliography --cited %} {% bibliography --cited %}

View File

@ -0,0 +1,49 @@
---
layout: post
title: "You can read my blog posts using `curl`"
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
lightweight, are only accessible using a full-fledged web browser. I thought it
would be interesting if my blog posts were available to be read using an even
simpler interface, cURL!
To make this work, I made a very simple Jekyll plugin that automatically
generates a "raw" page for every post I create. These raw pages are available by
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/
```
You can get a raw listing of my blog posts at `/raw/`:
```
curl https://mahdi.blog/raw/
```
To make this easily readable on small screens and terminals, I used vim's
text-width setting to make sure my lines do not exceed 80 characters:
```
:set tw=80
```
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
for [the raw
plugin](https://git.mahdi.blog/mahdi/mahdi.blog/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).

View File

@ -1,24 +0,0 @@
---
layout: page
title: About
permalink: /about/
---
Hi, it's Mahdi. I was born 24th of July, 1998. I write about a variety of topics here, whatever I find worthwhile to share with others.
I like so many things I'd better just list them instead of boring you by making up a fancy sentence about them, so here, in no particular order:
- Programming
- Mathematics
- Nature
- Artificial Intelligence
- Fitness
- Parkour
- All sorts of extreme sports: Skydiving, Scuba Diving, etc.
- Primitive Living
- Leadership
- Human relationships
- Reading
- Music and Art in general
- Philosophy
I like communicating with people, exploring and discovering about new concepts and new possibilities, and every human being is a new concept to discover. In simpler terms, I would like to get to know you, so feel free to shoot me an email: hi@mahdi.blog

View File

@ -17,6 +17,7 @@ layout: default
<span>{{ post.date | date: "%b %-d, %Y" }}</span> <span>{{ post.date | date: "%b %-d, %Y" }}</span>
{% if post.meta %} • <span>{{ post.meta }}</span>{% endif %} {% if post.meta %} • <span>{{ post.meta }}</span>{% endif %}
<span>Reading time: {{ post.content | reading_time }}</span> <span>Reading time: {{ post.content | reading_time }}</span>
<span><a href="/raw{{ page.url }}">raw</a></span>
</p> </p>
</h2> </h2>
<article class='post-content'> <article class='post-content'>

6
raw.html Normal file
View File

@ -0,0 +1,6 @@
---
---
{% for post in site.posts %}
{% if post.published == false %}{% continue %}{% endif %}
{{post.title}}: https://mahdi.blog/raw{{ post.url }}
{% endfor %}

View File

@ -1,4 +0,0 @@
---
layout: category
category: travel
---