Jim Cheung

Sunday, June 04, 2017

I can't use alt key combos in netbeans under os x

found this stack overflow answer useful:

download this keyboard layout for us english

copy it to ~/Library/Keyboard\ Layouts/

go keyboard system preference panel, under input sources tab, click + to add the layout.

however, alt key combos fires they key twice, so still useless.

zpresent.el is an emacs package for presentation

just create an org file and m-x zpresent will start the presentation.

(setq mode-line-format nil) to hide mode line

to do it globally, use (setq-default mode-line-format nil)

I like erlang/elixir's pattern matching (comes from prolog, but prolog is two-way unification)

I want to use them more when I do clojure, I'm ready to use core.match and defun heavily.

also studying clara-rules: Forward-chaining rules in Clojure.

reading Reactive Programming with RxJava, slowly.

rx started at microsoft, then those people went to netflix, facebook etc. rxjava was created by netflix.

the core of rxjava is Observable, and Observable is about pushing.

in contrast to Iterable (pulls)

I like the explaination they gave on performance of nginx vs tomcat:

event loop has performance advantage because hot threads, tomcat starts new thread on new request, which is cold and of course it takes time to warm up.

Friday, June 16, 2017

SREcon17 Asia/Australia has some pretty good topics.

I watched InnoDB to MyRocks Migration in Main MySQL Database at Facebook, learned more about MySQL internals.

I want to try MyRocks simply because it saves more space than compressed InnoDB, which is the biggest pain point on a $5 digitalocean droplet.

this guide teaches you how to build it under ubuntu and migrate from innodb to myrocks

further reading: MyRocks: A space- and write-optimized MySQL database

reading Understanding ECMAScript 6: The Definitive Guide for JavaScript Developers, quite good.

I finally understand yield after reading this book:

yield stops the function right after it's being called, so this code

let a = yield 1;

the assignment will be executed on the next yield, but you can call the next yield with next(5), so when the assignment happens, a will be 5

anyways, es6 is very different from the javascript I'd learned before (I read quite a few javascript books). but it's better, like kotlin to java.

I watched Anthony Marcar - Clojure At Scale @WalmartLabs, he mentioned component helps them to scale.

then I watched Stuart Sierra - Components Just Enough Structure

so in clojure, there're few libraries to help you maintain states:

there're tons of discussions on component and mount:

I picked mount, I don't mind to use global defs, I just don't want to pass extra parameters around.

Recently I've been using a lot mount and core.match, finally I can produce some clojure codes which is easy to read and easy to maintain.

read Reducers, transducers and core.async in Clojure, I've been working on some ETL tasks

so I watched Simplifying ETL with Clojure and Datomic - Stuart Halloway

I think core.async and transducers are good fit for etl jobs, I'm working on porting some of tasks to channels

I also found a good resources on core.async: Eric Normand's Core.async Patterns, and codes on lispcast/core-async-patterns.

some good reads:

Saturday, June 17, 2017

got my vortex core keyboard, it's very nice looking

however, 47 keys are not easy to use. the biggest problem with it is how to make pn and left space less wasted.

even with the latest firmware, you can only switch pn OR fn, not both.

I tried swapped pn and fn, and set left space as alt, but didn't work well.

I finally mapped left space as fn, and left pn being wasted.

the final version is like this:

| new key    | current key       | output   |
| row 1      |                   |          |
| fn + esc   | fn1 + shift + esc | ~        |
| fn + q     | fn1 + shift + tab | !        |
| fn + w     | right shift       | up       |
| fn + e     | fn1 + shift + s   | #        |
| fn + r     | fn1 + shift + d   | $        |
| fn + y     | fn1 + shift + g   | ^        |
| fn + u     | fn1 + shift + h   | &        |
| fn + i     | fn1 + shift + j   | *        |
| fn + o     | fn1 + shift + k   | (        |
| fn + p     | fn1 + shift + l   | )        |
| fn + del   | fn1 + m           | [        |
| fn + bs    | fn1 + ,           | ]        |
| row 2      |                   |          |
| fn + a     | right alt         | left     |
| fn + s     | menu              | down     |
| fn + d     | right ctrl        | right    |
| fn + f     | fn1 + shift + f   | %        |
| fn + j     | fn1 + ;           | -        |
| fn + k     | fn1 + n           | /        |
| fn + l     | fn1 + enter       | =        |
| fn + ;     | fn1 + b           | '        |
| fn + enter | fn1 + .           | \        |
| row 3      |                   |          |
| fn + x     | fn1 + shift + a   | @        |
| fn + c     | fn + u            | pageup   |
| fn + v     | fn + o            | pagedown |
| row 4      |                   |          |
| left space | fn                | fn       |


I also setup dedicated layer for numbers and arrows.

Wednesday, June 21, 2017

reading MongoDB in Action, Second Edition

there're lots of bad comments on mongodb, however, after read two parts of this book, I found mongodb is a really powerful tool.

I can also see they've been improved quite a lot in recent verisons.

