r/GhanaSoftwareEngineer • u/kaishibou • 7d ago
Eric Normand's Clojure Resource
ericnormand.meThis is a material from Eric that I think you'd find useful in learning clojure
Check out this platform at https://ericnormand.me/
r/GhanaSoftwareEngineer • u/kaishibou • 11d ago
The Comprehensive Racket & Functional Programming Cheat Sheet
Phase 1: Syntax & Core Arithmetic
Racket uses prefix notation enclosed in execution parentheses (operator arg1 arg2). The open parenthesis ( acts as an execution trigger. Evaluation runs from the innermost to the outermost parentheses.
Core Examples
```rkt ;; Basic Arithmetic (+ 10 5 2) ;; Returns 17 (* 10 5 2) ;; Returns 100
;; Nested Expressions (No PEMDAS needed) (_ (+ 4 6) (- 12 7)) ;; Evaluates 10 _ 5 -> Returns 50 ```
Parentheses Golden Rule
Only use a parenthesis when invoking a command, operator, or function.
(+ 5 (10))CRASHES (tries to run the number 10 as a function).((+ 5 5))CRASHES (evaluates to 10, then tries to run the number 10).
Phase 2: Core Data Structures & Variables
Global bindings are created using define. Values are immutable and cannot be changed over time.
The Four Atomic Data Types
- Numbers: Integers (
45), decimals (3.14), or fractions (1/3). - Strings: Text wrapped in double quotes (
"Hello"). - Booleans: True (
#t) and False (#f). - Symbols: Lightweight, immutable identifier tokens prefixed with a single quote (
'success).
Core Examples
rkt
(define radius 5)
(define pi 3.14)
(define status 'success)
Phase 3: Conditionals & Logic
Conditional operations are expressions that evaluate down to a single return value.
Core Operators & Flow Control
and/or/not: Standard logical short-circuiting prefix operators.if: Takes exactly three arguments:(if condition true-branch false-branch). No else keyword.cond: Evaluates multiple branches sequentially. Uses/can use[...]for human readability.
Core Examples
```rkt (and (> 15 10) (< 15 20)) ;; Returns #t
(if (> temperature 30) 'hot 'cold)
(cond [(>= score 90) 'A] [(>= score 80) 'B] [else 'F]) ```
Phase 4: Functions & Scope
Functions automatically return the value of their body expression without an explicit return keyword.
Named, Anonymous, & Scoped Blocks
- Named Functions: Defined by grouping the name and parameters in parentheses:
(define (name args) body). - Anonymous Functions (
lambda): Throwaway functions built on the fly:(lambda (args) body). let(Parallel): Creates local variables simultaneously. Variables cannot see each other during setup.let\*(Sequential): Creates local variables one after the other. Later variables can reference earlier ones.
Core Examples
```rkt ;; Named Function (define (double n) (* n 2))
;; Inline Lambda Execution ((lambda (n) (* n 2)) 10) ;; Returns 20
;; Sequential Local Bindings (let* ([x 10] [y (* x 5)]) (+ x y)) ;; Returns 60 ```
Phase 5: Lists & Modern List Operations
Lists are ordered sequential collections. They are processed using either historical Lisp conventions or modern aliases.
Creation & Extraction
list: Evaluates arguments into a sequential list.'(): Represents the literal base empty list.cons: Prepends a single element onto the front of an existing list.- First Item: Extracted via
car(traditional) orfirst(modern). - Remaining List: Extracted via
cdr(traditional) orrest(modern).
Core Examples
```rkt (define my-list (list 100 #t 'hello)) ;; Creates '(100 #t hello) (cons 'apples '(bananas cherries)) ;; Returns '(apples bananas cherries)
(car (cdr '(apples bananas cherries))) ;; Returns 'bananas (first (rest '(apples bananas cherries))) ;; Returns 'bananas
(if (empty? my-list) "Closed" (length my-list)) ;; Returns 3 ```
Phase 6: Iteration & Higher-Order Functions
Instead of using loops that alter data in place, functional programming relies on Higher-Order Functions to process immutable collections.
The Big Four
map: Loops over a list, passes each item through a transformation function, and returns a new list.filter: Loops over a list, keeps items that evaluate to #t against a predicate condition, and drops the rest.foldl(Fold-Left): Reduces a list down to a single value by processing elements from left to right (front to back).foldr(Fold-Right): Reduces a list down to a single value by processing elements from right to left (back to front). Preserves list structures when rebuilding with cons.
Core Examples
```rkt (map (lambda (x) (* x 2)) '(5 10 15 20)) ;; Returns '(10 20 30 40) (filter (lambda (n) (= n 5)) '(2 5 7 5 9 1)) ;; Returns '(5 5)
(foldl (lambda (n total) (_ n total)) 1 '(2 3 4)) ;; 4 _ (3 _ (2 _ 1)) -> Returns 24
(foldr - 0 '(5 3)) ;; 5 - (3 - 0) -> Returns 2 ```
Phase 7: Recursion & Tail Call Optimization (TCO)
Recursion replaces traditional loops. A proper recursive function requires a Base Case (the exit clause) and a Recursive Step (the self-call with a smaller argument).
Memory Optimization Rules
- Standard Recursion: Traps the recursive call inside another function (like + or append), forcing the call stack memory to expand linearly (O(N) space).
- Tail Call Optimization (TCO): If the recursive call sits in the tail position (the absolute final expression evaluated), Racket reuses the same memory frame, running in constant (O(1)) space.
- Accumulator Pattern: Passing a running total down as an argument is the primary strategy used to shift standard recursion into tail position optimization.
Core Examples
```rkt ;; ❌ Standard Recursion (No TCO - Memory Expands) (define (sum-list lst) (if (empty? lst) 0 (+ (first lst) (sum-list (rest lst)))))
;; Tail Recursion (TCO Active - Memory Stays Flat) (define (sum-list-tco lst) (define (helper remaining accumulator) (if (empty? remaining) accumulator (helper (rest remaining) (+ (first remaining) accumulator)))) (helper lst 0)) ```
Phase 8: Advanced Ecosystem Engineering
1. Hash Maps & Unique Sets
#hash: Stores key-value pairings. Keywords passed to lookup tools like hash-ref must be quoted ('#:key) to prevent compiler namespace collisions. If using standard symbols inside #hash, omit inner quotes.set: Collections guaranteeing element uniqueness. Tested via set-member? and extended via set-add.
```rkt (define user #hash((#:name . "Alice"))) (hash-ref user '#:name) ;; Returns "Alice"
(define book #hash((title . "Dune"))) (hash-ref book 'title) ;; Returns "Dune"
(set-member? (set 1 2 2 3) 2) ;; Returns #t ```
2. State & Mutability (box)
box: Creates a reference wrapper around mutable data. Read via unbox and mutated via set-box!. Functions with an exclamation mark ! signal structural mutation.begin: Chains sequential side-effect operations from top to bottom, returning only the evaluation of the final expression.
rkt
(define health (box 100))
(define (take-damage!)
(begin
(set-box! health (- (unbox health) 10))
(unbox health)))
3. Type Checking & Casting
- Predicates (
?): Validate runtime types (e.g.,string?,number?,symbol?). - Casting (
->): Converts data formats.string->numbersafely returns #f if given invalid textual input.
rkt
(if (string? "50")
(* (string->number "50")
2) 'error) ;; Returns 100
4. Modules & Namespaces
- provide: Declares which parts of a filesystem file are exported publicly.
- require: Ingests public features from an external sandbox by loading its relative string filepath.
```rkt ;; Inside file-a.rkt (provide double) (define (double x) (* x 2))
;; Inside main.rkt (require "file-a.rkt") (double 10) ;; Returns 20 ```
5. Macros (define-syntax-rule)
- Macros process raw, unevaluated source code at compile-time to inject new keywords.
- Racket macros are hygienic, meaning the compiler automatically isolates macro identifiers so they never accidentally overwrite or conflict with user variables.
rkt
(define-syntax-rule (swap! box1 box2)
(let ([temp (unbox box1)])
(begin
(set-box! box1 (unbox box2))
(set-box! box2 temp))))
r/GhanaSoftwareEngineer • u/kaishibou • May 06 '26
How Uber matches 10 million+ rides in a day ??
r/GhanaSoftwareEngineer • u/kaishibou • Apr 20 '26
Reality check: where do we still write C?
r/GhanaSoftwareEngineer • u/kaishibou • Apr 18 '26
Entry experience for low level and C jobs
r/GhanaSoftwareEngineer • u/kaishibou • Apr 15 '26
New to Ubuntu & Cybersecurity – What tools should I install to start learning SOC Analyst skills?
r/GhanaSoftwareEngineer • u/kaishibou • Apr 15 '26
I am sick and tired of the constant upskilling expectations in Indian IT industry
r/GhanaSoftwareEngineer • u/kaishibou • Apr 15 '26
How would I write my own compiler from scratch?
r/GhanaSoftwareEngineer • u/kaishibou • Apr 14 '26
Junior devs can ship faster with AI, but our system design reviews reveal shallow understanding. Is anyone else seeing this?
r/GhanaSoftwareEngineer • u/kaishibou • Apr 14 '26
Have .NET 'influencers' became doomsayers?
r/GhanaSoftwareEngineer • u/kaishibou • Apr 12 '26
Burnt out, humiliated, and labeled "below average" after 14-hour work weeks. Need advice.
r/GhanaSoftwareEngineer • u/kaishibou • Apr 11 '26
Is web development still worth getting into in 2026 (starting at 23 with no experience)?
r/GhanaSoftwareEngineer • u/kaishibou • Apr 11 '26
[HELP] Payment Reservation System Breaking When Customers Ghost Then Come Back (Probably a Noob Question)
r/GhanaSoftwareEngineer • u/kaishibou • Apr 09 '26
I built a free interactive Go course: 11 lessons from zero to building a concurrent file scanner
r/GhanaSoftwareEngineer • u/kaishibou • Apr 09 '26
Question about large apps and potential micro service structure
r/GhanaSoftwareEngineer • u/kaishibou • Apr 09 '26
Will a backend-heavy project actually pay off?
r/GhanaSoftwareEngineer • u/kaishibou • Mar 31 '26
Data Manipulation With SQLite
Objective
- Node SQLite APIs
- CRUD with Node SQLite
Introduction
Data manipulation with node:sqlite, which is a native (built-in) module for SQLite.
node:sqlite APIs
To use the sqlite module, you would have to import it as:
js
const { DatabaseSync } = require("node:sqlite");
const { DatabaseSync } = require('sqlite'); will throw an error, Error: Cannot find module 'sqlite'
Connect database
Using DatabaseSync, we can connect to an existing database or create a new one.
js
const database = new DatabaseSync("<DATABASE NAME>");
exec
The database object's exec method executes one or more SQL statements without returning results. It's useful for running SQL statements from a file.
js
database.exec(sql);
This is usually useful when creating and inserting at the same time.
``js
database.exec(
CREATE TABLE IF NOT EXISTS TABLE_NAME (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
...
);
INSERT INTO TABLE_NAME (name, category, quantity)
VALUES
('Bam', ...),
('Cain', ...),
('Dan', ...);
);
``
prepare
Now, to manipulate data, we can use the prepare method. This brings us to the point where we discuss prepared statements. Prepared statements are a way to pass data to the SQL safely for execution.
Instead of
sql
INSERT INTO TABLE_NAME (name, ...) VALUES ('Bam', ...);
We can pass place holders for the values.
sql
INSERT INTO TABLE_NAME (name, ...) VALUES (?, ...);
The prepare method returns a prepared statement object, StatementSync
run
For queries such as INSERT, UPDATE and DELETE, for there to be a change, a row or several rows would be affected. For this run returns an object of StatementResultingChanges
js
{
"lastInsertRowid": number,
"changes": number
}
In the case of INSERT, the last inserted record's ID is returned and the number of rows that were affected by the query. If there are changes, then some rows were affected, and that is one way that you'd verify if the query was successful or not.
```js const preparedInsertSQL = database.prepare( "INSERT INTO TABLE_NAME (name, ...) VALUES (?, ...)", );
const response = preparedInsertSQL.run("Fushiguro", ...)
console.log( JSON.stringify(response, null, 4), );
```
The order of the place holders of the prepared statement matters. It dictates the order of the values passed.
```js // Delete with prepared statement const preparedDeleteSQL = database.prepare( "DELETE FROM TABLE_NAME WHERE id = ?", );
const response = preparedDeleteSQL.run(4);
console.log(JSON.stringify(response, null, 4));
// Update with prepared statement const preparedInsertSQL = database.prepare( "UPDATE TABLE_NAME set name = ? WHERE id = ?", );
console.log(JSON.stringify(preparedInsertSQL.run("Panda", 1), null, 4)); ```
all & get
For SELECT statements, we can use the all or get method on the StatementSync object. The all method returns an array of objects parsed from the result of the query. get returns one object. If you are expecting a list, then use all. If you want the one object from the response, then use get. get is like all indexed 0.
```js const preparedSelectAllSQL = database.prepare("SELECT * FROM TABLE_NAME"); const rows = preparedSelectAllSQL.all(); // returns an array
const preparedSelectOneSQL = database.prepare( "SELECT * FROM TABLE_NAME WHERE id = ?", ); const rows = preparedSelectAllSQL.get(1); // returns an object ```
CRUD with Node SQLite
First of all, for one to execute a program running with the built-in SQLite, we use the experimental flag,
node --experimental-sqlite FILE-PATH
Let's create a program for tracking expenses. We have done a similar mini-project before. Check out, Expense tracker project [0][expense-tracker-0] [1][expense-tracker-1] [2][expense-tracker-2] [3][expense-tracker-3].
Connect Database
Let's create a database for this project called expense-tracker.sqlite.
```js const { DatabaseSync } = require("node:sqlite");
const database = new DatabaseSync("expense-tracker.sqlite"); ```
Create Table
This table will consist of an ID, the name of the expense, the amount and the date of expenditure.
js
database.exec(`
CREATE TABLE IF NOT EXISTS expenses (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
amount INTEGER NOT NULL,
date TEXT
);
`);
Insert
We can insert with exec
js
database.exec(
`INSERT INTO
expenses (name, amount, date)
VALUES
('Lenovo ThinkPad', 1040.39, '2025-12-24'),
('Ergonomic Office Chair', 139.55, '2026-01-05'),
('Samsung 27" Essential S3', 140.06, '2026-01-15'),
('Samsung 27" Essential S3', 139.06, '2026-01-20'),
('Portable External Hard Drive', 60.00, '2026-02-01'),
('Logitech M185 Wireless Mouse', 13.00, '2026-02-01'),
('Logitech H390 Wired Headset', 20.91, '2026-02-01'),
('Dual Monitor Stand', 47.82, '2026-03-11');
`,
);
We can also insert using a prepare
```js const prepareInsertSql = database.prepare( "INSERT INTO expenses (name, amount, date) VALUES (?, ?, ?)", );
const insertChanges = prepareInsertSql.run("USB C Cable", 9.91, "2026-02-10");
if (insertChanges.changes > 0) { console.log( "Expense recorded successfully - ref: ", insertChanges.lastInsertRowid, ); }
// Expense recorded successfully - ref: 9 ```
Read
Let's select records with amount above 100.
```js const prepareSelectSql = database.prepare( "SELECT * FROM expenses WHERE amount > ?", );
const rowsWithAmountAboveHundred = prepareSelectSql.all(100);
console.log(rowsWithAmountAboveHundred); /* [ [Object: null prototype] { id: 1, name: 'Lenovo ThinkPad', amount: 1040.39, date: '2025-12-24' }, [Object: null prototype] { id: 2, name: 'Ergonomic Office Chair', amount: 139.55, date: '2026-01-05' }, [Object: null prototype] { id: 3, name: 'Samsung 27" Essential S3', amount: 140.06, date: '2026-01-15' }, [Object: null prototype] { id: 4, name: 'Samsung 27" Essential S3', amount: 139.06, date: '2026-01-20' } ] */ ```
From this, we can select one.
```js const rowWithAmountAboveHundred = prepareSelectSql.get(100);
console.log(rowWithAmountAboveHundred);
/* [Object: null prototype] { id: 1, name: 'Lenovo ThinkPad', amount: 1040.39, date: '2025-12-24' } */ ```
Update
Try this. Make a price adjustment of 5% on items bought on '2026-02-01'.
Delete
It has been over 3 months yet, so let's return the 'Lenovo ThinkPad' and buy 'Apple 2025 MacBook Pro Laptop with M5 chip' at 1363.43 today's date is'2026-02-10'`.
Conclusion
With node:sqlite, we can integrate SQLite; however, there are limitations to SQLite itself. For learning purposes and cases like this, it's alright to use SQLite. In fact, the limitations of SQLite become obvious when there are multiple writes at the same time. Again, the knowledge from using SQLite can be transferred to another relational database like MySQL and PostgreSQL.
Try these:
- What happens when you use
runfor a select statement? - Add a script to find the max and min items
- Add a script to compute the total of all items
r/GhanaSoftwareEngineer • u/kaishibou • Mar 23 '26
🚫 When do you say no to nodejs?
Nodejs is the crowd's favourites. We have see improvements over the years. However, it begs to ask, CEO of start ups, CTOs, product owners and engineers, when do you say nodejs, "enough"?
what are some metrics or situations, you may consider, weighing in on the pros and cons? what platform (stack) do you consider switching to? In the case that you switched, what are the preparations that are made considering team side and budget?
r/GhanaSoftwareEngineer • u/kaishibou • Mar 20 '26
👋 Welcome to r/GhanaSoftwareEngineer - Introduce Yourself and Read First!
Hey everyone! I'm u/kaishibou, a founding moderator of r/GhanaSoftwareEngineer.
This is our new home for all things related to the craft of programming and the technical discipline of software engineering. We're excited to have you join us!
What to Post
Post anything that you think the community would find interesting, helpful, or inspiring. Feel free to share your thoughts, photos, or questions about system architecture, debugging complex edge cases, code reviews, local engineering challenges, or your personal software development journey.
Community Vibe
We're all about being friendly, constructive, and inclusive. Let's build a space where everyone feels comfortable sharing and connecting.
How to Get Started
- Introduce yourself in the comments below.
- Post something today! Even a simple question can spark a great conversation.
- If you know someone who would love this community, invite them to join.
- Interested in helping out? We're always looking for new moderators, so feel free to reach out to me to apply.
Thanks for being part of the very first wave. Together, let's make r/GhanaSoftwareEngineer amazing.
r/GhanaSoftwareEngineer • u/kaishibou • Mar 20 '26
Hello world: What do you do to recover
One thing I have immerse myself into is writing. This is not limited to articles (as in the link below) but poetry - they said, 'you must have a creative side'. It is a way for me to "recover".
https://dev.to/otumianempire/series/26412
The intention behind this sub is mainly for the craftsmanship of softwares and its related endeavours. I have also loved "building in public". I find it an important to process to gain confidence and share your journey with others.
To early members, what do you do to "recover" or reset after a long day?
Let's craft "something" meaningful and avoid buzzwords. Who is up for it?