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

=?UTF-8?B?VGhlIGJlc3QgY3VzdG9taXplZCBmcmVpZ2h0IHNvbHV0aW9uIGZyb20gRWFzZSBmcmVpZ2h0?=; =?UTF-8?B?VGhlIGJlc3QgY3VzdG9taXplZCBmcmVpZ2h0IHNvbHV0aW9uIGZyb20gRWFzZSBmcmVpZ2h0?=; =?UTF-8?B?RXhjbHVzaXZlIEVhc2VGcmVpZ2h0IEZyZWlnaHQgU2VydmljZXMgdGFpbG9yZWQganVzdCBmb3IgeW91?=; =?UTF-8?B?RXhjbHVzaXZlIEVhc2VGcmVpZ2h0IEZyZWlnaHQgU2VydmljZXMgdGFpbG9yZWQganVzdCBmb3IgeW91?=; =?UTF-8?B?RXhjbHVzaXZlIEVhc2VGcmVpZ2h0IEZyZWlnaHQgU2VydmljZXMgdGFpbG9yZWQganVzdCBmb3IgeW91?=; =?UTF-8?B?RXhjbHVzaXZlIEVhc2VGcmVpZ2h0IEZyZWlnaHQgU2VydmljZXMgdGFpbG9yZWQganVzdCBmb3IgeW91?=; =?UTF-8?B?RXhjbHVzaXZlIEVhc2VGcmVpZ2h0IEZyZWlnaHQgU2VydmljZXMgdGFpbG9yZWQganVzdCBmb3IgeW91?=; =?UTF-8?B?VGhlIGJlc3QgY3VzdG9taXplZCBmcmVpZ2h0IHNvbHV0aW9uIGZyb20gRWFzZSBmcmVpZ2h0?=; =?UTF-8?B?VGhlIGJlc3QgY3VzdG9taXplZCBmcmVpZ2h0IHNvbHV0aW9uIGZyb20gRWFzZSBmcmVpZ2h0?=; =?UTF-8?B?RXhjbHVzaXZlIEVhc2VGcmVpZ2h0IEZyZWlnaHQgU2VydmljZXMgdGFpbG9yZWQganVzdCBmb3IgeW91?=; =?UTF-8?B?VGhlIGJlc3QgY3VzdG9taXplZCBmcmVpZ2h0IHNvbHV0aW9uIGZyb20gRWFzZSBmcmVpZ2h0?=; =?UTF-8?B?VGhlIGJlc3QgY3VzdG9taXplZCBmcmVpZ2h0IHNvbHV0aW9uIGZyb20gRWFzZSBmcmVpZ2h0?=; =?UTF-8?B?RXhjbHVzaXZlIEVhc2VGcmVpZ2h0IEZyZWlnaHQgU2VydmljZXMgdGFpbG9yZWQganVzdCBmb3IgeW91?=; =?UTF-8?B?RXhjbHVzaXZlIEVhc2VGcmVpZ2h0IEZyZWlnaHQgU2VydmljZXMgdGFpbG9yZWQganVzdCBmb3IgeW91?=; =?UTF-8?B?RXhjbHVzaXZlIEVhc2VGcmVpZ2h0IEZyZWlnaHQgU2VydmljZXMgdGFpbG9yZWQganVzdCBmb3IgeW91?=; =?UTF-8?B?VGhlIGJlc3QgY3VzdG9taXplZCBmcmVpZ2h0IHNvbHV0aW9uIGZyb20gRWFzZSBmcmVpZ2h0?=; =?UTF-8?B?VGhlIGJlc3QgY3VzdG9taXplZCBmcmVpZ2h0IHNvbHV0aW9uIGZyb20gRWFzZSBmcmVpZ2h0?=; =?UTF-8?B?RXhjbHVzaXZlIEVhc2VGcmVpZ2h0IEZyZWlnaHQgU2VydmljZXMgdGFpbG9yZWQganVzdCBmb3IgeW91?=; =?UTF-8?B?VGhlIGJlc3QgY3VzdG9taXplZCBmcmVpZ2h0IHNvbHV0aW9uIGZyb20gRWFzZSBmcmVpZ2h0?=; =?UTF-8?B?VGhlIGJlc3QgY3VzdG9taXplZCBmcmVpZ2h0IHNvbHV0aW9uIGZyb20gRWFzZSBmcmVpZ2h0?=; =?UTF-8?B?RXhjbHVzaXZlIEVhc2VGcmVpZ2h0IEZyZWlnaHQgU2VydmljZXMgdGFpbG9yZWQganVzdCBmb3IgeW91?=; =?UTF-8?B?VGhlIGJlc3QgY3VzdG9taXplZCBmcmVpZ2h0IHNvbHV0aW9uIGZyb20gRWFzZSBmcmVpZ2h0?=; =?UTF-8?B?RXhjbHVzaXZlIEVhc2VGcmVpZ2h0IEZyZWlnaHQgU2VydmljZXMgdGFpbG9yZWQganVzdCBmb3IgeW91?=; =?UTF-8?B?RXhjbHVzaXZlIEVhc2VGcmVpZ2h0IEZyZWlnaHQgU2VydmljZXMgdGFpbG9yZWQganVzdCBmb3IgeW91?=; =?UTF-8?B?VGhlIGJlc3QgY3VzdG9taXplZCBmcmVpZ2h0IHNvbHV0aW9uIGZyb20gRWFzZSBmcmVpZ2h0?=; =?UTF-8?B?VGhlIGJlc3QgY3VzdG9taXplZCBmcmVpZ2h0IHNvbHV0aW9uIGZyb20gRWFzZSBmcmVpZ2h0?=; =?UTF-8?B?VGhlIGJlc3QgY3VzdG9taXplZCBmcmVpZ2h0IHNvbHV0aW9uIGZyb20gRWFzZSBmcmVpZ2h0?=; =?UTF-8?B?VGhlIGJlc3QgY3VzdG9taXplZCBmcmVpZ2h0IHNvbHV0aW9uIGZyb20gRWFzZSBmcmVpZ2h0?=; =?UTF-8?B?VGhlIGJlc3QgY3VzdG9taXplZCBmcmVpZ2h0IHNvbHV0aW9uIGZyb20gRWFzZSBmcmVpZ2h0?=; =?UTF-8?B?RXhjbHVzaXZlIEVhc2VGcmVpZ2h0IEZyZWlnaHQgU2VydmljZXMgdGFpbG9yZWQganVzdCBmb3IgeW91?=; =?UTF-8?B?RXhjbHVzaXZlIEVhc2VGcmVpZ2h0IEZyZWlnaHQgU2VydmljZXMgdGFpbG9yZWQganVzdCBmb3IgeW91?=; =?UTF-8?B?RXhjbHVzaXZlIEVhc2VGcmVpZ2h0IEZyZWlnaHQgU2VydmljZXMgdGFpbG9yZWQganVzdCBmb3IgeW91?=; =?UTF-8?B?VGhlIGJlc3QgY3VzdG9taXplZCBmcmVpZ2h0IHNvbHV0aW9uIGZyb20gRWFzZSBmcmVpZ2h0?=; =?UTF-8?B?VGhlIGJlc3QgY3VzdG9taXplZCBmcmVpZ2h0IHNvbHV0aW9uIGZyb20gRWFzZSBmcmVpZ2h0?=; =?UTF-8?B?VGhlIGJlc3QgY3VzdG9taXplZCBmcmVpZ2h0IHNvbHV0aW9uIGZyb20gRWFzZSBmcmVpZ2h0?=; 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

