#lang racket/base (require racket/list "../main.rkt") (provide usecase-random-number usecase-unique-values usecase-falsey-values usecase-currying usecase-object-destructuring usecase-timer-interval usecase-object-props usecase-string-concat-order usecase-freeze-vs-seal usecase-switch usecase-class-constructor usecase-sort-objects-by-property usecase-delete-array-elements usecase-bubble-sort usecase-binary-search usecase-map-count-occurrences usecase-get-html-three-ways usecase-anagram usecase-pairs-equal-target usecase-fetch-api all-js-usecases show-js-usecases write-js-usecases-file) ;; Use case 01: generate a random integer between 1 and 5. (define usecase-random-number (js (define (randomBetween1And5) (return (+ (send Math floor (* (send Math random) 5)) 1))))) ;; Use case 02: get unique values from an array with duplicates using Set. (define usecase-unique-values (js (define (uniqueValues xs) (return (send Array from (new Set xs)))))) ;; Use case 03: the six JavaScript falsey values. (define usecase-falsey-values (js (define (falseyValues) (return (array #f 0 "" js-null js-undefined js-NaN))))) ;; Use case 04: currying, simple example. (define usecase-currying (js (define (add x) (return (lambda (y) (return (+ x y))))))) ;; Use case 05: object destructuring. (define usecase-object-destructuring (js (define (describePerson person) (let-object ([name 'name] [age 'age 0]) person (return (string-append name ":" (number->string age))))))) ;; Use case 06: get out of a timer interval with setInterval/clearInterval. (define usecase-timer-interval (js (define (startTimer) (let* ([ticks 0] [intervalId #f]) (set! intervalId (setInterval (lambda () (set! ticks (+ ticks 1)) (when (= ticks 3) (clearInterval intervalId))) 10)) (return (object 'id intervalId 'getTicks (lambda () (return ticks)))))))) ;; Use case 07: get/set/delete object properties. The value of a is read via ;; dot access, bracket access, and destructuring. (define usecase-object-props (js (define (objectProps) (let* ([obj (object 'a 1)] [a1 obj.a] [a2 (js-ref obj "a")]) (let-object ([a3 'a]) obj (set! obj.b 2) (set-prop! obj "c" 3) (delete-prop! obj "a") (return (array a1 a2 a3 obj.b (js-ref obj "c") (send Object hasOwn obj "a")))))))) ;; Use case 08: string concatenation; order matters with JavaScript +. (define usecase-string-concat-order (js (define (concatOrder) (return (array (+ 1 2 "3") (+ "1" 2 3)))))) ;; Use case 09: Object.freeze() vs Object.seal(). (define usecase-freeze-vs-seal (js (define (freezeVsSeal) (let* ([frozen (send Object freeze (object 'a 1))] [sealed (send Object seal (object 'a 1))]) (set! frozen.a 9) (set! sealed.a 9) (delete-prop! sealed "a") (return (array frozen.a sealed.a (send Object isFrozen frozen) (send Object isSealed sealed) (send Object hasOwn sealed "a"))))))) ;; Use case 10: switch example. The Racket surface form is case. (define usecase-switch (js (define (switchExample n) (case n [(1) (return "one")] [(2 3) (return "two-or-three")] [else (return "other")])))) ;; Use case 11: class constructor with a default value. (define usecase-class-constructor (js (define-class Greeter (constructor ([name "world"]) (set! this.name name)) (method greet () (return (string-append "Hello " this.name)))) (define (classExample) (let* ([a (new Greeter)] [b (new Greeter "Ada")]) (return (array (send a greet) (send b greet))))))) ;; Use case 12: sort an array of objects by a given property. (define usecase-sort-objects-by-property (js (define (sortByProperty xs prop) (return (send (send xs slice) sort (lambda (a b) (return (- (js-ref a prop) (js-ref b prop))))))))) ;; Use case 13: four ways to delete/remove an element from an array. (define usecase-delete-array-elements (js (define (deleteArrayWays xs) (let* ([a1 (send xs slice)] [a2 (send xs slice)] [a3 (send xs slice)] [a4 (send xs slice)]) ;; 1. Mutating removal with splice. (send a1 splice 1 1) ;; 2. Functional removal with filter. (set! a2 (send a2 filter (lambda (x i) (return (not (= i 1)))))) ;; 3. Rebuild with slice + concat. (set! a3 (send (send a3 slice 0 1) concat (send a3 slice 2))) ;; 4. delete leaves a hole and preserves length. (delete-prop! a4 1) (return (array a1 a2 a3 (array (send Object hasOwn a4 "1") (length a4)))))))) ;; Use case 14: Bubble Sort. (define usecase-bubble-sort (js (define (bubbleSort xs) (let* ([a (send xs slice)] [n (length a)]) (while (> n 1) (let* ([i 1]) (while (< i n) (when (> (list-ref a (- i 1)) (list-ref a i)) (let* ([tmp (list-ref a (- i 1))]) (vector-set! a (- i 1) (list-ref a i)) (vector-set! a i tmp))) (set! i (+ i 1)))) (set! n (- n 1))) (return a))))) ;; Use case 15: Binary Search using recursion. (define usecase-binary-search (js (define (binarySearch xs target low high) (if (> low high) (return -1) (let* ([mid (send Math floor (/ (+ low high) 2))] [value (list-ref xs mid)]) (cond [(= value target) (return mid)] [(< value target) (return (binarySearch xs target (+ mid 1) high))] [else (return (binarySearch xs target low (- mid 1)))])))))) ;; Use case 16: use Map to count how often each element occurs in an array. (define usecase-map-count-occurrences (js (define (countOccurrences xs) (let* ([counts (new Map)]) (for ([x (in-list xs)]) (if (send counts has x) (send counts set x (+ (send counts get x) 1)) (send counts set x 1))) (return (send Array from (send counts entries))))))) ;; Use case 17: get HTML in three different ways via the DOM. (define usecase-get-html-three-ways (js (define (getHtmlThreeWays) (return (array document.body.innerHTML (js-dot (send document querySelector "body") innerHTML) (js-ref (send document getElementById "root") "innerHTML")))))) ;; Use case 18: determine if stringA can be arranged into stringB. (define usecase-anagram (js (define (sortChars s) (return (send (send (send s split "") sort) join ""))) (define (canArrange stringA stringB) (return (string=? (sortChars stringA) (sortChars stringB)))))) ;; Use case 19: determine what pairs in an array equal a given value, with no ;; repeated numbers in the result pairs. (define usecase-pairs-equal-target (js (define (pairsEqualTarget xs target) (let* ([seen (new Set)] [used (new Set)] [out (array)]) (for ([x (in-list xs)]) (let* ([y (- target x)]) (if (and (send seen has y) (not (send used has x)) (not (send used has y))) (begin (send out push (array y x)) (send used add x) (send used add y)) (send seen add x)))) (return out))))) ;; Use case 20: fetch API, handling results and errors. The function returns a ;; Promise, which the test framework awaits. (define usecase-fetch-api (js (define (loadTitle url) (return (send (send (send (fetch url) then (lambda (response) (return (send response json)))) then (lambda (data) (return (object 'ok #t 'title data.title)))) catch (lambda (err) (return (object 'ok #f 'message err.message)))))))) (define all-js-usecases `((random-number . ,usecase-random-number) (unique-values . ,usecase-unique-values) (falsey-values . ,usecase-falsey-values) (currying . ,usecase-currying) (object-destructuring . ,usecase-object-destructuring) (timer-interval . ,usecase-timer-interval) (object-props . ,usecase-object-props) (string-concat-order . ,usecase-string-concat-order) (freeze-vs-seal . ,usecase-freeze-vs-seal) (switch . ,usecase-switch) (class-constructor . ,usecase-class-constructor) (sort-objects-by-property . ,usecase-sort-objects-by-property) (delete-array-elements . ,usecase-delete-array-elements) (bubble-sort . ,usecase-bubble-sort) (binary-search . ,usecase-binary-search) (map-count-occurrences . ,usecase-map-count-occurrences) (get-html-three-ways . ,usecase-get-html-three-ways) (anagram . ,usecase-anagram) (pairs-equal-target . ,usecase-pairs-equal-target) (fetch-api . ,usecase-fetch-api))) (define (show-js-usecases) (for ([entry (in-list all-js-usecases)]) (displayln (format "// ~a" (car entry))) (displayln (cdr entry)) (newline))) (define (write-js-usecases-file path) (call-with-output-file path #:exists 'replace (lambda (out) (displayln "// Generated by demo/js-usecases.rkt" out) (displayln "// Each use case is wrapped in a function so snippets with return are valid." out) (for ([entry (in-list all-js-usecases)]) (fprintf out "\n// ~a\n" (car entry)) (fprintf out "function run_~a() {\n~a\n}\n" (regexp-replace* #rx"[^A-Za-z0-9_$]" (symbol->string (car entry)) "_") (cdr entry)))))) (module+ main (show-js-usecases))