biologist with a computing problem; personal account @__crusoe
25 stories
·
2 followers

Methods Included

1 Comment and 2 Shares

Standardizing computational reuse and portability with the Common Workflow Language.

Read the whole story
biocrusoe
46 days ago
reply
Our big paper is out!
Lansing, MI
luizirber
43 days ago
reply
Davis, CA
Share this story
Delete

2020: A Year in Review

1 Comment

2020 is not a year any of us will forget. The coronavirus pandemic has brought unprecedented changes to our daily lives. Sadly, many people have endured the loss of loved ones because of the pandemic. Some people suffering discrimination and persecution - including LGBT people - have felt this intensify as a result of changes in society brought about by the pandemic. In many ways, a concern for and a need to protect human rights has never felt more urgent. 

On the ECHR Sexual Orientation Blog I have tried, as always, to provide a factual and critical account of cases in the European Court of Human Rights (and wider developments in the Council of Europe) concerning sexual orientation discrimination. As usual, I have tried to provide readers with an insight into the facts of cases, a discussion of how the Court has approached them, as well as giving my own "point of view".

Below is an overview of much of the activity on the blog this year.

I want to thank everyone who stops by here from time to time to read about the Court and its cases. I have been writing this blog for 7 years now, and over that time I have made lots of new friends because of the blog - people who have contacted me via email, or on Twitter (@echrso) - and I really value that. Thank you for engaging with the material here!

I wish you all a very happy Christmas, in these difficult days, and a happy new year, in which I hope we all have brighter days. 


2020: A Year in Review

Decisions and judgments of the European Court of Human Rights

The Court issued a number of important decisions and judgments relating to sexual orientation discrimination throughout 2020...

In January, the Court issued its judgment in the case of Beizaras and Levickas v Lithuania, holding unanimously that there had been a violation of the Convention in respect of the State’s failure to protect individuals from homophobic hate speech. The judgment is important because it explicitly addresses "hateful comments", including undisguised calls for violence, made by private individuals against the gay community via social media. 

Also in January, the Court issued its judgment in Alekseyev and Others v Russia which concerned 77 applications made to the Court between November 2015 and June 2018 that primarily related to the ban, imposed by Russian authorities, on holding LGBT public assemblies. The Court found violations, but declared applications by Nikolay Alekseyev inadmissible as an abuse of the right of individual application (which I wrote about, in connection with an earlier case, here).

In June, the Court published its decision in the case of Carl Jóhann Lilliendahl v Iceland, in which it unanimously declared the application, by a 74-year-old man concerning a conviction in Iceland for anti-gay expression, inadmissible. The most striking aspect of the Court's decision was the clarification it contained regarding its approach to considering the expression of "hatred" against people on the grounds of sexual orientation. 

In October, the Court issued its judgment in the case of Aghdgomelashvili and Japaridze v Georgia. The case concerned discriminatory ill‑treatment by the police on the grounds of sexual orientation and gender identity, and the absence of an effective domestic investigation of this ill-treatment. The violations found by the Court make an important contribution to its evolving jurisprudence on the interplay between Article 3 and Article 14 of the Convention in respect of acts of hatred (both physical and speech acts) against LGBT people.

In November, the Court issued its judgment in Sozayev and Others v Russia. The case concerned the arrest and conviction of five applicants, in 2013, after they participated in a public assembly in front of the State Duma in Moscow in response to the legislative ban on the "promotion of non-traditional sexual relations among minors". In finding violations of the Convention the judgment addressed restrictions on the right to freedom of peaceful assembly generally, and the right to peacefully assemble to object to homophobic and transphobic laws.

Also in November, the Court issued its judgment in B and C v Switzerlandwhich concerned the case of a gay man (in a same-sex relationship) challenging his deportation to a country (The Gambia) where he would be at risk of ill-treatment because of his sexual orientation. For the first time in its history, the Court held that returning an applicant to a non-European state where they would be at risk of ill-treatment on the grounds of their sexual orientation amounted to a violation of Article 3 (prohibition of torture) of the Convention. 

And again in November, the Court issued its judgment in Honner v France in which it held that the refusal to award contact rights to the applicant in respect of the child which had been born to her former partner in Belgium using assisted reproductive techniques, while the two women were a couple, did not violate the Convention. 

In December, the Court issued its judgment in Berkman v RussiaThe case concerned the failure of police officers to ensure that an LGBTI event disrupted by counter-demonstrators proceeded peacefully, and the unlawful arrest of the applicant at the event. Finding violations of the Convention, the judgment was a further reiteration of the Court's now established principle that domestic authorities are under a positive obligation to ensure that LGBT+ people can exercise their right to freedom of peaceful assembly in circumstances free from homophobic hatred. 

Communicated cases

The Court communicated a range of new cases concerning sexual orientation discrimination throughout 2020, many of which I wrote about on the blog. I detailed...

Cases against Russia concerning employment discrimination, failure of the police to investigate violent hate crime, the deportation of a gay man to a country where he would be at risk, and "homosexual propaganda" laws.

A case against the United Kingdom concerning refusal to supply a gay man with a commercial service

A case against Romania brought by eight same-sex couples concerning the lack of legal recognition of their relationships.

Cases against Lithuania concerning anti-gay hate speech, and restrictions placed on a book for children.

Seven new cases against Poland concerning different aspects of sexual orientation discrimination

A case against France concerning access to a child.

A case against Greece, brought by 162 same-sex couples, concerning lack of relationship recognition

And a case against Croatia concerning lack of access to a fair trial in respect of an allegation of sexual orientation discrimination.

Anniversaries

There were a number of anniversaries this year connected to the Convention, and to sexual orientation discrimination, that I wrote about...

