Glossary: JSON, lazy evaluation and linters — DedSec Project
Glossary: JSON, lazy evaluation and linters JSON Definition and boundaries A standard text encoding for objects, arrays, strings, numbers, booleans and null. JSON syntax is not JavaScript…
JSON
Definition and boundaries
A standard text encoding for objects, arrays, strings, numbers, booleans and null. JSON syntax is not JavaScript object-literal syntax: comments and trailing commas are invalid. A parser verifies grammar rather than the application's schema.
Working miniature
import json
d=json.loads('{"active":true,"count":3}')
assert d['active'] is True
assert type(d['count']) is int
Guided investigation
Test duplicate keys, a top-level list and an unknown field. Add separate schema validation that checks exact keys; default json.loads normally retains the last duplicated key.
Lazy evaluation
Definition and boundaries
Computation deferred until a result is demanded. Python generators yield incrementally, while Haskell uses non-strict evaluation more broadly. Delayed work changes when errors and side effects occur.
Working miniature
def numbers():
yield 2
yield 4
it=numbers()
assert next(it)==2
assert list(it)==[4]
Guided investigation
Add a print before the first yield. Confirm it does not run at generator creation and that the iterator is exhausted after consumption.
Check your understanding
For Lazy evaluation, change one input in the example and explain whether the observed behavior still satisfies the stated definition. Record the exact output and distinguish a program error from a mistaken assumption.
Linter
Definition and boundaries
Tool that checks source code against configurable static rules. It may find unused imports and suspicious constructs without executing the application; this does not replace behavioral testing or type checking.
Working miniature
def ratio(total, used):
if total <= 0: raise ValueError('invalid total')
return used/total
assert ratio(4,2)==0.5
Guided investigation
Insert an unused variable into a scratch file, run a suitable linter and remove it without changing the validation. Compare warning output with an actual failing unit test.
List
Definition and boundaries
Ordered collection preserving element positions. Python's list is a mutable dynamic array with fast indexing; inserting at the beginning can shift the rest of the elements. Other languages may implement linked lists differently.
Working miniature
names=['Ada','Grace']; names.append('Lin')
assert names[-1]=='Lin'
assert names[1:]==['Grace','Lin']
Guided investigation
Compare append with insert(0, item) for a longer list. Copy a nested list shallowly, modify an inner list and observe shared references.
Lock
Definition and boundaries
Synchronization primitive guarding a critical section against concurrent mutation. A lock protects only the operations that consistently acquire it; it cannot automatically protect external state or turn multiple SQL statements into a transaction.
Working miniature
from threading import Lock
lock=Lock(); count=[0]
with lock: count[0]+=1
assert count==[1]
Guided investigation
Run concurrent increments using the same lock. Then sketch how two threads acquiring locks A/B in opposite orders can deadlock.
Four competing threads and one protected section
A lock protects a read-modify-write operation among cooperating threads. It guarantees exclusion, not scheduling order.
from threading import Thread, Lock
mutex, counter = Lock(), [0]
def run():
for _ in range(1000):
with mutex:
counter[0] += 1
jobs = [Thread(target=run) for _ in range(4)]
for t in jobs: t.start()
for t in jobs: t.join()
assert counter[0] == 4000
Extend the experiment with a count of workers currently inside the protected section; maximum concurrency there must be one. A standard Lock is not reentrant; acquiring it twice from one thread can deadlock. Do not hold the lock while awaiting network services.