jsmaker Java  Script Use Cases
1 Running the examples
2 Use cases
2.1 1. Random number between 1 and 5
2.2 2. Unique values with Set
2.3 3. Six falsey Java  Script values
2.4 4. Currying
2.5 5. Object destructuring
2.6 6. Escaping a timer interval
2.7 7. Get, set, and delete object properties
2.8 8. String concatenation order
2.9 9. Object.freeze versus Object.seal
2.10 10. Switch example
2.11 11. Class constructor with a default value
2.12 12. Sort objects by a property
2.13 13. Four ways to delete or remove an array element
2.14 14. Bubble sort
2.15 15. Recursive binary search
2.16 16. Count occurrences with Map
2.17 17. Get HTML in three ways
2.18 18. Anagram /   rearrangement check
2.19 19. Pairs equal to a target, without repeats
2.20 20. Fetch API with result and error handling
9.2

jsmaker JavaScript Use Cases🔗ℹ

Hans Dijkema <hans@dijkewijk.nl>

 (require js-maker/demo/js-usecases) package: js-maker

This document describes the practical JavaScript use cases in "demo/js-usecases.rkt". Each implementation is written as a Racket snippet using js and is tested by compiling it to JavaScript and executing that JavaScript with the configured test executor. The corresponding tests are in "testing/jsmaker-usecases.rkt".

The examples are shown vertically: first the Racket/js-maker source, then the generated JavaScript. Each code fragment is shown in a boxed documentation cell, preserving the light shaded background of the earlier side-by-side layout while avoiding narrow, wrapped code columns.

The tests intentionally use js/expression for their calls wherever possible. Raw JavaScript remains only in small harness preambles, such as fake setInterval, fake DOM objects, and fake fetch.

1 Running the examples🔗ℹ

Generate the JavaScript examples with:

racket demo/js-usecases.rkt

Run the use-case regression tests with:

racket testing/jsmaker-usecases.rkt

2 Use cases🔗ℹ

2.1 1. Random number between 1 and 5🔗ℹ

Racket / js-maker

(js

 (define (randomBetween1And5)

   (return (+ (send Math floor (* (send Math random) 5)) 1))))

Generated JavaScript

function randomBetween1And5() {

  return (Math.floor((Math.random() * 5)) + 1);

}

Tested behavior: With Math.random fixed at 0.80, the generated function returns 5.

2.2 2. Unique values with Set🔗ℹ

Racket / js-maker

(js

 (define (uniqueValues xs)

   (return (send Array from (new Set xs)))))

Generated JavaScript

function uniqueValues(xs) {

  return Array.from(new Set(xs));

}

Tested behavior: The array [1, 2, 2, 3, 1] becomes [1, 2, 3].

2.3 3. Six falsey JavaScript values🔗ℹ

Racket / js-maker

