§1. The Utilities

Now yiz are in the Willingdone Museyroom.
This is a Prooshious gunn. This is a ffrinch. Tip.
This is the flag of the Prooshious, the Cap and Soracer.
This is the bullet that byng the flag of the Prooshious.
This is the ffrinch that fire on the Bull that byng the
flag of the Prooshious. Saloos the Crossgunn!
Up with your pike and fork! (Bullsfoot! Fine!)
This is the triplewon hat of the Lipoleum.
Tip. Lipoleumhat.

[Click.]

  1. Introduction to the Utilities
  2. Function: repeat
  3. Function: assign
  4. Function: isDigit
  5. Function: indexOfLongestSuffixSansDigits
  6. Object: CharCode
  7. Object: KeyCode
  8. Object: Angle
  9. Object: Measure
  10. Object: FunctionCall
  1. Introduction to the Utilities

    We begin our deconstruction of Slytherins Wake by examining the program’s utilities. Each utility is small and may be used anywhere in Slytherins Wake. None of the utilities depend on anything except the type of programming environment typically provided by many popular web browsers. We assume that a JavaScript interpreter provided by a modern web browser such as such as Chrome, Edge, or Firefox will be used to execute the program and that the brower’s implementation of JavaScript supports the language features and standard library routines used by Slytherins Wake.

    The utilities we’re about to look at won’t shed much light on the anatomy of a snake. However, we should be familiar with them so that when we encounter one of the utilities in the context of another component, like a constructor function or another utility, we'll recognize it, remember what it does, and recall how it should be used if not exactly how it is implemented.

    Some of the utilities described below are first-class functions. The others are frozen objects identified by constant variables. First we’ll look at the functions, which are like loose tools strewn about on a programmer’s workbench. Then we’ll examine the objects, which are like toolboxes containing related tools, parts, and paraphernalia.

    Go slow. Study each part carefully. Read the notes. Follow the links that follow the notes. Do the exercises.

    NOTES

    1. This tapestry of text and source code that we’ve woven, which we’re now unraveling, is intended for highbrow coders everywhere and for the lowly worms who wrote it. It’s for experts and novices alike. In other words, we’re trying to satisfy everybody at the risk of humoring only him.
    2. We’ve sequenced the sections of Slytherins Wake such that little things are presented first, for the reader’s sake, thence we proceed to greater. This will appeal to those of you who enjoy a bottoms-up approach to making acquaintances. If you’re on a high harse and like to leer at things from the top down, come down and slog around in the mud with us for a while until we reach a level of abstraction that dispenses with dirty details you prefer not to deal with.
    3. We try to cater to the diverse needs of our readers by providing links to online resources about topics more or less relevant to Slytherins Wake in the sections where those topics are first introduced. Many of the links refer to pages on the website https://developer.mozilla.org. We’re all in on MDN. It’s our favorite online source of information about JavaScript. Thankfully, it’s add-free, as in cholesterol-free, sugar-free, gluten-free, …
    4. Besides hyperlinks, we also provide notes like this one. Similar to notes found in a study Bible, our notes are for students who seek a deeper level of understanding than their author, who forgets things easily.
    5. What’s noteworthy? you ask. That’s for us to decide and you to wonder about. Sometimes we find ourself in a rabbit hole. Take the note that follows this one, for example. It fascinates us, which might make you wonder.
    6. According to the Wikipedia article https://en.wikipedia.org/wiki/Study_Bible, “Nearly all Catholic Bibles have explanatory and interpretative footnotes.[citation needed] [sic] For example, the Jerusalem Bible is a widely respected study Bible originally made by French monks in Jerusalem, under the auspices of the Catholic Church. The original French edition of 1961 became the basis of versions of this study Bible in several other languages, including English, revised as the New Jerusalem Bible; some versions have more extensive notes than others.”

    SEE

    1. https://developer.mozilla.org/en-US/docs/Web/Tutorials
    2. https://developer.mozilla.org/en-US/docs/Glossary/JavaScript
    3. https://developer.mozilla.org/en-US/docs/Glossary/ECMAScript
    4. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions
    5. https://developer.mozilla.org/en-US/docs/Glossary/First-class_Function
    6. https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Basics
    7. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const
    8. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze

    SEE ALSO

    1. https://en.wikipedia.org/wiki/Tilting_at_windmills
    2. http://www.laputan.org/mud/mud.html
    3. https://en.wikipedia.org/wiki/Top-down_and_bottom-up_design
    4. https://en.wikipedia.org/wiki/Abstraction
    5. https://www.newyorker.com/culture/cultural-comment/going-all-in-on-all-in
    6. https://en.wikipedia.org/wiki/Study_Bible

  2. Function: repeat.

    We now present repeat, a simple utility function designed to execute another function multiple times. The function seems contrived and unnecessary to us. Its author says he hid an agenda somewhere around here, but he can’t remember where he put it. Can you help him find it?

    /**
     *  Given a function foo and a non-negative integer n,
     *  repeat calls foo n times.
     *  The value returned by the function is undefined.
     */
    function repeat(foo, n) {
      while (n > 0) {
        foo();
        n = n - 1;
      }
    }
    
    

    NOTES

    1. This piece of Slyterins Wake can be partitioned into two parts: a block of innocuous comments followed by some JavaScript code that defines a function. Comments that appear before a unit of code, such as the definition of a function or an object, typically describe the publicly accessible components or services the unit provides and how programmers may use it. (Comments have no effect on how a program runs.) Additional commentary might be needed to put a piece of a program in perspective so that readers thoroughly understand the contribution the piece makes to the whole program. Providing readers with contextual information through prose that is less constrained and more readable than tradition comments is a strategy that literate programmers adopt in their quest to help people, not machines, comprehend their code.
    2. Self-anointed literate programmers express themselves how ever they choose. That’s why their bible is called The Art, not The Dogma of Computer Programming. You can also view the source code for Slytherins Wake—including traditional comments like the comments shown in the code snippet above but without all this hot air—over at Tangled, the Reader’s Digest version of the program. Less is more and then some.
    3. A value passed to a JavaScript function can be a reference to another function just as easily as it can be a string or a number or any other type of data. This is a noteworthy feature of JavaScript that we’ll take advantage of repeatedly in Slytherins Wake.
    4. JavaScript variables, like the parameters foo and n, can be assigned values of any type. The function repeat does not verify that the value of foo is actually of type function or that the value of n is in fact a non-negative integer. The repeat utility and the other utilities described in this section are only intended to be used within Slytherins Wake; they are not intended to be used by developers who compose new programs using Slytherins Wake. Therefore, we have, we assert, complete control over all values passed to these utility functions and methods; we assume responsibility for the arguments we pass, ane we assure you they are of the correct type and are in range, assuming we haven’t made mistakes to the contrary.
    5. The fixed number of characters needed to define the function aside, every time we invoke repeat instead of writing a conventional loop, Slyterins Wake ends up being little smaller than it would have been if we had used a loop instead of calling the function. (Maybe this is that hidden agenda he’s searching for? The function still seems shaky, if you ask us.)
    6. Removing or tampering with repeat is verboten, especially if you don’t know what Chesterton’s fence is for. (He insisted we tell you that. Frankly, we’re not sure what all the fuss is about, much less how fences factor in.)

    SEE

    1. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar
    2. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures
    3. https://developer.mozilla.org/en-US/docs/Glossary/Parameter
    4. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/while
    5. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators#Relational_operators
    6. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Subtraction_(-)
    7. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Assignment_Operators
    8. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined

    SEE ALSO

    1. https://en.wikipedia.org/wiki/Wikipedia:Chesterton%27s_fence
    2. https://en.wikipedia.org/wiki/Foobar
    3. https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Coding_Style
    4. https://en.wikipedia.org/wiki/Less_(Unix)
    5. https://en.wikipedia.org/wiki/More_(command)

    EXERCISES

    1. How often is the function repeat invoked in Slytherins Wake?
    2. What is repeat’s raison d'ĂȘtre?
    3. Is there a limit to the number of times a JavaScript function can be invoked using repeat? If there is a limit, what is it and why does the limit exist?
    4. What are the values of the following JavaScript expressions?
      1. 'Doh!' - 1
      2. NaN > 0
    5. Is the function repeat an algorithm? Is it a computational method? Explain.
    6. Would you change repeat if you couldn’t be sure that the values assigned to the parameters foo and n were always going to be a reference to a function and a finite number respectively? If you wouldn’t change the function, why not? If you would change the function, why and how would you change it? (If you think the function should be changed, consider using a throw statement, the typeof operator, the isFinite global function, the Number.isFinite method, or anything else that might help.)
    7. Make an interesting change to the way repeat is implemented without changing the name of the function, the number or order of its parameters, or the service that repeat purports to provide. Test your change. Make sure the new version of repeat works just like the original version. Repeat as many times as you can or until you get tired of this exercise. Which variation of repeat do you like best? Why?
    8. Enhance repeat. Add a third parameter called args. In your enhanced version of the function, invoke foo by calling foo.apply. Pass the value of args to the apply method. Use your modified version of repeat together with the alert command to display the salutation Hello, Durlbin! in a popup window twice in a row.
    9. What happens when you execute the following command using the version of repeat that you created in the previous exercise?
      repeat(repeat, 2, [alert, 2, ["Finis, again!"]]);
    10. Try to compose a method using the Java programming language that does essentially the same thing that repeat does. Compare and contrast your Java method with the JavaScript function. If you could not create a comparable subroutine using Java, what inhibited you?

  1. Function: assign.

    /**
     * Giving two objects, target and source,
     * assign copies enumerable properties from source to target
     * and returns the value of target.
     */
    function assign(target, source) {
      for (let propertyName in source) {
        target[propertyName] = source[propertyName];
      }
      return target;
    }
    
    

    Note: The assign utility is similar to the standard library method Object.assign.

    SEE

    1. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in
    2. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let
    3. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_accessors
    4. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Enumerability_and_ownership_of_properties

    SEE ALSO

    1. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
    2. https://www.ecma-international.org/ecma-262/6.0/#sec-object.assign
    3. https://en.wikipedia.org/wiki/Polyfill_(programming)
    4. https://en.wikipedia.org/wiki/Shim_(computing)

  2. Function: isDigit.

    /**
     * Given a string s and an optional number i,
     * isDigit returns true if:
     *  a) the value of i is undefined or null
     *     and the first character of s is a digit, or
     *  b) the character at index i′ of s is a digit where
     *     i′ is the value of i converted to an integer.
     *  Otherwise, isDigit returns false.
     */
    function isDigit(s, i) {
      return CharCode.isDigit(s.charCodeAt(i));
    }
    
    

    Note:

    1. The description of isDigit above is ambiguous in at least one way. It doesn’t say how the value of i will be converted to an integer if it is not an integer to begin with. Will the value be rounded up or down? What if the value of i is a string, not a number? Since the conversion is performed by String.prototype.charCodeAt and we can’t see how that method does its job, it’s not easy to really know what will happen in all cases. Different web browser vendors may implement String.prototype.charCodeAt differently, and Slytherins Wake isn’t intended to be tied to just one browser. We can test various suspect scenarios using various versions of various web browsers and discover how charCodeAt behaves. But just talking about all those permutations makes our head hurt. What about browsers and input combinations that we don’t test? Is there authoritative documentation somewhere that says how String.prototype.charCodeAt should work? These are important questions to ponder.

    See

    1. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/charCodeAt
  3. Function: indexOfLongestSuffixSansDigits.

    /**
     * Returns the index of the beginning of the longest suffix of
     * string s that does not contain any digits.
     */
    function indexOfLongestSuffixSansDigits(s) {
      let i = s.length - 1;
      while (i > 0 && !isDigit(s, i)) {
        i = i - 1;
      }
      return i + 1;
    }
    
    
  4. Object: CharCode.

    const CharCode = Object.freeze({
    
    1. CharCode.<property>

        Zero: '0'.charCodeAt(0),
        Nine: '9'.charCodeAt(0),
      
    2. CharCode.isDigit

        isDigit: function(code) {
          return CharCode.Zero <= code && code <= CharCode.Nine;
        }
      
    });
    
    
  5. Object: KeyCode.

    const KeyCode = Object.freeze({
    
    1. KeyCode.<property>

        Space: 32,
        LeftArrow: 37,
        UpArrow: 38,
        RightArrow: 39,
        DownArrow: 40
      
    });
    
    
  6. Object: Angle.

    const Angle = Object.freeze({
    
    1. Angle.<properties>

        halfTurn: '180deg',
        straight: '0deg',
        quarterTurnLeft: '-90deg',
        quarterTurnRight: '90deg'
      
    });
    
    
  7. Object: Measure.

    const Measure = Object.freeze({
    
    1. Measure.indexOfUnits

        indexOfUnits: function (string) {
          return indexOfLongestSuffixSansDigits(string);
        },
      
    2. Measure.parseNumber

        parseNumber: function (value) {
          const number = parseFloat(value);
          return (isFinite(number)) ? number : 0;
        },
      
    3. Measure.units

        units: function (string) {
          return string.slice(Measure.indexOfUnits(string));
        },
      
    4. Measure.separate

        separate: function (string) {
          const i = Measure.indexOfUnits(string);
          return {
            number: Measure.parseNumber(string.slice(0, i)),
            units: string.slice(i)
          };
        }
      
    });
    
    
  8. Object: FunctionCall

    const FunctionCall = Object.freeze({
    
    1. FunctionCall.arguments

        arguments: function (string, fname) {
          if (fname === undefined) fname = "";
          const s = fname + '(';
          const i = string.indexOf(s);
          const j = string.indexOf(')', i);
          return (i < 0 || j < 0) ? "" : string.substring(i + s.length, j);
        }
      
    });
    
    
Tip (Bullseye! Game!) How Copenhagen ended.
This way the museyroom. Mind your boots goan out.

[Click.]