A mostly AI coded js-maker, supervised by me.
This commit is contained in:
@@ -0,0 +1,304 @@
|
||||
#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))
|
||||
Reference in New Issue
Block a user