In January, the UK celebrated the 20th anniversary of the ban on gay people serving in the armed forces being lifted. The ban came to an end on 12th January 2000 and this was the direct result of judgments by the Court in 1999. 

In November, the Convention had its 70th birthday.

Also in November, the UK celebrated the 20th anniversary of the legislation that brought about an equal "age of consent", which was significantly encouraged by litigation under the Convention. I summarised the legal history in a piece for Openly (which can be heard as a short podcast).  

December brought the 65th anniversary of the very first case brought under the Convention concerning sexual orientation discrimination. 

Other entries on the blog

In January, I wrote a piece about UK universities, freedom of speech, and trans issues

In June, I detailed an article that I wrote in the European Human Rights Law Review about "gender critical" beliefs.

In September, I wrote a piece about why LGBT people in the UK should prepare to defend their human rights, and this was discussed by Naomi Wolf.

In October, I made available an updated chapter that aims to provide a comprehensive but condensed assessment of the historical development and current state of human rights protection offered to LGBT people by the Council of Europe and, importantly, identify the gaps that currently exist in that protection. 

Also in October, I made available a draft of a new research article, written with Silvia Falcetta, which examines faith-based objections to the inclusion of LGBT content in "relationships education" in primary schools in England.

Blog readership

In the last year, the blog has been visited 51,500 times:


The readership of the blog is global, and four of the top ten countries for readership are outside of the Council of Europe:



The all-time visits for the blog, since it was founded in February 2013, is 331,526.

Read the whole story
biocrusoe
563 days ago
reply
What happened this year in the European Court of Human Rights with respect to sexual orientation rights.
Lansing, MI
Share this story
Delete

Unifying the Technical Interview

2 Shares

Previously: Rewriting the Technical Interview.

Aisha’s hands rattle you. They float gently in front of her shoulders, wrists cocked back. One sways cheerfully as she banters with the hiring manager—her lacquered nails a cyan mosaic over ochre palms. They flit, then hover momentarily as the two women arrange lunch. When the door closes, Aisha slaps her fingertips eagerly on the pine-veneer tabletop. Where have you seen them before?

But she is giggling and glad to finally meet you, and her hair bounces in loose ringlets around the shoulders of her yellow sundress, and you like her, this thirty-something engineer who has worked here three years (even if you don’t understand what it is, exactly, that she does for Mineral Analytics, Limited), who heard you were on the market, and just had to interview you personally. She tells you about the yogurt bar, and the yoga studio, and how important work-life balance is to the company. Then she asks you to balance a binary tree.

Even after all these centuries, you still have trouble grafting limbs. “I’m sorry, you’ll have to give me a moment,” you stall. “I can never keep the transformation rules straight.”

Plead with the demigoddess Andréka to intercede on your behalf.

vidrun@bamse ~> swipl

Aisha smirks. You suspect she knows something.

“Remind me, Aisha—we need to make sure that both branches have the same height? Or differ by just one?”

“At every level.” She folds her arms and offers you a break. “Would you like me to get us started?”

Release the cryptographic wards on two of your xterms, and slide the machine over.

eval_prim(Exp, _, Exp) :- Exp = nil ; Exp = [] ; number(Exp).

“We’ll start with terminals. Nils, empty lists, and numbers—that should be a good start, don’t you think?”

This seems reasonable enough.

“And you know we’re gonna need equality constraints. Addition too, for tree heights.”

:- use_module(library(reif)). eval_prim([eq, A, B], Env, R) :- eval_exp(A, Env, ARes), eval_exp(B, Env, BRes), if_((ARes = BRes), R = true, R = nil). eval_prim([plus, A, B], Env, R) :- eval_exp(A, Env, AR), eval_exp(B, Env, BR), R is AR + BR. eval_exp(Exp, Env, R) :- eval_prim(Exp, Env, R), !.

Clock! She pops her tongue at the cut, startling you. Consider asking about Env, but decide against it: she clearly knows where she’s going.

Aisha gives you a very knowing look over the top of her glasses, then summons a list from the void.

eval_prim([first, List], Env, R) :- eval_exp(List, Env, ListR), if_(([] = ListR), R = nil, [R|_] = ListR). eval_prim([rest, List], Env, R) :- eval_exp(List, Env, ListR), ((ListR = [], R = nil) ; (ListR = [_|R])). eval_prim([cons, Head, Tail], Env, R) :- eval_exp(Head, Env, HeadR), eval_exp(Tail, Env, TailR), if_((nil = TailR), TailL = [], TailL = TailR), R = [HeadR | TailL].

Without moving anything else, raise a single eyebrow two centimeters.

“I’ve read your work! You couldn’t walk into a bodega without conjuring a shopping list from thin air.”

She has read you, hasn’t she?

?- eval_exp([cons, 2, [cons, 1, nil]], {}, R). R = [2, 1].

You’re ready to take it from here, but Aisha continues, nails clacking against the keycaps.

eval_each([], _, []). eval_each([X | More], Env, [XR | MoreR]) :- eval_exp(X, Env, XR), eval_each(More, Env, MoreR).

“Aisha, I–”

Her hands flash and flourish, slapping out a polyrhythm you remember.

type(X, R) :- (atom(X), R = atom) ; (number(X), R = number) ; ([] = X , R = list) ; (functor(X, '[|]', _), R = list), ! ; (compound_name_arity(X, λ, _), R = function), ! ; (compound_name_arity(X, , _), R = macro), ! ; (compound_name_arity(X, Type, _), R = Type). eval_prim([type, X], Env, R) :- eval_exp(X, Env, XR), type(XR, R).

Fy Faen! You see it now!

