add albatross articles
simulpubed
This commit is contained in:
parent
aedc42a9b3
commit
66c4b32049
@ -10,6 +10,6 @@ const imgSrc =
|
|||||||
<template>
|
<template>
|
||||||
<figure class="flex flex-col items-center">
|
<figure class="flex flex-col items-center">
|
||||||
<img :src="imgSrc" />
|
<img :src="imgSrc" />
|
||||||
<figcaption class="text-center"><Markdown /></figcaption>
|
<figcaption class="text-center"><slot /></figcaption>
|
||||||
</figure>
|
</figure>
|
||||||
</template>
|
</template>
|
||||||
|
51
content/blog/2022/4-anonymous-browser-extensions.md
Normal file
51
content/blog/2022/4-anonymous-browser-extensions.md
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
---
|
||||||
|
title: "Stay Anonymous Online With These 4 Browser Extensions"
|
||||||
|
date: "2022-08-06"
|
||||||
|
tags:
|
||||||
|
- tech
|
||||||
|
- albatross
|
||||||
|
---
|
||||||
|
|
||||||
|
This article is [also published in *The FOSS Albatross.*](https://medium.com/the-foss-albatross/stay-anonymous-online-with-these-4-browser-extensions-f032c43f2bb)
|
||||||
|
|
||||||
|
It's a given that no matter what you do while browsing the web, Big Tech has their grubby fingers all over your data and tracks every site you visit, selling it to advertisers and other shady actors. Preventing this is almost impossible, short of something like Tor Browser behind a VPN in a virtual machine, which is slow and cumbersome.
|
||||||
|
|
||||||
|
<!-- more -->
|
||||||
|
|
||||||
|
If you're enamored with the convenience of major browsers, you can still increase your privacy by installing these well-known extensions for Chrome/Firefox, each tackling a different part of web security.
|
||||||
|
|
||||||
|
### 1. uBlock Origin
|
||||||
|
|
||||||
|
You might already know this extension as a popular ad blocker. However, it can do so much more — in addition to blocking ads, uBlock Origin [blocks trackers and malware sites](https://github.com/gorhill/uBlock) while being one of the lightest ad blockers out there to keep your sites snappy. By blocking trackers, you obviously reduce the amount of data that sites can collect, but by blocking ads, you also don't perform the *request* for the ad, so it's like the ad service doesn't even know you were ever there.
|
||||||
|
|
||||||
|
### 2. Decentraleyes
|
||||||
|
|
||||||
|
Whenever you connect to virtually any modern website, that website loads JavaScript libraries to make itself interactive, typically from content delivery networks (CDNs) such as Google, Microsoft, and Cloudflare. This, of course, isn't great, because that means that those CDNs know what site you're loading them from.
|
||||||
|
|
||||||
|
Enter Decentraleyes! This extension bundles quite a few common libraries so that whenever a site tries to grab it from a CDN, it loads it from Decentraleyes running locally on your computer instead. Privacy benefits aside, this also means that those sites load faster by not having to fetch more files from the web!
|
||||||
|
|
||||||
|
### 3. ClearURLs
|
||||||
|
|
||||||
|
Have you ever clicked through a bunch of links and ended up with the longest URL you've ever seen, all for a simple search query?
|
||||||
|
|
||||||
|
**A simple search for Wikipedia on Google:**
|
||||||
|
|
||||||
|
https://www.google.com/search?q=wikipedia&hl=en&ei=Ex7vYq-HI4KH0PEPpKus0Ac&ved=0ahUKEwjv3Lil0rP5AhWCAzQIHaQVC3oQ4dUDCA0&oq=wikipedia&gs_lcp=Cgdnd3Mtd2l6EAxKBAhBGABKBAhGGABQAFgAYABoAHABeACAAQCIAQCSAQCYAQA&sclient=gws-wiz
|
||||||
|
|
||||||
|
**A search for dog food on Amazon:**
|
||||||
|
|
||||||
|
https://www.amazon.com/s?k=dog+food&crid=2UT0FTXBL16XJ&sprefix=dog+foo%2Caps%2C182&ref=nb_sb_noss_2
|
||||||
|
|
||||||
|
All the nonsense after the ampersand (&) are used purely for tracking and won't be caught by content blockers like uBlock Origin because they're *in the initial request itself*. This data includes device and browser information, your search history, how you arrived at the site, and more.
|
||||||
|
|
||||||
|
ClearURLs offers a solution by simply removing all of the nonessential parts of a URL before sending it to Google or Amazon so that they never receive this information, securing a little bit more of your privacy.
|
||||||
|
|
||||||
|
### 4. NoScript
|
||||||
|
|
||||||
|
Lastly, the most intrusive forms of data collection are through JavaScript. So what if you just turned off JavaScript? You'd dramatically improve your browsing experience as sites load much faster, ads don't load at all, and none of the trackers can do a thing, but it could also result in broken sites that rely on it to function at all.
|
||||||
|
|
||||||
|
Therefore, if you truly care about privacy and want maximum control over what is allowed to load in your browser, you'll want to be able to selectively enable JavaScript per-script per website. NoScript is just the tool for this, with an easy-to-use interface that streamlines the troubleshooting process when sites require JavaScript.
|
||||||
|
|
||||||
|
------
|
||||||
|
|
||||||
|
You only need four extensions to dramatically reduce the data sites can collect on you from your browser. Although even these are no match for a properly tuned, custom solution like [LibreWolf](https://librewolf.net/), they provide an excellent first step into becoming more privacy-aware and in securing your data.
|
53
content/blog/2022/foss-licensing.md
Normal file
53
content/blog/2022/foss-licensing.md
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
---
|
||||||
|
title: "Choosing a License — Politics in FOSS"
|
||||||
|
date: "2022-09-02"
|
||||||
|
tags:
|
||||||
|
- tech
|
||||||
|
- albatross
|
||||||
|
---
|
||||||
|
|
||||||
|
This article is [also published in *The FOSS Albatross.*](https://medium.com/the-foss-albatross/choosing-a-license-politics-in-foss-df2cbfe48237)
|
||||||
|
|
||||||
|
All FOSS projects must have a license before other people can use them — but which should you choose, and what are the consequences behind each one?
|
||||||
|
|
||||||
|
<!-- more -->
|
||||||
|
|
||||||
|
## You need a license
|
||||||
|
|
||||||
|
Under the [Berne Convention](https://en.wikipedia.org/wiki/Berne_Convention) signed by the vast majority of countries in 1886, you own copyright to your software the moment you create it. Rights *exclusive to you* unless given otherwise include the right to copy and modify that software.
|
||||||
|
|
||||||
|
In a nutshell, it means that even if you submit your code to GitHub, *no one else* is allowed to copy or redistribute your code (e.g., via forking the repository).
|
||||||
|
|
||||||
|
Licenses work around this by granting specific permissions to other people *so long* as they follow the rules in the license.
|
||||||
|
|
||||||
|
Although there are many different types and variations of licenses, they can be broadly broken down into two categories: **copyleft** licenses and **permissive** licenses.
|
||||||
|
|
||||||
|
## Permissive licenses (e.g., MIT, BSD, Apache)
|
||||||
|
|
||||||
|
These licenses are pretty simple: they let anyone do virtually anything with them, so long as they credit you for using your code. This makes it easier for people to incorporate your code into theirs, but also raises the possibility that others, such as corporations, simply take your code without giving back.
|
||||||
|
|
||||||
|
Permissively licensed programs tend to be used more often by bigger projects due to the lack of restrictions.
|
||||||
|
|
||||||
|
The BSD operating system is a typical example of the dynamic of permissive licenses: Apple used BSD code as a basis for all of their operating systems (macOS, iOS, iPadOS, etc.), as well as Sony in their PlayStations, Nintendo in the Nintendo Switch, and much more. These corporations chose BSD because of how easy it is to take the code for free and build off of it.
|
||||||
|
|
||||||
|
## Copyleft licenses (e.g., GPL, MPL, CC-BY-SA)
|
||||||
|
|
||||||
|
If you really care about the ideology behind the free software movement, you might consider a copyleft license instead. These require all **derivative works** to have the same license that the original program had. They can still do whatever they want with your code, though.
|
||||||
|
|
||||||
|
For example, if library A held a copyleft license and application B bundled it in an app that they published, application B must also be compatible with that copyleft license or else they are in violation of library A's license.
|
||||||
|
|
||||||
|
…Which is a lot of words to say that copyleft licenses are "viral" in that they make everything they touch copyleft.
|
||||||
|
|
||||||
|
If you're a developer, this is really good for you, because it means that if a large corporation adapts your code to make it work for them and improves it, they have to share those improvements with you.
|
||||||
|
|
||||||
|
The Linux kernel is a great example of how copyleft has helped it grow to become the most-used operating system in the world. As devices adopt Linux (e.g., in Android phones), they are required to publish sources that make Linux compatible with their hardware, which is how the custom ROM community exists today!
|
||||||
|
|
||||||
|
Some corporations really hate copyleft because it forces them to open source their code, such as Google's [infamous policy on avoiding the AGPL](https://opensource.google/documentation/reference/using/agpl-policy/) like the plague. If that matters to you, you should use a more permissive license instead.
|
||||||
|
|
||||||
|
------
|
||||||
|
|
||||||
|
It's important to make sure that you are *allowed* to use a license in your project! After all, if you have a copyleft dependency, you can't license your program permissively. In addition, plenty of licenses are incompatible with one another, so you can't use both of them together.
|
||||||
|
|
||||||
|
In general, your program must be at least as copyleft as the most copyleft license in your dependency chain.
|
||||||
|
|
||||||
|
Although not a definitive guide, [https://choosealicense.com](https://choosealicense.com/) from GitHub is a great starting point to choose a license! So long as you're careful and check your dependencies' licenses, you'll be well on your way to contributing to the FOSS community!
|
56
content/blog/2022/github-for-dummies.md
Normal file
56
content/blog/2022/github-for-dummies.md
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
---
|
||||||
|
title: "GitHub for Dummies"
|
||||||
|
date: "2022-06-17"
|
||||||
|
tags:
|
||||||
|
- tech
|
||||||
|
- albatross
|
||||||
|
---
|
||||||
|
|
||||||
|
This article is [also published in *The FOSS Albatross.*](https://medium.com/the-foss-albatross/github-for-dummies-1bb448962fc5)
|
||||||
|
|
||||||
|
Ever been linked to a GitHub page to download something and couldn't figure out what to click? This short, simple guide will help you get to wherever you need in 4 easy steps.
|
||||||
|
|
||||||
|
<!-- more -->
|
||||||
|
|
||||||
|
::image{src="https://lh4.googleusercontent.com/u03FMDrVGVaU7x0ojxnNTAnM6_sPaSsnP1R6pZDJaTH95xqiH8LQKBN4OTZoU0Bigf6seLcCcDtSkuxcMwuLqLrCQH2fs6QsUZFyw58DN26sdbJcmMjXrhWjRQg6aoSzu-gBzib3gz20s0uFi_9h5k7QpgbohXqNkXw2pXPfPu4j3VibM_MNlHBK"}
|
||||||
|
|
||||||
|
What do all these words mean? Issues? Pull requests? Actions? Projects? Releases?
|
||||||
|
::
|
||||||
|
|
||||||
|
### The README and wiki
|
||||||
|
|
||||||
|
Always remember to first RTFM (Read The Fine Manual, with a slightly different word in place of "fine")! The README is always located on the home page of a repository, and it should contain a wealth of information for newcomers to familiarize themselves with the project. Installation instructions are often placed here if you scroll down far enough.
|
||||||
|
|
||||||
|
If that doesn't work, check out the project's wiki if they have one, located in the top navigation bar of the repository. Community members can also contribute to this page, so if you want to help the project and make it easier for newcomers, feel free to add or edit a page!
|
||||||
|
|
||||||
|
### Downloading releases
|
||||||
|
|
||||||
|
Now, if neither the README nor wiki have any hints to finding the link you want, you can go to the *Releases* section of the project, which on a desktop browser is in the right sidebar, while on mobile is located at the very bottom of the page.
|
||||||
|
|
||||||
|
::image{src="https://lh4.googleusercontent.com/v6G-c31NECe6ZJZhe2YSQXocQ4eCBJhYuXjNWSmECm5QQcSKaMWLpxe_roIkIonkMfUcDK4UtuqQEegVXCD1sAwHQnkssxOEk3uUrnQaMbhXL8zyeXdi0nUNv_QTKFsD5ZAUDJijHv_dc5wdTOEjggZipsIStM3vwaiabiNQ8XUY5bolApOupOwd"}
|
||||||
|
In this case, clicking one of the "primoprod" assets with the file extension for your device will get you a runnable program.
|
||||||
|
::
|
||||||
|
|
||||||
|
Releases are the "official" way for projects to upload stable versions of their program to send to others. In the "Assets" section of a release, clicking the link that is not labeled "Source code" will get you a runnable version of the program.
|
||||||
|
|
||||||
|
### Downloading repository files
|
||||||
|
|
||||||
|
Let's say you don't want to download the whole program, but instead just a certain file *inside* the repository. What do you do?
|
||||||
|
|
||||||
|
Similar to Google Drive and other cloud storage platforms, you can click through different folders and eventually on files. Although you can't download folders, you *can* download individual files by clicking on them and then clicking "Raw" or "View Raw".
|
||||||
|
|
||||||
|
If that doesn't work, right-click the page that clicking "Raw" or "View Raw" opened and press "Save Page As".
|
||||||
|
|
||||||
|
### Filing issues
|
||||||
|
|
||||||
|
Trouble in paradise? If none of the above options worked, you can always file a new issue in the "Issues" tab of the project, where you can report bugs and ask questions directly to the project owner.
|
||||||
|
|
||||||
|
![img](https://lh6.googleusercontent.com/l7mlo6OTPsAi17WcYgLeZ39aVp65D_24Kz4PMYOgKArwxJcz4jRcTCtud9UtChEUiUdnVR8sR7_6TvQJAAL2mFcKecLK-hhPvr7De_tPqrvh_mbaNCfVisD2yBn2icaXSl0eFDD4cIHKOzPKOM--2hruiM6qHkC6foW-6Pu63pU9c6FZOid10WXN)
|
||||||
|
|
||||||
|
Remember to read the project's issue guidelines, as some of them have a dedicated support forum or Discord to send help requests to.
|
||||||
|
|
||||||
|
### Contribute to FOSS!
|
||||||
|
|
||||||
|
For those just trying to get a file and dip, GitHub's interface is certainly more complex than it needs to be. The many buttons to streamline developers' experiences often get in the way of a user just trying to download the program.
|
||||||
|
|
||||||
|
As a developer, though, GitHub's many features are powerful and make development faster and more organised. If you ever decide to contribute to the FOSS community, return to GitHub and try to learn about the many other tools available to you!
|
55
content/blog/2022/googles-guide-to-taking-over-the-web.md
Normal file
55
content/blog/2022/googles-guide-to-taking-over-the-web.md
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
---
|
||||||
|
title: "Google's Guide to Taking Over the Web"
|
||||||
|
date: "2022-07-16"
|
||||||
|
tags:
|
||||||
|
- tech
|
||||||
|
- albatross
|
||||||
|
---
|
||||||
|
|
||||||
|
This article is [also published in *The FOSS Albatross.*](https://medium.com/the-foss-albatross/googles-guide-to-taking-over-the-web-26847a389ac5)
|
||||||
|
|
||||||
|
Do you have a dream? A dream where you call the shots for billions of other people and how they communicate with each other? Well, we've got the guide of the decade for you, taken straight from personal experience. In just four easy steps, you'll be able to corner the tech industry yourself!
|
||||||
|
|
||||||
|
<!-- more -->
|
||||||
|
|
||||||
|
## 1. Bribe your competitors.
|
||||||
|
|
||||||
|
This first step is the most important. Without getting your name out there, you don't have the influence needed for web domination. Take out a small loan if you have to. We've bought out Mozilla for $450 million and Apple for $15 billion so that we're the default search engine in Firefox and Safari. Why would our users ever bother to change the default — to something like *Bing*, no less — when ours is good enough?
|
||||||
|
|
||||||
|
You gotta get your customers to associate you with the web, and you know you've got that when your company name is added to the English dictionary. What's the first thing you do whenever you want to look something up? You Google it. And the simplest, easiest, lowest-effort way to do this is by bribing your competitors.
|
||||||
|
|
||||||
|
## 2. Create a browser.
|
||||||
|
|
||||||
|
Make it simple. Make it fast. Make it such that people actually want to use it. Creating your own browser lets you into a whole bunch of important standards organizations, including Ecma and ISO, but most importantly, the W3C.
|
||||||
|
|
||||||
|
Now that everyone is using your search engine, you can abuse your near-monopoly there to tell everyone to use your new browser.
|
||||||
|
|
||||||
|
"A better way to surf the web."
|
||||||
|
|
||||||
|
And since you're Google, they trust you. After all, they get all your information from you, so why would you lie to them? Your users will all happily switch. And, if you've gotten creative, your newfound popularity might mean that your browser engine will be used *outside* of the browser in, say, a popular [server-side language](https://nodejs.org/en/), or even to [make desktop applications](https://www.electronjs.org/)!
|
||||||
|
|
||||||
|
All giving you more power over where the future of the web goes.
|
||||||
|
|
||||||
|
## 3. Extend open standards.
|
||||||
|
|
||||||
|
Now that you have a secure foothold in guiding the future of the web and everyone loves your products, it's time to take the rest of the pages out of Microsoft's playbook: Embrace, Extend, and Extinguish. It's time to add new features. Ones that your users like! But make sure you leverage your own services to show just how important you are to the web. Make others *depend* on you.
|
||||||
|
|
||||||
|
For example, you could [send all traffic to news sites through your own servers](https://en.wikipedia.org/wiki/Accelerated_Mobile_Pages) and call it "speeding up page loads." Don't forget to pretty it up! Open source it, but *you're* the only one allowed to contribute to it. In your search engine — you know, the one that everyone relies on? — rank sites higher depending on if they use your service. That'll encourage them.
|
||||||
|
|
||||||
|
Also, this point is a great time to start hobbling your browser competitors. Lots of people are using your own browser now, but the other browsers are just as good and less people are switching. That's a problem. What can you do about that?
|
||||||
|
|
||||||
|
Hypothetically, of course, you could take another one of your services — one might even say one that is indispensable to the web — and make it [several times slower in other browsers](https://fossbytes.com/youtube-slow-mozilla-firefox-edge/) by using special code in your own browser. Now you've got users' attention. An essential service they use is slow in their browser! How convenient, then, that your browser just happens to fix all those problems!
|
||||||
|
|
||||||
|
Alternatively, if you happen to own an operating system that [powers 70% of all smartphones](https://gs.statcounter.com/os-market-share/mobile/worldwide), you can also put it in there, as only [10% of users change their default mobile browser](https://www.independent.co.uk/tech/google-alternatives-privacy-duckduckgo-search-engine-browser-chrome-eu-fine-a8455321.html)!
|
||||||
|
|
||||||
|
## 4. Make so many standards until no one can catch up.
|
||||||
|
|
||||||
|
If you've made it this far, you've got this in the bag. Just make the web experience "more complete" and "more streamlined!" Do what you've been doing in step 3 but make it impossible for any newcomers to do it securely and properly. Add a protocol for [USB access in the browser](https://en.wikipedia.org/wiki/WebUSB). Add a protocol for [Bluetooth in the browser](https://developer.mozilla.org/en-US/docs/Web/API/Web_Bluetooth_API). Replace third-party cookies with your own specialized tracking mechanism. All in the name of security and privacy, of course.
|
||||||
|
|
||||||
|
There are so many "standard" features in Chrome that it is practically unsustainable to create a new browser engine properly. Opera gave up and switched to Chrome. *Microsoft* tried with Edge before they gave up and used Chrome's engine instead.
|
||||||
|
|
||||||
|
## 5. Profit!
|
||||||
|
|
||||||
|
That's it! No one can stop you now. You have a stranglehold on the web. Your browser / browser engine have [70% of browser share worldwide](https://gs.statcounter.com/os-market-share/mobile/worldwide). Even in China, where your whole ecosystem is practically banned, you have [more than 50% market share](https://gs.statcounter.com/browser-market-share/all/china). Developers optimize for you, further reducing the market share of other browsers as sites are now broken in other browsers.
|
||||||
|
|
||||||
|
You're done. You've taken over the web. There is nothing anyone can do…except switch to Firefox. But who's going to do that? Why would anyone sacrifice the convenience of Chrome just to reject anti-competitive behavior of one company?
|
552
content/blog/2022/handy-python-tricks-2.md
Normal file
552
content/blog/2022/handy-python-tricks-2.md
Normal file
@ -0,0 +1,552 @@
|
|||||||
|
---
|
||||||
|
title: "13 Tricks to Write Nicer Python"
|
||||||
|
date: "2022-08-21"
|
||||||
|
tags:
|
||||||
|
- tech
|
||||||
|
- albatross
|
||||||
|
---
|
||||||
|
|
||||||
|
This article is [also published in *The FOSS Albatross.*](https://medium.com/the-foss-albatross/13-tricks-to-write-nicer-python-d6c65897cd59)
|
||||||
|
|
||||||
|
Known as an easy-to-use and flexible programming language, Python nevertheless still has plenty of tricks you can use to make your code prettier and faster to write. No matter if you’re new to Python or have years of experience, read more to find a tip for you!
|
||||||
|
|
||||||
|
<!-- more -->
|
||||||
|
|
||||||
|
## 1. F-strings
|
||||||
|
|
||||||
|
When printing out lots of text, you might find that you have to add lots of text together, which you might do by string concatenation:
|
||||||
|
|
||||||
|
```py
|
||||||
|
name = "John"
|
||||||
|
lastname = "Doe"
|
||||||
|
print("My name is " + name + " and my last name is " + lastname + ".")
|
||||||
|
```
|
||||||
|
|
||||||
|
As you can see, it gets quite long and cumbersome if the string is long enough and if you’re adding enough strings. This is where **f-strings** come in to make the code readable and actually more performant! These special strings begin with the letter “f” immediately before the opening quote of a string, and any expression in curly braces will be evaluated.
|
||||||
|
|
||||||
|
```py
|
||||||
|
print(f"My name is {name} and my last name is {lastname}.")
|
||||||
|
```
|
||||||
|
|
||||||
|
Completely clear, right?
|
||||||
|
|
||||||
|
That’s not all they can do, either! F-strings also provide some ways to easily format the data by providing how you want the data to be displayed after a colon in the expression.
|
||||||
|
|
||||||
|
For example, you can limit the number of decimal places shown in a float to two decimal places…
|
||||||
|
|
||||||
|
```py
|
||||||
|
num = 123.456789
|
||||||
|
print(f"{num:.2f}")
|
||||||
|
```
|
||||||
|
|
||||||
|
…and even dates and times!
|
||||||
|
|
||||||
|
```py
|
||||||
|
from datetime import date
|
||||||
|
today = date(2022, 8, 21)
|
||||||
|
print(f"{today:%m/%d/%Y}")
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
```
|
||||||
|
08/21/2022
|
||||||
|
```
|
||||||
|
|
||||||
|
## 2. Using “if” to its maximum potential
|
||||||
|
|
||||||
|
Like any language, Python has its quirks with values that evaluate to `True` and `False` in if statements. Specifically, **only the following are False** and every other value is True.
|
||||||
|
|
||||||
|
- Zero (`0` and `0.0`)
|
||||||
|
- Empty containers, such as lists, tuples, dictionaries, sets, **and strings**
|
||||||
|
- `False`
|
||||||
|
- `None`
|
||||||
|
|
||||||
|
This means that actions like checking for empty containers can be drastically shortened from:
|
||||||
|
|
||||||
|
```py
|
||||||
|
array = []
|
||||||
|
if len(array) != 0:
|
||||||
|
print("something is in the list!")
|
||||||
|
```
|
||||||
|
|
||||||
|
to:
|
||||||
|
|
||||||
|
```py
|
||||||
|
array = []
|
||||||
|
if array:
|
||||||
|
print("something is in the list!")
|
||||||
|
```
|
||||||
|
|
||||||
|
## 3. List comprehensions
|
||||||
|
|
||||||
|
You can generate a new list very easily with an inline `for`.
|
||||||
|
|
||||||
|
```py
|
||||||
|
array = [i for i in range(10)]
|
||||||
|
print(array)
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
```py
|
||||||
|
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||||
|
```
|
||||||
|
|
||||||
|
List comprehensions are just syntactic sugar for a regular for loop, so the above code is equivalent to:
|
||||||
|
|
||||||
|
```py
|
||||||
|
array = []
|
||||||
|
for i in range(10):
|
||||||
|
array.append(i)
|
||||||
|
print(array)
|
||||||
|
```
|
||||||
|
|
||||||
|
They’re also useful for performing operations *on* the elements, much like `map` in other functional programming languages.
|
||||||
|
|
||||||
|
```py
|
||||||
|
array = [i for i in range(10)]
|
||||||
|
new_array = [i ** 2 for i in array]
|
||||||
|
print(new_array)
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
```py
|
||||||
|
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
|
||||||
|
```
|
||||||
|
|
||||||
|
In addition, as an alternative to `filter`, you can only include specific elements by adding an `if` at the end:
|
||||||
|
|
||||||
|
```py
|
||||||
|
array = [i ** 2 for i in range(10) if i % 2 == 0]
|
||||||
|
print(array)
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
```py
|
||||||
|
[0, 4, 16, 36, 64]
|
||||||
|
```
|
||||||
|
|
||||||
|
This is equivalent to:
|
||||||
|
|
||||||
|
```py
|
||||||
|
array = []
|
||||||
|
for i in range(10):
|
||||||
|
if i % 2 == 0:
|
||||||
|
array.append(i ** 2)
|
||||||
|
print(array)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 4. Slicing strings and arrays
|
||||||
|
|
||||||
|
Compared to more traditional languages that only allow array accesses `array[i]` for one element, Python lets you "slice" a list or any other sequence (like strings) by a colon between the two indexes.
|
||||||
|
|
||||||
|
```py
|
||||||
|
string = "hello world!"
|
||||||
|
array = [1, 2, 3, 4, 5, 6]
|
||||||
|
|
||||||
|
print(string[2:7])
|
||||||
|
print(array[:-2])
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
```
|
||||||
|
llo w
|
||||||
|
[1, 2, 3, 4]
|
||||||
|
```
|
||||||
|
|
||||||
|
## 5. Tuple expansion
|
||||||
|
|
||||||
|
Tuple expansion is one of Python’s most powerful features, allowing you to expand or assign multiple values in a single line.
|
||||||
|
|
||||||
|
```py
|
||||||
|
a, b = 1, 2
|
||||||
|
s1, s2 = "baguette", "tomato" + "cheese"
|
||||||
|
print(a, b)
|
||||||
|
print(s1, s2)
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
```
|
||||||
|
1 2
|
||||||
|
baguette tomatocheese
|
||||||
|
```
|
||||||
|
|
||||||
|
The code above effectively assigns a tuple `(a, b)` to another tuple `(1, 2)` and is equivalent to the code below:
|
||||||
|
|
||||||
|
```py
|
||||||
|
a = 1
|
||||||
|
b = 2
|
||||||
|
s1 = "baguette"
|
||||||
|
s2 = "tomato" + "cheese"
|
||||||
|
```
|
||||||
|
|
||||||
|
This can let you return multiple values from a function.
|
||||||
|
|
||||||
|
```py
|
||||||
|
def init():
|
||||||
|
return (5, 6)
|
||||||
|
a, b = init()
|
||||||
|
```
|
||||||
|
|
||||||
|
And it’s also really useful in swapping variables!
|
||||||
|
|
||||||
|
```py
|
||||||
|
a = 2
|
||||||
|
b = 4
|
||||||
|
|
||||||
|
# oops, assigned them wrong
|
||||||
|
b, a = a, b
|
||||||
|
```
|
||||||
|
|
||||||
|
Tuple expansion can even be used in for loops to iterate over tuples or dictionaries!
|
||||||
|
|
||||||
|
```py
|
||||||
|
items = {
|
||||||
|
"apple": "juice",
|
||||||
|
"orange": "pulp",
|
||||||
|
"banana": "smoothie",
|
||||||
|
"mango": "slushie"
|
||||||
|
}
|
||||||
|
|
||||||
|
for key, value in items.items():
|
||||||
|
print(key, value)
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
```
|
||||||
|
apple juice
|
||||||
|
banana smoothie
|
||||||
|
mango slushie
|
||||||
|
orange pulp
|
||||||
|
```
|
||||||
|
|
||||||
|
## 6. Shorter code with shortcircuiting
|
||||||
|
|
||||||
|
Imagine you want to assign a variable based on the value of another variable. You might do it this way:
|
||||||
|
|
||||||
|
```py
|
||||||
|
name = "John"
|
||||||
|
if name == "John":
|
||||||
|
last_name = "Doe"
|
||||||
|
else:
|
||||||
|
last_name = "Unknown"
|
||||||
|
```
|
||||||
|
|
||||||
|
But that’s long, and `last_name` appears twice. You can have an inline if to do it in just one line:
|
||||||
|
|
||||||
|
```py
|
||||||
|
name = "John"
|
||||||
|
last_name = "Doe" if name == "John" else "Unknown"
|
||||||
|
```
|
||||||
|
|
||||||
|
Much nicer!
|
||||||
|
|
||||||
|
You also might be familiar with logical boolean operators and how they’re used in if statements.
|
||||||
|
|
||||||
|
```py
|
||||||
|
if password == "hunter2" and name == "Joe":
|
||||||
|
print("password accepted")
|
||||||
|
```
|
||||||
|
|
||||||
|
But you might not know some of their quirks or exactly how they work.
|
||||||
|
|
||||||
|
If you have two things opposite an `and`, for example `x and y`:
|
||||||
|
|
||||||
|
- If `x` evaluates to True, `y` is returned.
|
||||||
|
- If `x` evaluates to False, `x` is returned.
|
||||||
|
|
||||||
|
This might not seem that useful, but then look at `or` in `x or y`:
|
||||||
|
|
||||||
|
- If `x` evaluates to True, `x` is returned.
|
||||||
|
- If `x` evaluates to False, `y` is returned.
|
||||||
|
|
||||||
|
This might also not seem that useful until you learn that logical operators can also be used in assignments, where they’re most commonly used for fallback values.
|
||||||
|
|
||||||
|
```py
|
||||||
|
confirm = input("Accept the EULA? (Y/n) ") or "y"
|
||||||
|
```
|
||||||
|
|
||||||
|
Because `input` returns a string, if the user doesn't enter anything, it evaluates to False, so the value `"y"` is assigned to `confirm`.
|
||||||
|
|
||||||
|
## 7. Safer file handing with context managers
|
||||||
|
|
||||||
|
In most languages, when you write something to a file, it’s actually held in a buffer until you close it manually or automatically when the program ends.
|
||||||
|
|
||||||
|
In Python, you would run the following to write to a file:
|
||||||
|
|
||||||
|
```py
|
||||||
|
file = open("myfile.txt")
|
||||||
|
file.write("hello file")
|
||||||
|
file.close()
|
||||||
|
```
|
||||||
|
|
||||||
|
But that’s a lot of lines, and you might forget to run `file.close()`, particularly in long programs with lots of stuff being written to the file.
|
||||||
|
|
||||||
|
That’s where **context managers** come in, abstracting the whole process and calling `file.close()` automagically:
|
||||||
|
|
||||||
|
```py
|
||||||
|
with open("myfile.txt") as file:
|
||||||
|
file.write("hello file")
|
||||||
|
```
|
||||||
|
|
||||||
|
## 8. Nicer iteration with zip() and enumerate()
|
||||||
|
|
||||||
|
Python’s for loop is commonly known in other programming languages as a for-each loop. This is great if you just want each item in an iterable, but sometimes you want the index too! Instead of having to resort to `range(len(array))`, instead you can use `enumerate()` and tuple expansion to easily get both the index of the element and the element itself:
|
||||||
|
|
||||||
|
```py
|
||||||
|
array = ["a", "b", "c", "d", "e"]
|
||||||
|
for i, c in enumerate(array):
|
||||||
|
print(i, c)
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
```
|
||||||
|
0 a
|
||||||
|
1 b
|
||||||
|
2 c
|
||||||
|
3 d
|
||||||
|
4 e
|
||||||
|
```
|
||||||
|
|
||||||
|
In a similar vein, if you have two arrays you want to process at the same time, you don’t need to use `range(len(array))` when you have `zip()`, which will bundle the different iterators into one big one as big as the smallest iterable.
|
||||||
|
|
||||||
|
```py
|
||||||
|
ints = [1, 2, 3, 4]
|
||||||
|
strs = ("pomme", "poutine", "pinterest", "pear")
|
||||||
|
floats = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]
|
||||||
|
for i, s, f in zip(ints, strs, floats):
|
||||||
|
print(i, s, f)
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
```
|
||||||
|
1 pomme 1.0
|
||||||
|
2 poutine 2.0
|
||||||
|
3 pinterest 3.0
|
||||||
|
4 pear 4.0
|
||||||
|
```
|
||||||
|
|
||||||
|
## 9. Nicer paths with pathlib
|
||||||
|
|
||||||
|
Python is a cross-platform language, and if there’s one annoying difference between Windows and macOS / Linux, it’s that their path separators are different: Windows uses the backslash (`\`) while macOS and Linux use the forward slash (`/`), and attempting to access a path the wrong way will result in file not found.
|
||||||
|
|
||||||
|
So, in the olden days, you would have to string together a long string with `os.path.join` just to be safe:
|
||||||
|
|
||||||
|
```py
|
||||||
|
import os
|
||||||
|
path = os.path.join("folder", os.path.join("subfolder", "subsubfile.txt"))
|
||||||
|
```
|
||||||
|
|
||||||
|
Doesn’t that look clunky?
|
||||||
|
|
||||||
|
Luckily, a “new” (read: years-old) [addition to the standard library](https://docs.python.org/3/library/pathlib.html) makes that *much* easier:
|
||||||
|
|
||||||
|
```py
|
||||||
|
from pathlib import Path
|
||||||
|
path = Path("folder") / "subfolder" / "subsubfile.txt"
|
||||||
|
```
|
||||||
|
|
||||||
|
It also includes a bunch of helper methods to check for things and navigate the filesystem tree just because Python loves making your life easier.
|
||||||
|
|
||||||
|
```py
|
||||||
|
from pathlib import Path
|
||||||
|
path = Path("folder")
|
||||||
|
|
||||||
|
if path.exists() and path.is_file():
|
||||||
|
print("yay!")
|
||||||
|
print(path.parent)
|
||||||
|
print(path.suffix)
|
||||||
|
|
||||||
|
if not path.exists():
|
||||||
|
path.mkdir() ### create the folder if it doesn't exist
|
||||||
|
```
|
||||||
|
|
||||||
|
## 10. Iterable unpacking
|
||||||
|
|
||||||
|
n competitive programming, often you have to print out space-separated results. This can be done by the mildly inconveniencing
|
||||||
|
|
||||||
|
```py
|
||||||
|
print(" ".join([1, 2, 3, 4]))
|
||||||
|
```
|
||||||
|
|
||||||
|
or heaven forbid, via iteration:
|
||||||
|
|
||||||
|
```py
|
||||||
|
for i in [1, 2, 3, 4]:
|
||||||
|
print(i, end=" ")
|
||||||
|
print()
|
||||||
|
```
|
||||||
|
|
||||||
|
which is where iterable unpacking comes in, and you can go straight to
|
||||||
|
|
||||||
|
```py
|
||||||
|
array = [1, 2, 3, 4]
|
||||||
|
print(*array)
|
||||||
|
```
|
||||||
|
|
||||||
|
The **unpacking operator** (the asterisk) basically gets rid of the container and throws all of the elements inside directly into the print function as parameters.
|
||||||
|
|
||||||
|
That means that the above line of code is equivalent to:
|
||||||
|
|
||||||
|
```py
|
||||||
|
print(1, 2, 3, 4)
|
||||||
|
```
|
||||||
|
|
||||||
|
which nicely prints out the integers separated by spaces with a newline at the end.
|
||||||
|
|
||||||
|
But wait, there’s more! The unpacking operator is also commonly used in function definitions as a catch-all parameter for extra arguments, stuffing them into a list.
|
||||||
|
|
||||||
|
```py
|
||||||
|
def init(a, b, *args):
|
||||||
|
print(a, b)
|
||||||
|
print(args)
|
||||||
|
|
||||||
|
init(1, 2, "pomme", 4, 6.0)
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
```
|
||||||
|
1, 2
|
||||||
|
['pomme', 4, 6.0]
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also use this in normal assignment to, say, only get the first and last elements of an array:
|
||||||
|
|
||||||
|
```py
|
||||||
|
first, *args, last = [1, 2, 3, 4, 5]
|
||||||
|
print(first)
|
||||||
|
print(args)
|
||||||
|
print(last)
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
```
|
||||||
|
1
|
||||||
|
[2, 3, 4]
|
||||||
|
5
|
||||||
|
```
|
||||||
|
|
||||||
|
## 11. Else outside of if
|
||||||
|
|
||||||
|
Everyone knows what if-else does. But did you know that Python also lets you use it after loops and exception blocks?
|
||||||
|
|
||||||
|
- In loops, `else` is run *only if* the loop did not `break`.
|
||||||
|
- In exception blocks, `else` is run *only if* there was no exception.
|
||||||
|
|
||||||
|
These are especially useful so you don’t have to add an indicator variable yourself:
|
||||||
|
|
||||||
|
```py
|
||||||
|
for i in array:
|
||||||
|
if i.is_tomato():
|
||||||
|
print("found a tomato!")
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
print("no tomato found :(")
|
||||||
|
```
|
||||||
|
|
||||||
|
…is equivalent to
|
||||||
|
|
||||||
|
```py
|
||||||
|
found_tomato = False
|
||||||
|
for i in array:
|
||||||
|
if i.is_tomato():
|
||||||
|
found_tomato = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if found_tomato:
|
||||||
|
print("found a tomato!")
|
||||||
|
else:
|
||||||
|
print("non tomato found :(")
|
||||||
|
```
|
||||||
|
|
||||||
|
Similarly, in a try-except block:
|
||||||
|
|
||||||
|
```py
|
||||||
|
try:
|
||||||
|
number = int(input("Enter a number: "))
|
||||||
|
except ValueError:
|
||||||
|
print("That's not a number >:(")
|
||||||
|
else:
|
||||||
|
print("You know how to follow instructions! :D")
|
||||||
|
```
|
||||||
|
|
||||||
|
…which is equivalent to:
|
||||||
|
|
||||||
|
```py
|
||||||
|
is_number = True
|
||||||
|
try:
|
||||||
|
number = int(input("Enter a number: "))
|
||||||
|
except ValueError:
|
||||||
|
is_number = False
|
||||||
|
|
||||||
|
if is_number:
|
||||||
|
print("You know how to follow instructions! :D")
|
||||||
|
else:
|
||||||
|
print("That's not a number >:(")
|
||||||
|
```
|
||||||
|
|
||||||
|
## 12. Type hinting
|
||||||
|
|
||||||
|
When you use a library, your IDE often knows what types a function will accept so you don’t have to guess.
|
||||||
|
|
||||||
|
These come from **type hints** in the code, which you can use in your own code, especially if there is a lot of reused code and it’s a long program.
|
||||||
|
|
||||||
|
A colon after a variable shows its type:
|
||||||
|
|
||||||
|
```py
|
||||||
|
a: int = 4
|
||||||
|
```
|
||||||
|
|
||||||
|
…while an arrow after a function shows its return value.
|
||||||
|
|
||||||
|
```py
|
||||||
|
def pow(x: int, y: int) -> int:
|
||||||
|
return x ** 2
|
||||||
|
|
||||||
|
def largest(array: list[int]) -> int:
|
||||||
|
return max(array)
|
||||||
|
```
|
||||||
|
|
||||||
|
In more complex programs, type hinting is especially useful as your IDE can provide autocomplete and better syntax highlighting as it knows the limits of your program, so if you accidentally assume the wrong type of an object, your IDE will complain and find the bug before it causes a runtime crash.
|
||||||
|
|
||||||
|
## 13. The walrus operator (:=)
|
||||||
|
|
||||||
|
Say you’re doing something over and over again and checking for a condition until it’s true. You could do it in a while loop:
|
||||||
|
|
||||||
|
```py
|
||||||
|
import requests
|
||||||
|
|
||||||
|
r = requests.get("https://google.com")
|
||||||
|
while r.status_code != 200:
|
||||||
|
print(r.status_code)
|
||||||
|
time.sleep(1)
|
||||||
|
r = requests.get("https://google.com")
|
||||||
|
```
|
||||||
|
|
||||||
|
But the assignment is repeated twice!
|
||||||
|
|
||||||
|
Introducing the walrus operator, which assigns *and returns the assigned value* in the same statement, allowing for less repeated code and some pretty crazy one-liners:
|
||||||
|
|
||||||
|
```py
|
||||||
|
import requests
|
||||||
|
|
||||||
|
while (r := requests.get("https://google.com")).status_code != 200:
|
||||||
|
print(r.status_code)
|
||||||
|
time.sleep(1)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Although thirteen of them are covered here, there are endless ways to optimise your code so that it’s faster to read, write, and run. Python is a “batteries included” language — chances are that the way you’re used to doing things in other languages have a shorter and more concise method in Python.
|
||||||
|
|
||||||
|
The most important tip I can give you is to check the standard library if you want to do something — from [image format recognition](https://docs.python.org/3/library/imghdr.html) to [config file management](https://docs.python.org/3/library/configparser.html) to [basic database operations](https://docs.python.org/3/library/sqlite3.html), the standard library is chock full of useful tools included over the years.
|
56
content/blog/2022/how-to-emulate.md
Normal file
56
content/blog/2022/how-to-emulate.md
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
---
|
||||||
|
title: "Reviving Older Games Through Emulation"
|
||||||
|
date: "2022-05-22"
|
||||||
|
tags:
|
||||||
|
- tech
|
||||||
|
- albatross
|
||||||
|
---
|
||||||
|
|
||||||
|
This article is [also published in *The FOSS Albatross.*](https://medium.com/the-foss-albatross/reviving-older-games-through-emulation-ca4e9705700c)
|
||||||
|
|
||||||
|
Throughout the past few decades, video games have evolved from an art medium restricted solely to specialized consoles to one enjoyable on all sorts of platforms, including everyday devices such as PCs and phones, replayable for the years to come.
|
||||||
|
|
||||||
|
However, for all of the beloved games that *are* locked to consoles, what option do you have but to let them die out as discontinued second-hand consoles grow more and more expensive as they break down?
|
||||||
|
|
||||||
|
Introducing…emulation!
|
||||||
|
|
||||||
|
<!-- more -->
|
||||||
|
|
||||||
|
### TIL converting games to Australian birds will preserve them.
|
||||||
|
|
||||||
|
::image{src="https://upload.wikimedia.org/wikipedia/commons/9/9d/Emu_1_-_Tidbinbilla.jpg"}
|
||||||
|
(Wikipedia Commons, public domain)
|
||||||
|
::
|
||||||
|
|
||||||
|
Though *emu* and *emulation* share three letters, the only other similarity they have is that large entities have tried and failed miserably to stamp them out in the past. Emulation is the process of one system (such as a phone or computer) imitating another one (such as a video game console) to run programs designed for that system. Emus will now forever ravage the Australian wilderness, and emulation has been ruled to be legal in at least the United States.
|
||||||
|
|
||||||
|
Today, almost every popular system with games in demand has an emulator developed for them that works to some extent, allowing people to take their *rightfully owned* games and play them long after the original system has been discontinued or play them with mods to enhance their experience such as by increasing resolution.
|
||||||
|
|
||||||
|
In a nutshell, this means that if the Nintendo DS you owned as a kid suddenly broke one day, you can back up your cartridges and play Pokémon Black on your phone or computer instead!
|
||||||
|
|
||||||
|
### Cool, how do I try it out?
|
||||||
|
|
||||||
|
Modern-day emulators are nearly all FOSS, allowing them to be ported to most desktop and even mobile operating systems. We recommend the emulators below for their respective systems for a variety of reasons, including user-friendliness, ease of use, performance, and accessibility.
|
||||||
|
|
||||||
|
| Platform | PC | Android |
|
||||||
|
| ----------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
|
||||||
|
| Sony PlayStation 2 | [PCSX2](https://pcsx2.net/) | [AetherSX2](https://www.aethersx2.com/) |
|
||||||
|
| Nintendo GameCube / Wii | [Dolphin](https://dolphin-emu.org/) | [Dolphin](https://dolphin-emu.org/) |
|
||||||
|
| Nintendo DS | [melonDS](https://melonds.kuribo64.net/) / [DeSmuME](https://desmume.org/download/) | [DraStic](https://play.google.com/store/apps/details?id=com.dsemu.drastic&gl=US) / [melonDS](https://github.com/rafaelvcaetano/melonDS-android) |
|
||||||
|
| Sony PlayStation 3 | [RPCS3](https://rpcs3.net/) | None |
|
||||||
|
| Nintendo 3DS | [Citra](https://citra-emu.org/) | [Citra](https://citra-emu.org/) / [Mikage](https://mikage.app/) |
|
||||||
|
| Nintendo Switch | [yuzu](https://yuzu-emu.org/) / [Ryujinx](https://ryujinx.org/) | [Skyline](https://github.com/skyline-emu/skyline) (WIP) |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Do note that emulators, unlike typical games, are *much* heavier on the CPU compared to the GPU because of all the translation required for the emulator to "convert" the game from the console's "language" to that of your phone or PC.
|
||||||
|
|
||||||
|
You can find more details about each emulator and other options for different consoles on the [Emulation General Wiki](https://emulation.gametechwiki.com/index.php/Main_Page).
|
||||||
|
|
||||||
|
### I want to learn more!
|
||||||
|
|
||||||
|
From stories about games relying on undocumented behaviour to *game-breaking* bugs cancelled out only by *console-breaking* bugs, emulation is a fascinating topic well-deserving of your interest if you're at all interested in low-level systems.
|
||||||
|
|
||||||
|
Modern emulators usually perform high-level emulation (HLE), where they emulate the functions that the system OS provides, compared to emulating each transistor like some monstrously complex Minecraft redstone contraption. As you might guess, this approach sacrifices some accuracy for greater performance — it's like translating a book character by character instead of word by word.
|
||||||
|
|
||||||
|
For further reading, there are plenty of blogs run by emulators outlining their tales in overcoming tricky obstacles, and we here at the *Albatross* strongly recommend you go check them out! [Dolphin](https://dolphin-emu.org/blog/) (GameCube / Wii), [yuzu](https://yuzu-emu.org/entry/) (Switch), [Ryujinx](https://blog.ryujinx.org/) (Switch), and [RPCS3](https://rpcs3.net/blog/) (PS3) all attempt to post regular progress reports on their respective blogs, linked above.
|
33
content/blog/2022/many-steps-to-access-a-website.md
Normal file
33
content/blog/2022/many-steps-to-access-a-website.md
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
---
|
||||||
|
title: "Appreciate Your Browser!"
|
||||||
|
date: "2022-09-18"
|
||||||
|
tags:
|
||||||
|
- tech
|
||||||
|
- albatross
|
||||||
|
---
|
||||||
|
|
||||||
|
This article is [also published in *The FOSS Albatross.*](https://medium.com/the-foss-albatross/appreciate-your-browser-82d36a81a696)
|
||||||
|
|
||||||
|
*Click.* Milliseconds after you press a link, your screen flashes white. Elements slowly load in as a page full of search results appears in front of your eyes. How does this magic work? How does your computer know exactly what to show you when you press a button on your mouse? Let's go on a journey through your system to see exactly what happens.
|
||||||
|
|
||||||
|
<!-- more -->
|
||||||
|
|
||||||
|
------
|
||||||
|
|
||||||
|
The instant your finger pushes past a physical barrier, a switch connects a circuit and electrons go speeding through a wire (or over the air if your mouse is wireless) to your computer.
|
||||||
|
|
||||||
|
The moment the central processing unit (CPU) of your computer receives the electrons, it propagates that signal up to your operating system as a **hardware interrupt**, pulling all the brakes on whatever it's currently doing to handle the signal.
|
||||||
|
|
||||||
|
Eventually, your browser realises it's been clicked on and starts the process to fetch the page you're looking for from the internet. Through the operating system, your browser sends a small packet of information to your router, asking it where exactly https://en.wikipedia.org is through its **domain name system** (DNS)!
|
||||||
|
|
||||||
|
Your router kindly asks several other routers, which in turn ask even more routers until it gets back to you with a "208.80.154.224"!
|
||||||
|
|
||||||
|
Armed with this **internet protocol** (IP) address, your browser then asks your router to connect to it, which it happily does, informing you when it returns that the server with that address does in fact exist and is alive.
|
||||||
|
|
||||||
|
Now it's finally time to connect to the server. Your browser extends a handshake to the server, hoping it will reciprocate. Because Wikipedia is a trustworthy site that knows social expectations, it will return the handshake, whispering a secret only it knows through the **Transport Layer Security** (TLS) protocol.
|
||||||
|
|
||||||
|
Assured of Wikipedia's trustworthiness, your browser whispers secrets back, telling Wikipedia the information you're looking for. Wikipedia nods knowingly, but because they have other people to meet, they tell you everything you could ever need to know about parakeets in less than a millisecond with the power of **gzip** (compression) — you just need some time to decipher it.
|
||||||
|
|
||||||
|
Finally satisfied, your browser arranges the data prettily so that it's easy for you to read and holds it out to you expectantly, waiting for your praise.
|
||||||
|
|
||||||
|
Unfortunately, you snatch it out of your browser's hands, berating it for being so slow as you skim only the opening paragraph before yelling at it to fetch more information from Wikipedia, this time about parrots.
|
@ -27,5 +27,10 @@ export const tagInfo: Record<string, TagData> = {
|
|||||||
description:
|
description:
|
||||||
"A collection of very short stories written to do something productive during June–August 2020 and August 2021.",
|
"A collection of very short stories written to do something productive during June–August 2020 and August 2021.",
|
||||||
},
|
},
|
||||||
|
albatross: {
|
||||||
|
name: "The FOSS Albatross",
|
||||||
|
description:
|
||||||
|
'Articles about free and open source software. Also available on <a href="https://medium.com/the-foss-albatross">Medium</a>.',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
export default tagInfo;
|
export default tagInfo;
|
||||||
|
Loading…
Reference in New Issue
Block a user