(js

 (define (falseyValues)

   (return (array #f 0 "" js-null js-undefined js-NaN))))

Generated JavaScript

function falseyValues() {

  return [false, 0, "", null, undefined, NaN];

}

Tested behavior: Mapping JavaScript Boolean over the returned values yields six false values.

2.4 4. Currying🔗ℹ

Racket / js-maker

(js

 (define (add x)

   (return (lambda (y)

             (return (+ x y))))))

Generated JavaScript

function add(x) {

  return function(y) {

    return (x + y);

  };

}

Tested behavior: The generated call add(2)(3) returns 5; the test call itself is produced with js/expression.

2.5 5. Object destructuring🔗ℹ

Racket / js-maker

(js

 (define (describePerson person)

   (let-object ([name 'name]

                [age  'age 0])

               person

     (return (string-append name ":" (number->string age))))))

Generated JavaScript

function describePerson(person) {

  return (() => {

    const { name: name, age: age = 0 } = person;

    return (name + ":" + String(age));

  })();

}

Tested behavior: The object { name: "Ada", age: 37 } is rendered as "Ada:37".

2.6 6. Escaping a timer interval🔗ℹ

Racket / js-maker

(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)))))))

Generated JavaScript

function startTimer() {

  {

    let ticks = 0;

    let intervalId = false;

    intervalId = setInterval(function() {

      ticks = (ticks + 1);

      if ((ticks === 3)) clearInterval(intervalId);

      return undefined;

    }, 10);

    return {id: intervalId, getTicks: function() { return ticks; }};

  }

}

Tested behavior: A fake timer runs the callback five times, but clearInterval stops it at tick 3.

2.7 7. Get, set, and delete object properties🔗ℹ

Racket / js-maker

(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")))))))

Generated JavaScript

function objectProps() {

  let obj = {a: 1};

  let a1 = obj.a;

  let a2 = obj["a"];

  return (() => {

    const { a: a3 } = obj;

    obj.b = 2;

    obj["c"] = 3;

    delete obj["a"];

    return [a1, a2, a3, obj.b, obj["c"], Object.hasOwn(obj, "a")];

  })();

}

Tested behavior: The three reads produce 1, the two writes produce 2 and 3, and the deleted property is absent.

2.8 8. String concatenation order🔗ℹ

Racket / js-maker

(js

 (define (concatOrder)

   (return (array (+ 1 2 "3")

                  (+ "1" 2 3)))))

Generated JavaScript

function concatOrder() {

  return [(1 + 2 + "3"), ("1" + 2 + 3)];

}

Tested behavior: The generated function returns ["33", "123"].

2.9 9. Object.freeze versus Object.seal🔗ℹ

Racket / js-maker

(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"))))))

Generated JavaScript

function freezeVsSeal() {

  let frozen = Object.freeze({a: 1});

  let sealed = Object.seal({a: 1});

  frozen.a = 9;

  sealed.a = 9;

  delete sealed["a"];

  return [frozen.a, sealed.a, Object.isFrozen(frozen),

          Object.isSealed(sealed), Object.hasOwn(sealed, "a")];

}

Tested behavior: The frozen value stays 1; the sealed value changes to 9 but remains present.

2.10 10. Switch example🔗ℹ

Racket / js-maker

(js

 (define (switchExample n)

   (case n

     [(1) (return "one")]

     [(2 3) (return "two-or-three")]

     [else (return "other")]))))

Generated JavaScript

function switchExample(n) {

  switch (n) {

    case 1: return "one";

    case 2:

    case 3: return "two-or-three";

    default: return "other";

  }

}

Tested behavior: The generated function maps 1, 2, and 9 to the three expected branches.

2.11 11. Class constructor with a default value🔗ℹ

Racket / js-maker

(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))))))

Generated JavaScript

class Greeter {

  constructor(name = "world") {

    this.name = name;

  }

  greet() {

    return ("Hello " + this.name);

  }

}

function classExample() {

  let a = new Greeter();

  let b = new Greeter("Ada");

  return [a.greet(), b.greet()];

}

Tested behavior: The default constructor value and explicit constructor argument both work.

2.12 12. Sort objects by a property🔗ℹ

Racket / js-maker

(js

 (define (sortByProperty xs prop)

   (return (send (send xs slice)

                 sort

                 (lambda (a b)

                   (return (- (js-ref a prop) (js-ref b prop))))))))

Generated JavaScript

function sortByProperty(xs, prop) {

  return xs.slice().sort(function(a, b) {

    return (a[prop] - b[prop]);

  });

}

Tested behavior: Sorting age objects by age yields [20, 25, 30].

2.13 13. Four ways to delete or remove an array element🔗ℹ

Racket / js-maker

(js

 (define (deleteArrayWays xs)

   (let* ([a1 (send xs slice)]

          [a2 (send xs slice)]

          [a3 (send xs slice)]

          [a4 (send xs slice)])

     (send a1 splice 1 1)

     (set! a2 (send a2 filter (lambda (x i) (return (not (= i 1))))))

     (set! a3 (send (send a3 slice 0 1) concat (send a3 slice 2)))

     (delete-prop! a4 1)

     (return (array a1 a2 a3

                    (array (send Object hasOwn a4 "1") (length a4)))))))

Generated JavaScript

function deleteArrayWays(xs) {

  let a1 = xs.slice(), a2 = xs.slice(), a3 = xs.slice(), a4 = xs.slice();

  a1.splice(1, 1);

  a2 = a2.filter(function(x, i) { return !(i === 1); });

  a3 = a3.slice(0, 1).concat(a3.slice(2));

  delete a4[1];

  return [a1, a2, a3, [Object.hasOwn(a4, "1"), a4.length]];

}