© 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

=?UTF-8?B?VGhlIGJlc3QgY3VzdG9taXplZCBmcmVpZ2h0IHNvbHV0aW9uIGZyb20gRWFzZSBmcmVpZ2h0?=

From: Tina <freight@...>

Date: Thu, 13 Jun 2024 13:42:27 +0800 (GMT+08:00)

CkhpCgoKCgpHcmVldGluZ3MgZnJvbSBFYXNlRnJlaWdodCEgSSdtIFRpbmEsIHRoZSBGcmVpZ2h0
IE1hbmFnZXIgYXQgRWFzZUZyZWlnaHQsIGFuIEFJIGZyZWlnaHQgYWdlbnQgbmV0d29yayBlc3Rh
Ymxpc2hlZCB1bmRlciBOZXRlYXNlLCBhIENoaW5lc2UgcHVibGljbHkgbGlzdGVkIGNvbXBhbnkg
aW4gMjAwMS4gV2l0aCAxNSB5ZWFycyBvZiBleHBlcmllbmNlIGluIHRoZSBpbXBvcnQgYW5kIGV4
cG9ydCBpbmR1c3RyeSwgd2UgaGF2ZSBnYXRoZXJlZCBvdmVyIDEwLDAwMCBDaGluZXNlIGZyZWln
aHQgYWdlbnRzIHRvIGVuc3VyZSBvdXIgY3VzdG9tZXJzIHJlY2VpdmUgZWZmaWNpZW50IGFuZCBj
b3N0LWVmZmVjdGl2ZSBmcmVpZ2h0IHNlcnZpY2VzLgoKCldlIHN1cHBvcnQgeW91OgoxLk11bHRp
cGxlIGZyZWlnaHQgcXVvdGF0aW9ucyB0byBlbnN1cmUgeW91IGNob29zZSB0aGUgYmVzdCBzb2x1
dGlvbi4KMi5UaGUgcXVvdGF0aW9uIGRldGFpbHMgYXJlIHNwZWNpZmljIGFuZCBjb21wcmVoZW5z
aXZlLCBwcm92aWRpbmcgYSBjbGVhciB1bmRlcnN0YW5kaW5nIG9mIGVhY2ggY29zdCBpbnZvbHZl
ZC4KMy5UcmFuc3BhcmVudCBwcmljaW5nLCBubyBtaWRkbGVtYW4gbWFya3Vwcy4KNC5PZmZlcmlu
ZyBhIHZhcmlldHkgb2Ygc2hpcHBpbmcgbWV0aG9kcyBmb3IgZmxleGlibGUgc2VsZWN0aW9uIGJh
c2VkIG9uIHNwZWNpZmljIG5lZWRzLgoKCgoKCldlIGJlbGlldmUgaW4gb3VyIGFiaWxpdHkgdG8g
cHJvdmlkZSB5b3Ugd2l0aCBjdXN0b21pemVkIHNlcnZpY2VzLCBlYXJuaW5nIHlvdXIgcmVjb2du
aXRpb24gdGhyb3VnaCBvdXIgcHJvZmVzc2lvbmFsaXNtLCBjYXBhYmlsaXRpZXMsIHNwZWVkLCBh
bmQgZWZmaWNpZW5jeSwgZW5zdXJpbmcgeW91IGVuam95IHRoZSBiZXN0IHNoaXBwaW5nIHNvbHV0
aW9ucy5QbGVhc2Uga2luZGx5IGNvbnRhY3QgdXMgbm93IGZvciBmcmVlIGNvbnRhaW5lciBzaGlw
cGluZyBxdW90ZSEKCgoKCkJlc3QgcmVnYXJkcywKVGluYSBYaWUKUHJvZHVjdCBPcGVyYXRpb25z
CgpFYXNlRnJlaWdodChOZXRFYXNlKQoKV2Vic2l0ZTpmcmVpZ2h0LmZhY3RvcnkuMTYzLmNvbQpF
LW1haWw6dGluYTAzQGVhc2VmcmllZ2h0aW5jLmNvbQoKCgpBZGRyZXNzOk5ldGVhc2XCreKAlDM5
OSBXYW5nc2hhbmcgUm9hZCwgQmluamlhbmcgRGlzdHJpY3QsIEhhbmd6aG91CgoKCgoKCgoKSWYg
eW91IGRvbid0IHdhbnQgdG8gcmVjZWl2ZSBvdXIgZW1haWxzLCB5b3UgY2FuIGVhc2lseSB1bnN1
YnNjcmliZSBoZXJlLgoKCg0KDQo=