there're few ways to do authentication for aws api gateway calls mentioned in their documentation

however, actually only two are useful for client side javascript:

if you're willing to do a registration flow on cognito, it's the best way. cognito issues token and verify it for you.

otherwise, you'll need to use a lambda to verify tokens issued by your backend or something like auth0 (auth0 can verify tokens for you as well)

some notes from implementing the lambda:

also, for lambda using proxy integration, you also need to follow their output format

about aws lambda to connect database, connection pool is a problem, because there's no connection pool.

lambda should be stateless, it can die and restart anytime. so connection pool doesn't make sense to it.

the best way is use a rest api wrapper, but usually it will be difficult to find library to do connection this way.

mongodb article uses a cached connection declared outside of handler function.

which is the way I've been using now: use atom to hold the connection state.

I think for aws dynamodb they're using rest api endpoints. so no this problem.

about dynamodb, some notes too:

the query is quite limited and it requires more effort on application side.

for me, serverless is still quite painful to work with: too many small pieces, hard to test, it scales well (means you don't want it connecting to your existing infrastrucure/applications, unless your application scales that well too)

Saturday, June 24, 2017

I'm wondering why dynamodb only said they're doing partitioning, instead of sharding.

I did some search, partitioning is a more generic term, horizontal partitioning is one of partitioning type, and sharding is basically horizontal partitioning except:

Horizontal partitioning can be done both within a single server and across multiple servers, the latter often being referred to as sharding.

still didn't get the answer, dynamodb obviously is sharding, but why only term partitioning is used?

I'm looking for a better way to handle exceptions in clojure, I found MichaelDrogalis/dire: Erlang-style supervisor error handling for Clojure useful.

let's take a look at its self correcting example:

(ns mytask
  (:require [dire.core :refer [with-handler supervise]]
            [fs.core :refer [touch]]))

(defn read-file [file-name]
  (slurp file-name))

(with-handler #'read-file
  (fn [exception file-name & _]
    (touch file-name)
    (supervise #'read-file file-name)))

(supervise #'read-file "my-file")

which is super nice.

Sunday, June 25, 2017

I usually don't write tests, but Midje is what I will use if I have to.

just add this to project.clj:

:profiles {:dev {:dependencies [[midje "1.8.3"]]}}

test files locates:

├── src
│   └── quux
│       └── core.clj
└── test
    └── quux
        └── core_test.clj

a simple test is like:

(ns myproject.core-test
  (:require [midje.sweet :refer :all]
            [clojure.string :as str]))

(fact "simple test"
      (str/split "a/b/c" #"/") => ["a" "b" "c"])

you can run tests in cider repl too:

user> (use 'midje.repl)
user> (load-facts) ;; load all facts
user> (check-facts) ;; recheck facts
user> (autotest) ;; watch file changes and load facts
user> (autotest :stop) ;; stop autotest, also has :pause, :resume

to run test from lein, add lein-midje to your ~/.lein/profiles.clj first:

{:user {:plugins [[lein-midje "3.2.1"]]}}

then you can run

$ lein midje // load facts
$ lein midje :autotest // watch file changes and load facts

I have to say the autotest feature is very useful.

to exclude all clj/cljs/cljx files in a uberjar, add this line to project.clj:

  :uberjar-exclusions [#"\.(clj[x|s]?|java)"]

Tuesday, June 27, 2017

reading an old book: Clojure High Performance Programming

learned a thing I didn't know before:

locking, same as synchronized in java

pretty low level but good to know.

I did few aws lambda in clojure, but the team wants node.js, so I have to rewrite it.

very unhappy with that, IMHO clojure version is more concise and solid, node.js one is ... meh.

but I have to admit node.js is more suitable for aws lambda, you don't even need to include the aws sdk, just a js file.

I felt a little bit better after listening defn episode #23 - Stuart Halloway

clojure is definitely not dying, because there are still very great developers working on it.

I really should dive into spec and datomic, they're good thinkings and make clojure unique.

category theory, I still don't get it

but for clojure here's a library: funcool/cats

I want to try their Maybe, Either and Exception types, mainly for error handling.

while working with node.js, I use vim

I set these two options:

set makeprg=node\ %
set autowrite

then run the script with :make, it should work for ruby, php etc.

put this to .vimrc to enable it by file extensions:

autocmd BufNewFile,BufRead *.rb set makeprg=ruby\ %
autocmd BufNewFile,BufRead *.pl set makeprg=perl\ %
autocmd BufNewFile,BufRead *.php set makeprg=php\ %
autocmd BufNewFile,BufRead *.js set makeprg=node\ %
autocmd BufNewFile,BufRead *.sh set makeprg=bash\ %

Thursday, June 29, 2017

when using custom authorizer for api gateway, if you want to get the user id embed in the jwt, you can set the principalId to contain the user id, the lambda callback function should be able to get it via event.requestContext.authorizer.principalId

I put my reading notes for two books I read recently:

Blog Archive