Tested behavior: splice, filter, and slice/concat remove the item; delete leaves a hole and preserves length.

2.14 14. Bubble sort🔗ℹ

Racket / js-maker

(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))))

Generated JavaScript

function bubbleSort(xs) {

  let a = xs.slice();

  let n = a.length;

  while ((n > 1)) {

    let i = 1;

    while ((i < n)) {

      if ((a[(i - 1)] > a[i])) {

        let tmp = a[(i - 1)];

        a[(i - 1)] = a[i];

        a[i] = tmp;

      }

      i = (i + 1);

    }

    n = (n - 1);

  }

  return a;

}

Tested behavior: Sorting [5, 1, 4, 2, 8] yields [1, 2, 4, 5, 8].

2.15 15. Recursive binary search🔗ℹ

Racket / js-maker

(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)))])))))

Generated JavaScript

function binarySearch(xs, target, low, high) {

  if ((low > high)) return -1;

  let mid = Math.floor(((low + high) / 2));

  let value = xs[mid];

  if ((value === target)) return mid;

  if ((value < target)) return binarySearch(xs, target, (mid + 1), high);

  return binarySearch(xs, target, low, (mid - 1));

}

Tested behavior: Searching 7 returns index 3; searching 4 returns -1.

2.16 16. Count occurrences with Map🔗ℹ

Racket / js-maker

(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))))))

Generated JavaScript

function countOccurrences(xs) {

  let counts = new Map();

  for (const x of xs) {

    if (counts.has(x)) counts.set(x, (counts.get(x) + 1));

    else counts.set(x, 1);

  }

  return Array.from(counts.entries());

}

Tested behavior: The array ["a", "b", "a", "c", "b", "a"] yields [["a",3],["b",2],["c",1]].

2.17 17. Get HTML in three ways🔗ℹ

Racket / js-maker

(js

 (define (getHtmlThreeWays)

   (return (array document.body.innerHTML

                  (js-dot (send document querySelector "body") innerHTML)

                  (js-ref (send document getElementById "root") "innerHTML")))))

Generated JavaScript

function getHtmlThreeWays() {

  return [document.body.innerHTML,

          document.querySelector("body").innerHTML,

          document.getElementById("root")["innerHTML"]];

}

Tested behavior: A fake DOM returns the same HTML string through all three access forms.

2.18 18. Anagram / rearrangement check🔗ℹ

Racket / js-maker

(js

 (define (sortChars s)

   (return (send (send (send s split "") sort) join "")))

 

 (define (canArrange stringA stringB)

   (return (string=? (sortChars stringA) (sortChars stringB)))))

Generated JavaScript

function sortChars(s) {

  return s.split("").sort().join("");

}

function canArrange(stringA, stringB) {

  return (sortChars(stringA) === sortChars(stringB));

}

Tested behavior: listen/silent returns true; abc/abd returns false.

2.19 19. Pairs equal to a target, without repeats🔗ℹ

Racket / js-maker

(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))))

Generated JavaScript

function pairsEqualTarget(xs, target) {

  let seen = new Set();

  let used = new Set();

  let out = [];

  for (const x of xs) {

    let y = (target - x);

    if (seen.has(y) && !(used.has(x)) && !(used.has(y))) {

      out.push([y, x]); used.add(x); used.add(y);

    } else {

      seen.add(x);

    }

  }

  return out;

}

Tested behavior: For [1, 2, 3, 4, 3, 5] and target 6 the returned pairs are [[2,4],[3,3],[1,5]].

2.20 20. Fetch API with result and error handling🔗ℹ

Racket / js-maker

(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)))))))

Generated JavaScript

function loadTitle(url) {

  return fetch(url)

    .then(function(response) { return response.json(); })

    .then(function(data) { return {ok: true, title: data.title}; })

    .catch(function(err) { return {ok: false, message: err.message}; });

}

Tested behavior: A fake fetch resolves /ok to {ok:true,title:"Done"} and rejects /fail to {ok:false,message:"network"}.