Snap your fingers, recalling your laptop to your hands. The instrument flies from her grasp, and you are already on your feet, anchoring yourself to the ethernet, Aisha standing in one fluid swooping motion as you cross-step back for space, one hand outstretched to seize—

—thin air.

Your laptop hovers in the air between you, screen blushing rose to iris. Aisha, yawning, checks her nails. Faint bangles of non-printable control characters encircle her wrist in glowing rings, impossible to see directly.

“Oh honey.” Her voice acquires a familiar, husky resonance.

You know her you know her you know–

She sighs in exasperation. “You’re old, not senile!”

Remember 1921: the salt-wind scoring your forehead as the bow of the Kovno cut through the cold Atlantic night. The icy pit of the Gardnos Stone, wrapped in burlap, weighing your bag as if seeking to drown the whole ship. It refused flight, warmth, comprehension. The coven had sent you in search of answers: to Antwerp, to Victorieplaats—all masonry and copper, gold figures gleaming atop the mercantile houses of the bustling diamond-hive.

You’d sought a specialist. You found Aligaz.

A eager scion of the Semien stone-mages, cast from rocky fingertips at a time of cosmopolitan awakenings, he had set up shop in an alley just south of the plaza. Géomancien, Aligaz had explained, giggling at the word, and gestured to the glittering shelves: crystals and milky stones in every color, charged by the steady glow of gaslight. All swish and charm, he had whisked the Stone from your bag and informed you, in lilting French, that you needed to lighten up. “Ces suédois!” You’d bristled at the insult… but he had, in the end, been right.

You had traded spells and languages, huddled under the rain-roaring copper roof of Aligaz’s attic. Worked together to uncover the mystery of Gardnos, and one another. Aligaz, endlessly inventive, had outmatched you at every turn: constructing puzzles within puzzles, locks which everted, became their own keys. He had wondered at your tales of the fjords, and you, in turn, had planned to travel south with him, to see the Ethiopian landscapes he so lovingly recalled—but the coven recalled you to Skjækra. That he could stand before you now, after so many years…

“… Aisha?” You ask, tentative.

“After my aunt.” She smiles fondly.

“What a beautiful name!” It suits her well. “When did—”

“Harlem. After the war.” And here she trails off; lost, perhaps, in her own private recollection.

You are happy for Aisha, of course. To claim one’s true self is the right of all people, and the most powerful of all magics. But you have so many questions!

“What became of the Stone? How did you know? What are you doing here, of all places?”

“Vidrun, this is a geological surveying company. Of course I’m here. The question is why are you applying?”

You pause for a moment.

Why are you here?

“You summoned me!”

“I didn’t know for sure,” she admits. “But rumors spread, and your style is distinctive. How could I pass over the chance to challenge you once more?”

Now the meaning of her spell becomes clear: a trap laid not to ensnare, but to evince. She has offered you a gift. Return the laptop to her, and accept the invitation with grace.

bind(K, V, Env, Env2) :- atom(K), Env2 = Env.put(K, V).

“I bind you, Vidrun,” she intones. Her voice now carries the weight of the Semien, of the Alps, of the Sierra Nevada. A century has grounded her.

“I bind you head and tail.”

bind([], _, Env, Env). bind([K|Ks], Vs, Env, Env3) :- (K = &(K2), bind(K2, Vs, Env, Env3), !) ; ([] = Vs, bind(K, nil, Env, Env2), bind(Ks, [], Env2, Env3)); ([V1|V1s] = Vs, bind(K, V1, Env, Env2), bind(Ks, V1s, Env2, Env3)).

Your breath catches in your throat.

“You shall see only that which is shown,” she continues.

eval_var(Var, Env, R) :- atom(Var), get_dict(Var, Env, R).

“You may speak without speaking,”

eval_prim([quote, R], _, R).

“And within these bounds, you may choose your own path.”

eval_prim([cond], _Env, nil). eval_prim([cond, Default], Env, R) :- eval_exp(Default, Env, R). eval_prim([cond, Test, Branch | More], Env, R) :- eval_exp(Test, Env, TestR), if_((nil = TestR), eval_prim([cond | More], Env, R), eval_exp(Branch, Env, R)).

A Lisp, then. Murmuring softly, you offer a prayer to McCarthy. Hopefully Aisha does not expect you to reinvent lambdas from scratch.

“What you let, will become.”

eval_prim([let, [], Body], Env, R) :- eval_exp(Body, Env, R). eval_prim([let, [K, V | More], Body], Env, R) :- eval_exp(V, Env, VR), bind(K, VR, Env, Env2), eval_prim([let, More, Body], Env2, R).

Well, that’s something, at least. Serial assignment, too—a luxury. But Aisha is not finished. She clacks her heels firmly onto the industrially-sealed concrete, and opens her arms wide. Her palms are ruddy laterite, her upturned eyes glinting magnetite under halogen stars.

evoke(Vars, Args, Body, Env, R) :- bind(Vars, Args, Env, Env2), eval_exp(Body, Env2, R). eval_application([Fun | Args], Env, R) :- eval_exp(Fun, Env, FunR), FunR = λ(Vars, Body, Env2), eval_each(Args, Env, ArgsR), evoke(Vars, ArgsR, Body, Env2, R).

The Church. The lambda calculus. The gay agenda. It has known a thousand names, a thousand forms. Aisha slams her palms together, and with the crash of mountains, summons the thousandth-and-first.

eval_prim([lambda, Args, Body], Env, R) :- R = λ(Args, Body, Env.put(recur, R)).

The conference room twists, folds somehow. Outside, the rows of desks and office furniture rush away to the horizon, replaced by a featureless expanse of evenly-lit pine. On the tabletop, a miniature cube of glass and concrete inflates from nothing to a tiny, modernist dollhouse. You lean over to look inside, notice the light outside the conference room abruptly dim, and think better of it.