=?UTF-8?B?RXhjbHVzaXZlIEVhc2VGcmVpZ2h0IEZyZWlnaHQgU2VydmljZXMgdGFpbG9yZWQganVzdCBmb3IgeW91?=

From: Tina <freight@...>

Date: Tue, 18 Jun 2024 19:45:16 +0800 (GMT+08:00)

CkhpCgoKCgpIaSxuaWNlIHRvIGNvbnRhY3QgeW91IGFnYWluISBJJ20gVGluYSwgZnJlaWdodCBt
YW5hZ2VyIG9mIEVhc2VmcmVpZ2h0LCBmcm9tIHRoZSBBSSBmcmVpZ2h0IGFnZW50IG5ldHdvcmsg
b2YgTmV0RWFzZSwgYSBsaXN0ZWQgY29tcGFueSBpbiBDaGluYS5XZSBhcmUgbm90IGp1c3QgeW91
ciBwb2ludCBvZiBjb250YWN0IHdpdGggZnJlaWdodCBhZ2VudHMsIGJ1dCB5b3VyIGdsb2JhbCB0
cmFkZSBwYXJ0bmVyLCBvZmZlcmluZyBpbnNpZ2h0cyBhbmQgYWR2aWNlIHRvIG5hdmlnYXRlIHRo
ZSBjb21wbGV4aXRpZXMgb2YgaW50ZXJuYXRpb25hbCBzaGlwcGluZy4KCgpXZSBzdXBwb3J0IHlv
dToKIDEuT2ZmZXJzIGRlZGljYXRlZCBvbmUtb24tb25lIGN1c3RvbWVyIHNlcnZpY2UgcmVwcmVz
ZW50YXRpdmVzIGFuZCBwcm9tcHQgcXVvdGF0aW9ucwogMi5PZmZlciB0YWlsb3JlZCBmcmVpZ2h0
IHNvbHV0aW9ucyB0byBtZWV0IHRoZSB1bmlxdWUgcmVxdWlyZW1lbnRzIG9mIG91ciBjbGllbnRz
LgogMy5Qcm92aWRpbmcgcmVsaWFibGUgZnJlaWdodCBwYXJ0bmVycyBhbmQgaGF2ZSBvZmZpY2Vz
IGluIG1ham9yIHBvcnRzIGZvciBvbi1zaXRlIGF1ZGl0cwoKCk91ciBjdXN0b21lciBzdXBwb3J0
IHRlYW0gaXMgYWx3YXlzIHJlYWR5IHRvIGFzc2lzdCB3aXRoIGFueSBpbnF1aXJpZXMsIGVuc3Vy
aW5nIGEgc21vb3RoIGFuZCB3b3JyeS1mcmVlIGV4cGVyaWVuY2UuUGxlYXNlIGtpbmRseSByZXBs
eSB0byBnZXQgdGhlIGxhdGVzdCBmcmVlIG9mIGNoYXJnZSBDaGluYSBzaGlwcGluZyBxdW90ZXMh
CgoKCgoKQmVzdCByZWdhcmRzLApUaW5hIFhpZQpQcm9kdWN0IE9wZXJhdGlvbnMKCkVhc2VGcmVp
Z2h0KE5ldEVhc2UpCgpXZWJzaXRlOmZyZWlnaHQuZmFjdG9yeS4xNjMuY29tCkUtbWFpbDp0aW5h
MDNAZWFzZWZyaWVnaHRpbmMuY29tCgoKCkFkZHJlc3M6TmV0ZWFzZcKt4oCUMzk5IFdhbmdzaGFu
ZyBSb2FkLCBCaW5qaWFuZyBEaXN0cmljdCwgSGFuZ3pob3UKCgoKCgoKCgpJZiB5b3UgZG9uJ3Qg
d2FudCB0byByZWNlaXZlIG91ciBlbWFpbHMsIHlvdSBjYW4gZWFzaWx5IHVuc3Vic2NyaWJlIGhl
cmUuCgoKCuWcqDIwMjQtMDYtMTPvvIxUaW5hIDxmcmVpZ2h0QGluZmluaXRlbG9naXN0aWNzZXJ2
aWNlcy5jb20+IOWGmemBkzotLS0tLeWOn+Wni+mCruS7ti0tLS0tCiDlj5Hku7bkurrvvJogVGlu
YSA8ZnJlaWdodEBpbmZpbml0ZWxvZ2lzdGljc2VydmljZXMuY29tPgog5Y+R5Lu25pe26Ze0OiAy
MDI05bm0MDbmnIgxM+aXpSDlkajlm5sKIOaUtuS7tuS6uu+8miBbY29tcHV0ZStsZWFybmluZ2Vy
MEBhY29va2Uub3JnXQog5Li76aKY77yaIFRoZSBiZXN0IGN1c3RvbWl6ZWQgZnJlaWdodCBzb2x1
dGlvbiBmcm9tIEVhc2UgZnJlaWdodAoKCkhpCgoKCgpHcmVldGluZ3MgZnJvbSBFYXNlRnJlaWdo
dCEgSSdtIFRpbmEsIHRoZSBGcmVpZ2h0IE1hbmFnZXIgYXQgRWFzZUZyZWlnaHQsIGFuIEFJIGZy
ZWlnaHQgYWdlbnQgbmV0d29yayBlc3RhYmxpc2hlZCB1bmRlciBOZXRlYXNlLCBhIENoaW5lc2Ug
cHVibGljbHkgbGlzdGVkIGNvbXBhbnkgaW4gMjAwMS4gV2l0aCAxNSB5ZWFycyBvZiBleHBlcmll
bmNlIGluIHRoZSBpbXBvcnQgYW5kIGV4cG9ydCBpbmR1c3RyeSwgd2UgaGF2ZSBnYXRoZXJlZCBv
dmVyIDEwLDAwMCBDaGluZXNlIGZyZWlnaHQgYWdlbnRzIHRvIGVuc3VyZSBvdXIgY3VzdG9tZXJz
IHJlY2VpdmUgZWZmaWNpZW50IGFuZCBjb3N0LWVmZmVjdGl2ZSBmcmVpZ2h0IHNlcnZpY2VzLgoK
CldlIHN1cHBvcnQgeW91OgogMS5NdWx0aXBsZSBmcmVpZ2h0IHF1b3RhdGlvbnMgdG8gZW5zdXJl
IHlvdSBjaG9vc2UgdGhlIGJlc3Qgc29sdXRpb24uCiAyLlRoZSBxdW90YXRpb24gZGV0YWlscyBh
cmUgc3BlY2lmaWMgYW5kIGNvbXByZWhlbnNpdmUsIHByb3ZpZGluZyBhIGNsZWFyIHVuZGVyc3Rh
bmRpbmcgb2YgZWFjaCBjb3N0IGludm9sdmVkLgogMy5UcmFuc3BhcmVudCBwcmljaW5nLCBubyBt
aWRkbGVtYW4gbWFya3Vwcy4KIDQuT2ZmZXJpbmcgYSB2YXJpZXR5IG9mIHNoaXBwaW5nIG1ldGhv
ZHMgZm9yIGZsZXhpYmxlIHNlbGVjdGlvbiBiYXNlZCBvbiBzcGVjaWZpYyBuZWVkcy4KCgoKCgpX
ZSBiZWxpZXZlIGluIG91ciBhYmlsaXR5IHRvIHByb3ZpZGUgeW91IHdpdGggY3VzdG9taXplZCBz
ZXJ2aWNlcywgZWFybmluZyB5b3VyIHJlY29nbml0aW9uIHRocm91Z2ggb3VyIHByb2Zlc3Npb25h
bGlzbSwgY2FwYWJpbGl0aWVzLCBzcGVlZCwgYW5kIGVmZmljaWVuY3ksIGVuc3VyaW5nIHlvdSBl
bmpveSB0aGUgYmVzdCBzaGlwcGluZyBzb2x1dGlvbnMuUGxlYXNlIGtpbmRseSBjb250YWN0IHVz
IG5vdyBmb3IgZnJlZSBjb250YWluZXIgc2hpcHBpbmcgcXVvdGUhCgoKCgpCZXN0IHJlZ2FyZHMs
ClRpbmEgWGllClByb2R1Y3QgT3BlcmF0aW9ucwoKRWFzZUZyZWlnaHQoTmV0RWFzZSkKCldlYnNp
dGU6ZnJlaWdodC5mYWN0b3J5LjE2My5jb20KRS1tYWlsOnRpbmEwM0BlYXNlZnJpZWdodGluYy5j
b20KCgoKQWRkcmVzczpOZXRlYXNlwq3igJQzOTkgV2FuZ3NoYW5nIFJvYWQsIEJpbmppYW5nIERp
c3RyaWN0LCBIYW5nemhvdQoKCgoKCgoKCklmIHlvdSBkb24ndCB3YW50IHRvIHJlY2VpdmUgb3Vy
IGVtYWlscywgeW91IGNhbiBlYXNpbHkgdW5zdWJzY3JpYmUgaGVyZS4KCgoKCg0KDQo=

