Andrew Cooke | Contents | Latest | RSS | Previous | Next

C[omp]ute

Welcome to my blog, which was once a mailing list of the same name and is still generated by mail. Please reply via the "comment" links.

Always interested in offers/projects/new ideas. Eclectic experience in fields like: numerical computing; Python web; Java enterprise; functional languages; GPGPU; SQL databases; etc. Based in Santiago, Chile; telecommute worldwide. CV; email.

Personal Projects

Choochoo Training Diary

Last 100 entries

Surprise Paradox; [Books] Good Author List; [Computing] Efficient queries with grouping in Postgres; [Computing] Automatic Wake (Linux); [Computing] AWS CDK Aspects in Go; [Bike] Adidas Gravel Shoes; [Computing, Horror] Biological Chips; [Books] Weird Lit Recs; [Covid] Extended SIR Models; [Art] York-based Printmaker; [Physics] Quantum Transitions are not Instantaneous; [Computing] AI and Drum Machines; [Computing] Probabilities, Stopping Times, Martingales; bpftrace Intro Article; [Computing] Starlab Systems - Linux Laptops; [Computing] Extended Berkeley Packet Filter; [Green] Mainspring Linear Generator; Better Approach; Rummikub Solver; Chilean Poetry; Felicitations - Empowerment Grant; [Bike] Fixing Spyre Brakes (That Need Constant Adjustment); [Computing, Music] Raspberry Pi Media (Audio) Streamer; [Computing] Amazing Hack To Embed DSL In Python; [Bike] Ruta Del Condor (El Alfalfal); [Bike] Estimating Power On Climbs; [Computing] Applying Azure B2C Authentication To Function Apps; [Bike] Gearing On The Back Of An Envelope; [Computing] Okular and Postscript in OpenSuse; There's a fix!; [Computing] Fail2Ban on OpenSuse Leap 15.3 (NFTables); [Cycling, Computing] Power Calculation and Brakes; [Hardware, Computing] Amazing Pockit Computer; Bullying; How I Am - 3 Years Post Accident, 8+ Years With MS; [USA Politics] In America's Uncivil War Republicans Are The Aggressors; [Programming] Selenium and Python; Better Walking Data; [Bike] How Fast Before Walking More Efficient Than Cycling?; [COVID] Coronavirus And Cycling; [Programming] Docker on OpenSuse; Cadence v Speed; [Bike] Gearing For Real Cyclists; [Programming] React plotting - visx; [Programming] React Leaflet; AliExpress Independent Sellers; Applebaum - Twilight of Democracy; [Politics] Back + US Elections; [Programming,Exercise] Simple Timer Script; [News] 2019: The year revolt went global; [Politics] The world's most-surveilled cities; [Bike] Hope Freehub; [Restaurant] Mama Chau's (Chinese, Providencia); [Politics] Brexit Podcast; [Diary] Pneumonia; [Politics] Britain's Reichstag Fire moment; install cairo; [Programming] GCC Sanitizer Flags; [GPU, Programming] Per-Thread Program Counters; My Bike Accident - Looking Back One Year; [Python] Geographic heights are incredibly easy!; [Cooking] Cookie Recipe; Efficient, Simple, Directed Maximisation of Noisy Function; And for argparse; Bash Completion in Python; [Computing] Configuring Github Jekyll Locally; [Maths, Link] The Napkin Project; You can Masquerade in Firewalld; [Bike] Servicing Budget (Spring) Forks; [Crypto] CIA Internet Comms Failure; [Python] Cute Rate Limiting API; [Causality] Judea Pearl Lecture; [Security, Computing] Chinese Hardware Hack Of Supermicro Boards; SQLAlchemy Joined Table Inheritance and Delete Cascade; [Translation] The Club; [Computing] Super Potato Bruh; [Computing] Extending Jupyter; Further HRM Details; [Computing, Bike] Activities in ch2; [Books, Link] Modern Japanese Lit; What ended up there; [Link, Book] Logic Book; Update - Garmin Express / Connect; Garmin Forerunner 35 v 230; [Link, Politics, Internet] Government Trolls; [Link, Politics] Why identity politics benefits the right more than the left; SSH Forwarding; A Specification For Repeating Events; A Fight for the Soul of Science; [Science, Book, Link] Lost In Math; OpenSuse Leap 15 Network Fixes; Update; [Book] Galileo's Middle Finger; [Bike] Chinese Carbon Rims; [Bike] Servicing Shimano XT Front Hub HB-M8010; [Bike] Aliexpress Cycling Tops; [Computing] Change to ssh handling of multiple identities?; [Bike] Endura Hummvee Lite II; [Computing] Marble Based Logic; [Link, Politics] Sanity Check For Nuclear Launch; [Link, Science] Entropy and Life

© 2006-2017 Andrew Cooke (site) / post authors (content).

Learning Erlang

From: "andrew cooke" <andrew@...>