eval_exp(Exp, Env, R) :- eval_var(Exp, Env, R), ! ; eval_prim(Exp, Env, R), ! ; eval_application(Exp, Env, R), !.

Aisha takes a deep breath and regains her composure. You sense her spell is near complete.

Whisper softly, so as not to disturb her work. “Macros?”

She glares sidelong, eyes wide. “Really?”

“It’ll be fun.”

eval_prim([gensym, Prefix], _Env, R) :- atom_concat(Prefix, '__auto__', Sym), gensym(Sym, R). eval_prim([macro, Args, Body], Env, R) :- R = (Args, Body, Env). eval_application([Fun | Args], Env, R) :- eval_exp(Fun, Env, FunR), ((FunR = λ(Vars, Body, Env2), eval_each(Args, Env, ArgsR), evoke(Vars, ArgsR, Body, Env2, R)) ; (FunR = (Vars, Body, Env2), evoke(Vars, Args, Body, Env2, Code), eval_exp(Code, Env, R))).

“One more thing,” you request. “Some kind of product type.”

“Ma'am, this is a Wendy’s.”

“Do you really want to watch me reinvent a dynamic type system on top of bare lists?”

Aisha considers the possibility—somewhat sadistically, you think—but this is not that kind of interview.

“Fine. But that’s ALL you’re getting.”

eval_prim([struct, Type | Fields], Env, R) :- eval_each(Fields, Env, FieldsR), compound_name_arguments(R, Type, FieldsR). eval_prim([destruct, Type, Struct], Env, R) :- eval_exp(Struct, Env, StructR), compound_name_arguments(StructR, Type, R).

Your hair charges with static as Aisha seals the spell. Her nails flare in the light, leaving cyan trails in the air above the keyboard. As she executes the final command, you feel your connection with Andréka severed. You are locked in Aisha’s calculus now.

“I knew exactly where you were going with this, Vidrun. You couldn’t remember how to balance a binary tree, so you thought you’d define the transformational invariants and have Prolog solve them for you.”

“So you’re trapping me in a Lisp instead.”

“Would you have preferred an Algolem?” Aisha smirks. You would not.

Very well. Sprinkle salt, as is tradition, in the protective form of two parentheses. No—you wipe the salt clear—square brackets. Test the forms of this new plane.

?- eval_exp([let, [list, [lambda, [&(args)], args]], [list, 1, 2, 3]], e{}, R). R = [1, 2, 3].

It’s not much, but it’s a start. Aisha watches you expectantly; you need to do something. Stall for time by summoning an algebra.

and, [macro, [a, b], [list, [quote, cond], a, b]], or, [macro, [a, b], [let, [a_, [gensym, a]], [list, [quote, let], [list, a_, a], [cond, a_, a_, b]]]], not, [lambda, [x], [cond, x, nil, [quote, true]]],

Aisha makes a show of yawning. Bore her with type predicates.

is_null, [lambda, [x], [or, [eq, x, []], [eq, x, nil]]], is_list, [lambda, [x], [eq, [type, x], [quote, list]]], is_pair, [lambda, [x], [and, [not, [is_null, x]], [is_list, x]]], is_fn, [lambda, [x], [eq, [type, x], [quote, function]]],

You think you’re getting the hang of this—though you haven’t used your comma key this much in years. It’s all so excitingly verbose.

second, [lambda, [coll], [first, [rest, coll]]], map, [lambda, [f, coll], [cond, [is_null, coll], [], [cons, [f, [first, coll]], [recur, f, [rest, coll]]]]], find, [lambda, [f, coll], [cond, [is_pair, coll], [let, [x, [first, coll]], [cond, [f, x], x, [recur, f, [rest, coll]]]]]], fold, [lambda, [f, init, coll], [cond, [is_null, coll], init, [recur, f, [f, init, [first, coll]], [rest, coll]]]], rev, [lambda, [coll], [fold, [lambda, [list, elem], [cons, elem, list]], [], coll]], [rev, [list, 1,2,3]] R = [3, 2, 1].

Smile, wistfully. That had been a good interview.

syntax_quote_fn, [lambda, [expr], [cond, [is_null, expr], expr, [is_list, expr], [let, [f, [first, expr]], [cond, [eq, f, [quote, unquote]], [second, expr], [cons, [quote, list], [map, recur, expr]]]], [list, [quote, quote], expr]]], syntax_quote, [macro, [expr], [syntax_quote_fn, expr]],

“Honestly!” Aisha mutters. “I don’t know what you wanted macros for in the first place. Is this really necessary for balancing a tree?”

Keep your expression as enigmatic as possible. She may have cut you off from the Goddess Andréka, but you can will your own deities into existence.

lvar, [lambda, [num], [struct, lvar, num]], is_lvar, [lambda, [x], [eq, [quote, lvar], [type, x]]], lvar_num, [lambda, [x], [first, [destruct, foo, x]]],

Aisha’s jaw drops as she grasps your scheme. “You have got to be kidding.”

“Kiselyov, Friedman, Byrd”, you incant. “I call upon you, triune, though you have never dwelt within these forms. May you walk this plane as well!”

walk, [lambda, [u, subs], [let, [pr, [and, [is_lvar, u], [find, [lambda, [v], [eq, u, [first, v]]], subs]]], [cond, pr, [recur, [rest, pr], subs], u]]],

“May all merge within your reasoned embrace!”