=?UTF-8?B?VGhlIGJlc3QgY3VzdG9taXplZCBmcmVpZ2h0IHNvbHV0aW9uIGZyb20gRWFzZSBmcmVpZ2h0?=

From: Tina <freight@...>

Date: Thu, 18 Jul 2024 11:40:18 +0800 (GMT+08:00)

CkhpCgoKCgpHcmVldGluZ3MgZnJvbSBFYXNlRnJlaWdodCEgSSdtIFRpbmEsIHRoZSBGcmVpZ2h0
IE1hbmFnZXIgYXQgRWFzZUZyZWlnaHQsIGFuIEFJIGZyZWlnaHQgYWdlbnQgbmV0d29yayBlc3Rh
Ymxpc2hlZCB1bmRlciBOZXRlYXNlLCBhIENoaW5lc2UgcHVibGljbHkgbGlzdGVkIGNvbXBhbnkg
aW4gMjAwMS4gV2l0aCAxNSB5ZWFycyBvZiBleHBlcmllbmNlIGluIHRoZSBpbXBvcnQgYW5kIGV4
cG9ydCBpbmR1c3RyeSwgd2UgaGF2ZSBnYXRoZXJlZCBvdmVyIDEwLDAwMCBDaGluZXNlIGZyZWln
aHQgYWdlbnRzIHRvIGVuc3VyZSBvdXIgY3VzdG9tZXJzIHJlY2VpdmUgZWZmaWNpZW50IGFuZCBj
b3N0LWVmZmVjdGl2ZSBmcmVpZ2h0IHNlcnZpY2VzLgoKCldlIHN1cHBvcnQgeW91OgogMS5NdWx0
aXBsZSBmcmVpZ2h0IHF1b3RhdGlvbnMgdG8gZW5zdXJlIHlvdSBjaG9vc2UgdGhlIGJlc3Qgc29s
dXRpb24uCiAyLlRoZSBxdW90YXRpb24gZGV0YWlscyBhcmUgc3BlY2lmaWMgYW5kIGNvbXByZWhl
bnNpdmUsIHByb3ZpZGluZyBhIGNsZWFyIHVuZGVyc3RhbmRpbmcgb2YgZWFjaCBjb3N0IGludm9s
dmVkLgogMy5UcmFuc3BhcmVudCBwcmljaW5nLCBubyBtaWRkbGVtYW4gbWFya3Vwcy4KIDQuT2Zm
ZXJpbmcgYSB2YXJpZXR5IG9mIHNoaXBwaW5nIG1ldGhvZHMgZm9yIGZsZXhpYmxlIHNlbGVjdGlv
biBiYXNlZCBvbiBzcGVjaWZpYyBuZWVkcy4KCgoKCgpXZSBiZWxpZXZlIGluIG91ciBhYmlsaXR5
IHRvIHByb3ZpZGUgeW91IHdpdGggY3VzdG9taXplZCBzZXJ2aWNlcywgZWFybmluZyB5b3VyIHJl
Y29nbml0aW9uIHRocm91Z2ggb3VyIHByb2Zlc3Npb25hbGlzbSwgY2FwYWJpbGl0aWVzLCBzcGVl
ZCwgYW5kIGVmZmljaWVuY3ksIGVuc3VyaW5nIHlvdSBlbmpveSB0aGUgYmVzdCBzaGlwcGluZyBz
b2x1dGlvbnMuUGxlYXNlIGtpbmRseSBjb250YWN0IHVzIG5vdyBmb3IgZnJlZSBjb250YWluZXIg
c2hpcHBpbmcgcXVvdGUhCgoKCgpCZXN0IHJlZ2FyZHMsVGluYSBYaWUKQ3VzdG9tZXIgUmVwcmVz
ZW50YXRpdmUKCkVhc2VGcmVpZ2h0IChTdWJzaWRpYXJ5IG9mIE5ldEVhc2UpCgpXZWJzaXRlOiBl
YXNlLWZyZWlnaHQuY29tCkUtbWFpbDogdGluYUBlYXNlZnJlaWdodGluYy5jb20KCgoKQWRkcmVz
czogTmV0ZWFzZcKt4oCUMzk5IFdhbmdzaGFuZyBSb2FkLCBCaW5qaWFuZyBEaXN0cmljdCwgSGFu
Z3pob3UKCgoKCgoKCgoKCgoKCgrlnKgyMDI0LTA2LTEz77yMVGluYSA8ZnJlaWdodEBpbmZpbml0
ZWxvZ2lzdGljc2VydmljZXMuY29tPiDlhpnpgZM6LS0tLS3ljp/lp4vpgq7ku7YtLS0tLQog5Y+R
5Lu25Lq677yaIFRpbmEgPGZyZWlnaHRAaW5maW5pdGVsb2dpc3RpY3NlcnZpY2VzLmNvbT4KIOWP
keS7tuaXtumXtDogMjAyNOW5tDA25pyIMTPml6Ug5ZGo5ZubCiDmlLbku7bkurrvvJogW2NvbXB1
dGUrbGVhcm5pbmdlcjBAYWNvb2tlLm9yZ10KIOS4u+mimO+8miBUaGUgYmVzdCBjdXN0b21pemVk
IGZyZWlnaHQgc29sdXRpb24gZnJvbSBFYXNlIGZyZWlnaHQKCgpIaQoKCgoKR3JlZXRpbmdzIGZy
b20gRWFzZUZyZWlnaHQhIEknbSBUaW5hLCB0aGUgRnJlaWdodCBNYW5hZ2VyIGF0IEVhc2VGcmVp
Z2h0LCBhbiBBSSBmcmVpZ2h0IGFnZW50IG5ldHdvcmsgZXN0YWJsaXNoZWQgdW5kZXIgTmV0ZWFz
ZSwgYSBDaGluZXNlIHB1YmxpY2x5IGxpc3RlZCBjb21wYW55IGluIDIwMDEuIFdpdGggMTUgeWVh
cnMgb2YgZXhwZXJpZW5jZSBpbiB0aGUgaW1wb3J0IGFuZCBleHBvcnQgaW5kdXN0cnksIHdlIGhh
dmUgZ2F0aGVyZWQgb3ZlciAxMCwwMDAgQ2hpbmVzZSBmcmVpZ2h0IGFnZW50cyB0byBlbnN1cmUg
b3VyIGN1c3RvbWVycyByZWNlaXZlIGVmZmljaWVudCBhbmQgY29zdC1lZmZlY3RpdmUgZnJlaWdo
dCBzZXJ2aWNlcy4KCgpXZSBzdXBwb3J0IHlvdToKIDEuTXVsdGlwbGUgZnJlaWdodCBxdW90YXRp
b25zIHRvIGVuc3VyZSB5b3UgY2hvb3NlIHRoZSBiZXN0IHNvbHV0aW9uLgogMi5UaGUgcXVvdGF0
aW9uIGRldGFpbHMgYXJlIHNwZWNpZmljIGFuZCBjb21wcmVoZW5zaXZlLCBwcm92aWRpbmcgYSBj
bGVhciB1bmRlcnN0YW5kaW5nIG9mIGVhY2ggY29zdCBpbnZvbHZlZC4KIDMuVHJhbnNwYXJlbnQg
cHJpY2luZywgbm8gbWlkZGxlbWFuIG1hcmt1cHMuCiA0Lk9mZmVyaW5nIGEgdmFyaWV0eSBvZiBz
aGlwcGluZyBtZXRob2RzIGZvciBmbGV4aWJsZSBzZWxlY3Rpb24gYmFzZWQgb24gc3BlY2lmaWMg
bmVlZHMuCgoKCgoKV2UgYmVsaWV2ZSBpbiBvdXIgYWJpbGl0eSB0byBwcm92aWRlIHlvdSB3aXRo
IGN1c3RvbWl6ZWQgc2VydmljZXMsIGVhcm5pbmcgeW91ciByZWNvZ25pdGlvbiB0aHJvdWdoIG91
ciBwcm9mZXNzaW9uYWxpc20sIGNhcGFiaWxpdGllcywgc3BlZWQsIGFuZCBlZmZpY2llbmN5LCBl
bnN1cmluZyB5b3UgZW5qb3kgdGhlIGJlc3Qgc2hpcHBpbmcgc29sdXRpb25zLlBsZWFzZSBraW5k
bHkgY29udGFjdCB1cyBub3cgZm9yIGZyZWUgY29udGFpbmVyIHNoaXBwaW5nIHF1b3RlIQoKCgoK
QmVzdCByZWdhcmRzLApUaW5hIFhpZQpQcm9kdWN0IE9wZXJhdGlvbnMKCkVhc2VGcmVpZ2h0KE5l
dEVhc2UpCgpXZWJzaXRlOmZyZWlnaHQuZmFjdG9yeS4xNjMuY29tCkUtbWFpbDp0aW5hMDNAZWFz
ZWZyaWVnaHRpbmMuY29tCgoKCkFkZHJlc3M6TmV0ZWFzZcKt4oCUMzk5IFdhbmdzaGFuZyBSb2Fk
LCBCaW5qaWFuZyBEaXN0cmljdCwgSGFuZ3pob3UKCgoKCgoKCgpJZiB5b3UgZG9uJ3Qgd2FudCB0
byByZWNlaXZlIG91ciBlbWFpbHMsIHlvdSBjYW4gZWFzaWx5IHVuc3Vic2NyaWJlIGhlcmUuCgoK
CgoNCg0K

Comment on this post