Date: Sun, 15 Apr 2007 12:18:37 -0400 (CLT)

I have been playing around with Erlang this weekend.

While I haven't yet used the threading stuff I have written a parser
combinator library (although Erlang does include some kind of yacc-like
tool).

Some random observations:

- Apart from the message sending and infrastructure, it's a very simple,
pure functional language.  There's no mutable state (no Monads, no mutable
references) except for (i) global process namespace (thanks to Kragen for
pointing this one out) and (ii) an integrated "object" database.

- The hot code replacement stuff makes working in the shell a pain (I
couldn't work out how to force recompiled code to load!), so the best
thing to do is use the emacs mode fully (which includes an embedded shell
and forces reload on recompile).

- Dependencies aren't recompiled automatically.  There is a make-like
tool, but I haven't used it and don't know how well it's integrated with
the emacs edit/compile/run cycle.

- Error messages could be a little less cryptic.  Syntax errors in
particular give you just the line number to work with.

- For a functional language the handling of higher order functions is very
clumsy.  While functions can be invoked on arguments via the usual syntax:
  foo(...)
  module:foo(...)
they cannot be referred to as such:
  lists:map(foo, [...]) % error
  lists:map(module:foo, [...]) % error
instead you need to use a {module, name} tuple;
  lists:map({module, foo}, [...])
And if an expression evaluates to a function it cannot be applied
directly.  Instead, the whole thing must be enclosed in parens:
  hof(...)(...) % error
  (hof(...))(...)

- In general the docs are good.  However I couldn't find anything that
described inline operators (++, --, arithmetic, others?).  Partly because
these are difficult to search for...

- For some reason (strange compatibility with shell stadards) the regexp
(which is much more limited than perl5) will not match " *" against the
empty string(!).

- There are a couple of language extensions that seem a bit "ad-hoc" and
poorly integrated.  One is support for records (named access to tuple
fields).  The other is a kind of ADT (called "behaviours").  Don't have
more specific criticism of these yet as I haven't used them.

Andrew

Datalog Parser in Erlang

From: "andrew cooke" <andrew@...>

Date: Sun, 15 Apr 2007 15:18:23 -0400 (CLT)

It's probably not complete (although I'm not sure there is a formal def
for Datalog, it doesn't support extra conditions like equality and
certainly doesn't support negation), but here's an example of the parser
output:

Eshell V5.5.4  (abort with ^G)
1> parse_datalog:rule("forefather(X, Y) :- forefather(X, Z), father(Z, Y)").
{rule,{predicate,{name,"forefather"},[{var,"X"},{var,"Y"}]},
      [{predicate,{name,"father"},[{var,"Z"},{var,"Y"}]},
       {predicate,{name,"forefather"},[{var,"X"},{var,"Z"}]}]}
2> parse_datalog:fact("father(\"Rodney\", \"Andrew\")").
{fact,{name,"father"},[{name,"Rodney"},{name,"Andrew"}]}


And here's the code (just the top level, not the libraries):


-module(parse_datalog).

% testing only(?)
-export([space/0, space/1, list/1, list_tail/1, args/1]).

-export([var/0, var/1, name/0, name/1, fact/1, rule/1]).

-import(parse, [empty/0, label/2, function/2, either/2, cons/2, drop/1,
                star/1, both/3, append/1, all/1, seq/1, result/2, export/3,
                parser_lift/1, eos_/0]).
-import(parse_string, [string/1, regexp/1, quote/2]).


var() -> label(var, regexp("[A-Z][0-9a-zA-Z_]*")).
name() ->
    label(name, either(regexp("[a-z][0-9a-zA-Z_]*"), quote("\\", "\""))).

% erlang lib fails to match empty string with " *"
space() -> drop(either(regexp(" *"), empty())).
space(Parser) -> append([space(), Parser, space()]).

open() -> drop(space(string("("))).
close() -> drop(space(string(")"))).
entail() -> drop(space(string(":-"))).
comma() -> drop(space(string(","))).

list_tail(Parser) -> seq([comma(), Parser]).
list(Parser) -> cons(Parser, star(list_tail(Parser))).

% ouch - list reversal needed here :o(
args(Parser) ->
    (parser_lift({lists, reverse}))
      (append([open(), list(Parser), close()])).

fact() -> both(fact, name(), args(name())).
predicate() -> both(predicate, name(), args(either(name(), var()))).
rule() -> both(rule, predicate(), append([entail(), list(predicate())])).

complete(Parser, Stream) ->
    export(seq([Parser, space(), eos_()]), Stream, fail).

var(Stream) -> export(var(), Stream, fail).
name(Stream) -> export(name(), Stream, fail).

fact(Stream) -> complete(fact(), Stream).
rule(Stream) -> complete(rule(), Stream).

Re: Learning Erlang

From: "Joe Armstrong" <joearms@...>

Date: Mon, 16 Apr 2007 09:43:31 +0200

- The hot code replacement stuff makes working in the shell a pain (I
couldn't work out how to force recompiled code to load!), so the best
thing to do is use the emacs mode fully (which includes an embedded shell
and forces reload on recompile).

> c(foo).
{ok, foo}

foo is loaded and ready to run - you don't have to do anything
(well you might have to if foo was spawned by large number of parallel
process and
made funny tail calls that we can't handle - the point is that this
should just work
even when you have very large systems wih loads of different modules
involved

- Dependencies aren't recompiled automatically.  There is a make-like
tool, but I haven't used it and don't know how well it's integrated with
the emacs edit/compile/run cycle.

Source code dependencies must be handled with something "external"
- I just use make - run-time dependencies are handled automatically.
ie if foo calls bar and you reload bar then all the calls to bar from
foo will be
changed to the new versions without you having to do anything to foo.


- For a functional language the handling of higher order functions is very
clumsy.  While functions can be invoked on arguments via the usual syntax:
  foo(...)
  module:foo(...)
they cannot be referred to as such:
  lists:map(foo, [...]) % error
  lists:map(module:foo, [...]) % error
instead you need to use a {module, name} tuple;
  lists:map({module, foo}, [...])
And if an expression evaluates to a function it cannot be applied
directly.  Instead, the whole thing must be enclosed in parens:
  hof(...)(...) % error
  (hof(...))(...)

   You need a fun keyword :-)


   lists:map(fun foo/2, [...])  %% ok a reference to the local function foo

   lists:map(fun remote:var/4, ...)   %% a remote reference

Records are poorly integrated - we always said we know this sucks but
can anybody come
up with a better syntax - nobody has (well not quite true, there is a
better syntax but
compiling it is tricky)

Behaviours are much more than ASTs - think of them as HOFS working with parallel
processes to provide things like fault-tolerance or scalability

Erlang is not a functional language with "added concurrency" it's the other
way around.

The important thing is that Erlang is a concurrent language where you happen
to do things in a functional language.

It was not designed for  an edit/compile/run cycle.

it was designed for startOnce/evovle ....

ie for never-stop evolving systems ( we have some systems that have
run for six years
and evolved thought dozens of major upgrades)

The "threading stuff" is what it's all about - this what makes Erlang
differ from
most other languages - Because our threading stuff does not mutate state we can
run on a multicore - with no locks and no sharing - so when the 100+ core CPUs
come our very slow and pure code will run much faster than all
these silly things that mutate state and crash each other quickly.

Cheers

/Joe Armstrong

Thanks for comment and apologies for ignoring/formatting

From: "andrew cooke" <andrew@...>

Date: Tue, 17 Apr 2007 11:52:43 -0400 (CLT)

Hi,

I just saw that you replied to something I posted on my blog about Erlang.
 Thank-you for taking the time to do so.  I was reading the page because I
was going to add an update myself, having found the "fun" keyword.

Sorry for the poor formatting and apparent attribution to me, not you.  At
some point (maybe this weekend) I will fix the code (just some bash
scripts that put emails into web pages) and regenerate the site.  It's not
a popular site - I think you are my second reply ever - and lacks a
certain polish, I'm afraid.

Also sorry if my comments came across as a criticism of Erlang without
mentioning the importance of concurrency.  The reason I am using the
language is because I want the concurrency and I can't see how to do it
reasonably with any other approach.  However I am just starting out so
thought it better to get a grip on the base language first.

Incidentally, I realise I am guilty of "not using the language as it was
designed to be used", but if I could add one thing it would be, at the
moment, not a nicer syntax for records, but currying.  That and not (even)
needing "fun" for function references... :o)

Cheers,
Andrew

Thanks for comment and apologies for ignoring/formatting

From: "andrew cooke" <andrew@...>

Date: Wed, 18 Apr 2007 09:14:33 -0400 (CLT)

Hi,

I just saw that you replied to something I posted on my blog about Erlang.
 Thank-you for taking the time to do so.  I was reading the page because I
was going to add an update myself, having found the "fun" keyword.

Sorry for the poor formatting and apparent attribution to me, not you.  At
some point (maybe this weekend) I will fix the code (just some bash
scripts that put emails into web pages) and regenerate the site.  It's not
a popular site - I think you are my second reply ever - and lacks a
certain polish, I'm afraid.

Also sorry if my comments came across as a criticism of Erlang without
mentioning the importance of concurrency.  The reason I am using the
language is because I want the concurrency and I can't see how to do it
reasonably with any other approach.  However I am just starting out so
thought it better to get a grip on the base language first.

Incidentally, I realise I am guilty of "not using the language as it was
designed to be used", but if I could add one thing it would be, at the
moment, not a nicer syntax for records, but currying.  That and not (even)
needing "fun" for function references... :o)

Cheers,
Andrew

Comment on this post