ext_s, [lambda, [x, v, subs], [cons, [cons, x, v], subs]], unify, [lambda, [u, v, subs], [let, [u, [walk, u, subs], v, [walk, v, subs]], [cond, [eq, u, v], subs, [is_lvar, u], [ext_s, u, v, subs], [is_lvar, v], [ext_s, v, u, subs], [and, [is_pair, u], [is_pair, v]], [let, [subs, [recur, [first, u], [first, v], subs]], [and, subs, [recur, [rest, u], [rest, v], subs]]]]]],

Aisha locks eyes with you. Inside each of you, something shifts, merges, becomes bound.

mzero, [],

“M'Zero,” she quips, and you share a giggle.

“Absolute unit,” you respond.

unit, [lambda, [state], [cons, state, mzero]],

Demand equality. Some would call this a constraint, but you know it to be foundational.

eql, [lambda, [u, v], [lambda, [st], [let, [subs, [unify, u, v, [first, st]]], [cond, subs, [unit, [cons, subs, [rest, st]]], mzero]]]],

“May this space be open to newcomers,” you declare.

call_fresh, [lambda, [f], [lambda, [st], [let, [c, [rest, st]], [[f, [lvar, c]], [cons, [first, st], [plus, 1, c]]]]]],

“And may their futures weave a beautiful tapestry.” You forsee threads of execution racing ahead, taking turns, alternating and combining.

mplus, [lambda, [a, b], [let, [mplus, recur], [cond, [is_null, a], b, [is_fn, a], [lambda, [], [mplus, b, [a]]], [cons, [first, a], [mplus, [rest, a], b]]]]], bind, [lambda, [stream, goal], [let, [bind, recur], [cond, [is_null, stream], mzero, [is_fn, stream], [lambda, [], [bind, [stream], goal]], [mplus, [goal, [first, stream]], [bind, [rest, stream], goal]]]]],

Imbue the triune with its own algebra.

disj, [lambda, [g1, g2], [lambda, [state], [mplus, [g1, state], [g2, state]]]], conj, [lambda, [g1, g2], [lambda, [state], [bind, [g1, state], g2]]]

Moving carefully, you follow a thread of that tapestry to its first few knots.

pull, [lambda, [stream], [cond, [is_fn, stream], [recur, [stream]], stream]], take, [lambda, [n, stream], [cond, [eq, 0, n], [], [let, [stream, [pull, stream], state, [first, stream]], [cond, state, [cons, state, [recur, [plus, n, -1], [rest, stream]]], []]]]], run_raw, [lambda, [n, goal], [take, n, [goal, [cons, [], 0]]]],

The work complete, you let go a sigh. Your godhead takes its first tottering steps.

?- eval([run_raw, 3, [call_fresh, [lambda, [x], [disj, [eql, x, [quote, aisha]], [eql, x, [quote, vidrun]]]]]], R = [[[[lvar(0)|aisha]]|1], [[[lvar(0)|vidrun]]|1]].

“You absolute madwoman,” Aisha chortles. “You can’t remember how to balance a binary tree, but you memorized µKanren?”

“It comes in handy!” You stammer. “And honestly, it’s shorter.” Offer her a reifier by way of apology.

“Fine. Fine!” Aisha throws up her hands in mock exasperation. “I’ve let you get away with it this far!”

walkr, [lambda, [v, subs], [let, [v, [walk, v, subs], walkr, recur, w, [lambda, [v2], [walkr, v2, subs]]], [cond, [is_lvar, v], v, [is_pair, v], [cons, [w, [first, v]], [w, [rest, v]]], v]]], reify, [lambda, [states], [map, [lambda, [state], [walkr, [lvar, 0], [first, state]]], states]]

“Only with respect to the first variable,” you explain. “But it still makes things easier to read.”

eval([reify, [run_raw, 3, [call_fresh, [lambda, [x], [disj, [eql, x, [quote, aisha]], [eql, x, [quote, vidrun]]]]]]], R). R = [aisha, vidrun].

Aisha has the look of a woman who has realized, six hours into her shift, that she has left the oven on. “That’s why you wanted macros. You wanted syntax for this rickety-ass interpreter.”

Reward her insight by entering the metatrance of creation, and let the forms spill from your fingertips.

zzz, [macro, [g], [let, [state_, [gensym, state]], [syntax_quote, [lambda, [[unquote, state_]], [lambda, [], [[unquote, g], [unquote, state_]]]]]]], conjall, [macro, [&(gs)], [let, [[g, &(gs)], [rev, gs]], [fold, [lambda, [form, goal], [syntax_quote, [conj, [zzz, [unquote, goal]], [unquote, form]]]], [list, [quote, zzz], g], gs]]], disjall, [macro, [&(gs)], [let, [[g, &(gs)], [rev, gs]], [fold, [lambda, [form, goal], [syntax_quote, [disj, [zzz, [unquote, goal]], [unquote, form]]]], g, gs]]], conde, [macro, [&(clauses)], [cons, [quote, disjall], [map, [lambda, [goals], [cons, [quote, conjall], goals]], clauses]]], fresh, [macro, [vars, &(goals)], [fold, [lambda, [form, var], [syntax_quote, [call_fresh, [lambda, [[unquote, var]], [unquote, form]]]]], [cons, [quote, conjall], goals], [rev, vars]]], run, [macro, [n, vars, &(goals)], [syntax_quote, [reify, [run_raw, [unquote, n], [unquote, [cons, [quote, fresh], [cons, vars, goals]]]]]]]

Crack your knuckles, and enjoy the series of pops which fizzle from somewhere under your keyboard. “Would you like to do the honors?”

Aisha, half-amused, half exasperated, draws a shining hair from her scalp. Fingers deft, she ties a knot in it for zero.

succ, [lambda, [n], [cons, [quote, 'S'], n]], n0, [list, 0], succo, [lambda, [n, next], [eql, [succ, n], next]],

You draw one of your own, and align them, side by side.

lesso, [lambda, [lesser, greater], [let, [lesso, recur], [fresh, [g], [succo, g, greater], [conde, [[eql, lesser, g]], [[lesso, lesser, g]]]]]], maxo, [lambda, [a, b, max], [conde, [[eql, a, b], [eql, max, a]], [[lesso, a, b], [eql, max, b]], [[lesso, b, a], [eql, max, a]]]], approxo, [lambda, [a, b], [conde, [[eql, a, b]], [[succo, a, b]], [[succo, b, a]]]],

Aisha reaches into her purse, and withdraws a single gleaming seed. This she sets gently upon the table, and waits for you to draw it to fruition.

leaf, [lambda, [x], [list, [quote, leaf], x]], branch, [lambda, [left, right], [list, [quote, branch], left, right]],

A maple tree in miniature, no more than 4 inches high, rises from the tabletop. Outside, in the vast expanse of tabletop, its twin—writ large—swells to full size.

Aisha recognizes the form you have chosen, and raises a spell of translation around it.

tree, [lambda, [t], [cond, [is_list, t], [let, [[left, right], t], [branch, [recur, left], [recur, right]]], [leaf, t]]], untree, [lambda, [[type, a, b]], [cond, [eq, type, [quote, branch]], [list, [recur, a], [recur, b]], [eq, type, [quote, leaf]], a]],

With a flick of your hands, the tree shimmers, reforms.

[tree, [quote, [1, [2, 3]]]] R = [branch, [leaf, 1], [branch, [leaf, 2], [leaf, 3]]].

You measure along each leaf, each branch, and find the height thereof.

heighto, [lambda, [t, h], [let, [heighto, recur], [conde, [[fresh, [x], [eql, t, [leaf, x]], [eql, h, n0]]], [[fresh, [left, right, left_height, right_height, max_height], [eql, t, [branch, left, right]], [heighto, left, left_height], [heighto, right, right_height], [maxo, left_height, right_height, max_height], [succo, max_height, h]]]]]],

Pause a moment, and look to Aisha. A balanced tree: each branch of roughly the same height. Each branch, in turn, a balanced tree itself. Speaking slowly, then faster, in unison, recite:

balancedo, [lambda, [t, h], [let, [balancedo, recur], [conde, [[fresh, [x], [eql, t, [leaf, x]]]], [[fresh, [left, right, left_height, right_height], [eql, t, [branch, left, right]], [balancedo, left], [balancedo, right], [heighto, left, left_height], [heighto, right, right_height], [approxo, left_height, right_height]]]]]],

With all the delicacy you can muster, you peel boughs from trunks, rearrange, then press the limbs gently together. Aisha leans in and blows; the warmth of her breath speeding the healing process.

rot_lefto, [lambda, [t1, t2], [fresh, [a, b, c], [eql, t1, [branch, a, [branch, b, c]]], [eql, t2, [branch, [branch, a, b], c]]]],

Aisha folds her hands together, whispers an incantation, and unfolds them. The maple peels apart into mirrored copies.

rot_botho, [lambda, [t1, t2], [conde, [[rot_lefto, t1, t2]], [[rot_lefto, t2, t1]]]],

Following her lead, you thrust your hands forth and split your fingers in twos, then fours. The tree flickers, expanding into a small forest of copies–each different in exactly one way.

roto, [lambda, [t1, t2], [let, [roto, recur], [conde, [[rot_botho, t1, t2]], [[fresh, [t1l, t1r, t2l, t2r], [eql, t1, [branch, t1l, t1r]], [eql, t2, [branch, t2l, t2r]], [conde, [[eql, t1r, t2r], [roto, t1l, t2l]], [[eql, t1l, t2l], [roto, t1r, t2r]]]]]]]],

Aisha snaps, and with a thwap, unfurls a ludicrously oversized hand-fan from thin air. You ask her where she summoned it from, and how did she ever get Turing to sign it—but she simply bats her eyes and fans herself, looking incredibly smug.

rotso, [lambda, [t1, t2], [let, [rotso, recur], [conde, [[eql, t1, t2]], [[fresh, [t], [roto, t1, t], [rotso, t, t2]]]]]],

The tabletop is filled with trees; outside the conference room, an infinite forest of golden leaves shimmers. Aisha’s fan waves, and a thousand branches whisper in wind-dappled light.

When she refurls the fan, the forest folds with it. Only a solitary tree remains.

It is an act of extraordinary beauty, and for a moment, you are back in the Victorieplaats attic: sunset cast through time-warbled windows, each amber shaft holding sparkling motes of dust which blaze into light, drift briefly, and then go dim again: not lost, merely out of view, and Aisha is whispering an incantation to you, her words unfolding a map within a map within your mind, and you wonder, had you not been recalled, what more you might have become…

“Vidrun. Almost there.”

You take her offered hand in yours, and voices evenly matched, complete the spell.

balanceo, [lambda, [tree, balanced], [conde, [[rotso, tree, balanced], [balancedo, balanced]]]]

Measuring carefully and whispering to herself, Aisha encodes the tree in front of you, and asks for its balanced form:

[map, untree, [run, 1, [t], [balanceo, [tree, [quote, [[0,1],[[2,[3,4]],5]]]], t]]] R = [[[[0, 1], 2], [[3, 4], 5]]].

The tree shifts, blurs, and for an instant you perceive a forest of its balanced siblings, each one possible, but this one yours, and there it is: golden leaves arranged exactly as they were before, but supported by new, more even branches. As her spell unwinds, and the conference room re-attaches to reality, Aisha beams.

“I knew you couldn’t do anything the easy way.”

“Never have,” you admit. “Thank you, Aisha.”

“Any time,” she smiles, and from the tabletop, into your outstretched palms, delivers you a gleaming maple seed.


With sincerest thanks to Taber Bain, Zyle Cook, Brad Greenlee, Coda Hale, Duretti Hirpa, Moishe Lettvin, Dan Mess, Kit Patella, and Emily St, who contributed research, story suggestions, and feedback on initial drafts.

This work was inspired by Andréka and Németi’s 1978 The Generalized Completeness of Horn Predicate Logic as a Programming Language, which shows that logic programs are Turing-complete, as well as McCarthy’s 1955 Lisp paper which defines a Lisp evaluator (including recursive lambdas!) in terms of a handful of basic functions: car, cdr, cons, cond, and so on. It also draws on Steele Jr & Sussman’s The Art of the Interpreter. I designed several Prolog metacircular interpreters based on both of these papers, but ultimately wrote the (much more complex) interpreter here in search of concision and execution speed. The µKanren implementation is directly taken from µKanren: A Minimal Functional Core for Relational Programming, by Hemann & Friedman, though Vidrun invokes Friedman, Byrd, and Kiselyov for their work on The Reasoned Schemer. An earlier version of this work followed Byrd, Holk, and Friedman in using miniKanren to generate quines: Vidrun was to escape a trap by constructing interpreters which interpreted themselves. This approach seemed too derivative, and balancing a binary tree was an interview question which I personally bombed in 2010; it felt nice to revisit the problem with Aisha & Vidrun at the helm.

You can find a fully commented and expanded version of Aisha & Vidrun’s program here. This version includes (do ...) expressions, side effects, stacktraces, additional literals, eval, and a partial dynamic type system. In addition to balancing binary trees, it includes a tiny lambda-calculus interpreter: a sort of lisp-in-minikanren-in-lisp-in-prolog.

Read the whole story
biocrusoe
626 days ago
reply
Lansing, MI
Share this story
Delete

Uploading Metadata: A Case Study in Adjusting Undocumented Behavior on Legacy Code Bases

1 Share
Reading Time: 4 minutes

I sometimes live stream my development work on the NASA Landsat Data Processing Pipeline. It’s an asychronous task management app written in Python.

NASA Vehicle Assembly Building with Launch Pad 39A in the Background.
NASA Vehicle Assembly Building with Launch Pad 39A in the Background. Photo by @mgde_visuals.

The pipeline’s tasks include:

  • collecting and unpacking massive data collected by Earth-orbiting satellites about the radiation reflected from Earth’s surface at various wavelengths
  • turning that data into image representations that the human eye can interpret
  • manipulating those images, say, to emphasize a particular wavelength, or divide the image into tiles for easier analysis
  • uploading the resulting images to the Zooniverse, a platform for people-powered scientific research.

Sound cool? It is. If you’d like to learn more about it and/or enjoy the live streams where I write code for it, I recommend taking a look at this technical briefing I made for you. I explain what the app does and why it matters, then I guide you through the code…all while sipping coffee, bikini-clad, in front of a gorgeous Space Coast sunrise 😉.

The technical briefing done, it was time to get to work.

What you see below are the recordings of about two hours of streams. In these streams, I’m working on including additional data with the images uploaded to the Zooniverse—data that records the latitude and longitude coordinates where the image was taken, the size of the image, and other information.

You get to see me make design decisions about how our app should work for Earth science research teams that need metadata uploaded versus teams that don’t.

You also get to see me spelunk through a fairly complex app to identify:

  • What’s already working
  • Where functionality is missing
  • Where new functionality should live

In the past I’ve done detailed show notes for these streams, but nowadays I’m streaming enough that I don’t have time to do that. Instead, here’s how this will go:

  1. Eventually if enough people support the Patreon I’ll hire someone to help create show notes so you get them again 😉
  2. In the meantime, I will pull out enticing quotes from the streams to reeeel you into watching them. That’s right—just like you’re a fish.

6:23 – This is where I explain the decisions we (well, I, with you as an audience) have to make about how to make this app work for multiple potential use cases.

59:20 – “GAH! LOOK AT THIS!”

1:04:00 – “So we may need to parse a CSV which…I’m not super pumped about…but whatever”

1:17:30 – “So we open, blah blah blah, blah blah blah, then we do this dict reader AND THEN if we were to print row it would look like…this, supposedly.”

1:26:50 – “I want to make reads fast, because we only have to do [the insertion] once, but we have to read constantly.”

Here’s some additional footage after we took a break:

2:30 – “And then I don’t ever set any config. HelLO?…No…NO…..THERE we go!”

8:08 – Go here if you want to hear me sing a Backstreet Boys song for some reason

10:55 – Oh, this  was probably the reason.

We left off on this stream asking the research team for the wgs row of a location with a visible coast, which I ended up solving by using the Landsat Acquisition Map to locate a tile that likely included coastline and get the WRS (World Reference System) row and path for that tile.

While I finished this feature up off-stream, in future streams we’ll look at details of UI design, deployment, and maybe even some researcher-facing features!

If you liked this piece, you might also like:

The debugging posts (a toolkit to help you respond to problems in software)

The Listening Series (Prepare to question much of what you know about how to be good at your job.)

Skills for working on distributed teams (including communication skills that will make your job easier)

 

Read the whole story
biocrusoe
730 days ago
reply
Lansing, MI
Share this story
Delete

SIMDe 0.5.0 Released

2 Shares

I’m pleased to announce the availability of the first release of SIMD Everywhere (SIMDe), version 0.5.0, representing more than three years of work by over a dozen developers.

SIMDe is a permissively-licensed (MIT) header-only library which provides fast, portable implementations of SIMD intrinsics for platforms which aren’t natively supported by the API in question.

For example, with SIMDe you can use SSE on ARM, POWER, WebAssembly, or almost any platform with a C compiler. That includes, of course, x86 CPUs which don’t support the ISA extension is question (e.g., calling AVX-512F functions on a CPU which doesn’t natively support them).

If the target natively supports the SIMD extension in question there is no performance penalty for using SIMDe. Otherwise, accelerated implementations, such as NEON on ARM, AltiVec on POWER, WASM SIMD on WebAssembly, etc., are used when available to provide good performance.

SIMDe has already been used to port several packages to additional architectures through either upstream support or distribution packages, particularly on Debian.

If you’d like to play with SIMDe online, you can do so on Compiler Explorer.

What is in 0.5.0

The 0.5.0 release is SIMDe’s first release. It includes complete implementations of:

  • MMX
  • SSE
  • SSE2
  • SSE3
  • SSSE3
  • SSE4.1
  • AVX
  • FMA
  • GFNI

We also have rapidly progressing implementations of many other extensions including NEON, AVX2, SVML, and several AVX-512 extensions (AVX-512F, AVX-512BW, AVX-512VL, etc.).

Additionally, we have an extensive test suite to verify our implementations.

What is coming next

Work on SIMDe is proceeding rapidly, but there are a lot of functions to implement… x86 alone has about 6,000 SIMD functions, and we’ve implemented about 2,000 of them. We will keep adding more functions and improving the implementations we already have.

Our NEON implementation is being worked on very actively right now by Sean Maher and Christopher Moore, and is expected to continue progressing rapidly.

We currently have two Google Summer of Code students working on the project as well; Hidayat Khan is working on finishing up AVX2, and Himanshi Mathur is focused on SVML.

If you’re interested in using SIMDe but need some specific functions to be implemented first, please file an issue and we may be able to prioritize those functions.

Getting Involved

If you’re interested in helping out please get in touch. We have a chat room on Gitter which is fairly active if you have questions, or of course you can just dive right in on the issue tracker.

Read the whole story
luizirber
743 days ago
reply
Davis, CA
biocrusoe
743 days ago
reply
Lansing, MI
Share this story
Delete

Top tech grads are increasingly unwilling to work for Big Tech, viewing it as a new, unethical Wall Street

2 Shares

About five years ago, I was trying to get a bunch of Big Tech companies to take the right side of an urgent online civil rights fight, and I called an old friend who was very senior at one of the biggest tech companies in the world; they told me that it wasn't going to work, in part because the kinds of people who were coming to tech were there because they wanted to get as rich as possible, no matter what they had to do. My friend contrasted this with earlier eras -- even the dotcom bubble -- when the financial motive was blended with a genuine excitement for the transformative potential of tech to make a fairer, more equitable world. Now, my friend said, the kind of kid who would have gotten an MBA was instead getting an electrical engineering or computer science degree -- not out of any innate love for the subject, but because that was a path to untold riches.

But things are changing. Not only are young people far more skeptical of capitalism and concerned that it will annihilate the human race, but the tech companies' masks have slipped, revealing their willingness to supply ICE and the Chinese government alike, to help the oil industry torch the planet, and to divert their fortunes to supporting white nationalist causes. Companies that tout their ethical center have harbored and even rewarded serial sexual predators and busted nascent union movements.

The tech worker uprisings of recent years have caught the attention of the best and brightest grads of America's elite universities. The New York Times reports that tech recruiters are getting the cold shoulder from students a job fairs, where they are quizzed about Salesforce and Palantir's work with ICE; Google's multimillion-dollar payout for a top exec who engaged in years of demeaning sexual misconduct; Tesla's union-busting; and Facebook's years and years of depraved fuckery (a former Facebook recruiter told the Times that the rate of job-offer acceptances has fallen by 40%!).

Two years ago, I wrote that the tech industry's scarcest resource was tech workers, who are increasingly disillusioned with their employers, and who no longer see themselves as possible CEOs of their own startups, thanks to the monopoly tactics and market concentration that have created a "kill zone" around tech that preclude the possibility of unseating the Big Tech companies with your scrappy startup.

Tech companies can hire new cafeteria workers and gig economy drivers, but talented software engineers, security researchers, and mathematicians are in short supply. They have incredibly leverage over the Big Tech companies, and, as they start to build solidarity with their users and more easily replaced co-workers, they have it within their power to bring Big Tech to its knees.

“It felt like in my freshman year Google, Palantir and Facebook were these shiny places everyone wanted to be. It was like, ‘Wow, you work at Facebook. You must be really smart,’” said Ms. Dogru, 23. “Now if a classmate tells me they’re joining Palantir or Facebook, there’s an awkward gap where they feel like they have to justify themselves.”

Palantir, in particular, has drawn the ire of students at Stanford for providing services to U.S. Immigrations and Customs Enforcement (also known as ICE).

Last summer, a campus activist group, Students for the Liberation of All People, visited the company’s office, a 15-minute walk from campus, and hung a banner nearby that read: “Our software is so powerful it separates families.” Similar protests took place at the University of California, Berkeley, Brown and Yale, according to Recode. The protests, and the attitudes they reflected, were also covered in The Los Angeles Times.

Audrey Steinkamp, a 19-year-old sophomore at Yale, which sends about 10 percent of each graduating class into tech, said that taking a job in Silicon Valley is seen as “selling out,” no different from the economics majors going into consulting who are “lovingly and not-so-lovingly called ‘snakes.’”

‘Techlash’ Hits College Campuses [Emma Goldberg/New York Times]

(Image: No Tech For ICE)

Read the whole story
biocrusoe
901 days ago
reply
Lansing, MI
luizirber
904 days ago
reply
Davis, CA
Share this story
Delete
Next Page of Stories