59 Matching Annotations
  1. Sep 2020
    1. Adjacent Edges

      This is a similar concept, but more complicated. A vertex can be connected to any number of edges. So edge adjacency is not a 1:1 parallel.

    2. Adjacent Vertices

      Seeing as an edge can only touch two members, their adjacency is directly correlated to them having a shared edge

    3. Order of a Network

      much like a set order, describes the number of members

  2. Feb 2020
    1. We need to supply a routingKey when sending, but its value is ignored for fanout exchanges.

      Fanout \(\text{exchanges}\) ignore routingKey, as they contact all all channels bound to them.

      When using a direct \(\text{exchange}\), or an auto-generated direct \(\text{exchange}\), the routingKey is used to contact a \(\text{queue}\) of specified name.

    2. That relationship between exchange and a queue is called a binding.

      Each source \((\text{exchange})\) needs a \(\text{binding}\) in order to connect to a destination \((\text{queue})\).

      $$\text{exchange } E ~~_{\large{~~\rightarrow}}^{\text{binding}}~ \text{queue } Q $$

      \(\text{bindings}\) can be added to a \(\text{channel}\) using queueBind:

      channel.queueBind(queueName,
                        exchangeName, 
                        routingKey);
      
    3. when we supply no parameters to queueDeclare() we create a non-durable, exclusive, autodelete queue with a generated name:

      Every \(\text{subscriber}\) should be declared to have it's own \(\text{queue}\). These \(\text{queues}\) need certain parameters in order to be temporary:

      queueName: uniqueId
      durable: false;
      exclusive: true;
      autoDelete: true;
      

      These \(\text{queues}\) can be created with other, special parameters if necessary, along with those listed above. Otherwise, they are easiest to create by the simple method: channel.queueDeclare().

    4. The empty string denotes the default or nameless exchange: messages are routed to the queue with the name specified by routingKey, if it exists.

      Nameless exchange: when an "" \(\text{exchange}\) name is not specified, basicPublish will instead try and route \(\text{messages}\) directly to a \(\text{queue}\) with the name given as routingKey.

    5. The exchange must know exactly what to do with a message it receives. Should it be appended to a particular queue? Should it be appended to many queues? Or should it get discarded. The rules for that are defined by the exchange type.

      An \(\text{exchange}\) can be defined by its Exchange Type rules to address a list of queues, or to address none.

    6. The core idea in the messaging model in RabbitMQ is that the producer never sends any messages directly to a queue. Actually, quite often the producer doesn't even know if a message will be delivered to any queue at all.

      \(\text{producers}\) send messages to \(\text{exchanges}\), who then forward those messages to \(\text{queues}\).

      Any given \(\text{producer}\) doesn't need to know which \(\text{queues}\) its messages will be directly forwarding to, just which \(\text{exchange}\) it is contacting to do that forwarding.

    1. Consumers therefore can be overwhelmed by the rate of deliveries, potentially accumulating a backlog in memory and running out of heap or getting their process terminated by the OS. Some client libraries will apply TCP back pressure (stop reading from the socket until the backlog of unprocessed deliveries drops beyond a certain limit)

      If an autoAck consumer becomes overloaded with messages, it may form a TCP backlog and begin dropping messages. These will not be registered as nack by RabbitMQ, and will not be re-queued for re-delivery.

    2. automatic message acknowledgement should be considered unsafe and not suitable for all workloads.

      autoAck or the "fire-and-forget" model is not safe for workloads, but can be used in high throughput environments with very low complexity of work per message.

    3. When a consumer (subscription) is registered, messages will be delivered (pushed) by RabbitMQ using the basic.deliver method. The method carries a delivery tag, which uniquely identifies the delivery on a channel.

      Messages are delivered with Unique Identifiers as delivery tag

    4. Depending on the acknowledgement mode used, RabbitMQ can consider a message to be successfully delivered either immediately after it is sent out (written to a TCP socket) or when an explicit ("manual") client acknowledgement is received.

      If autoAck is disabled, manual ack becomes a requirement. We can, then, also manually nack or reject if conditions for ack are not met.

    1. we can use the basicQos method with the prefetchCount = 1 setting. This tells RabbitMQ not to give more than one message to a worker at a time.

      Declaring channel.basicQos(1) on each worker forces a near-random distribution of work. If each worker is constantly occupied, this distribution becomes normalized and all workers receive even work loads.

    2. RabbitMQ doesn't allow you to redefine an existing queue with different parameters and will return an error to any program that tries to do that.

      Once a \(\text{queue }Q\) has been initially declared, it can not be re-declared. So, get your queue parameters right before you get to prod.

    3. A worker process running in the background will pop the tasks and eventually execute the job. When you run many workers the tasks will be shared between them.

      On a \(\text{queue }Q\), \(_{\text{subscripts}}\) will represent enqueued messages, and \(^{\text{superscripts}}\) will represent a number of sent but unacked messages.

      A \(\text{worker }1\), a type of \(\text{consumer}\), can only process 1 \(\text{message }M_1\) at any time. It will then manually send an \(\text{ACK}\) to demonstrate it has completed it's task and is free for another \(\text{message }M_2\).

      Triple dots \(\cdots\) represent down time where a \(\text{queue }Q\) either has no queued \(\text{messages}\) or it is waiting for an active \(\text{consumer}\) to receive \(\text{messages}\).

      EX: Given 3 time intensive tasks and 2 workers: $$ \text{producer } P ~~_{\normalsize\rightarrow}^{3M}~ \text{queue }Q_0\ \text{queue }Q3 ~~{\normalsize\rightarrow}^{M_1}~ \text{worker }1\ \text{queue }Q2^1 ~~{\normalsize\rightarrow}^{M_2}~ \text{worker }2\ \text{queue }Q1^2 ~\cdots\ \text{worker }1 ~~{\normalsize\rightarrow}^{\text{ACK } M_1}~ \text{queue }Q_1^2\ \text{queue }Q1^1 ~~{\normalsize\rightarrow}^{M_3}~ \text{worker }1\ \text{queue }Q0^2 ~\cdots\ \text{worker }2 ~~{\normalsize\rightarrow}^{\text{ACK } M_2}~ \text{queue }Q_0^2\ \text{queue }Q0^1 ~\cdots\ \text{worker }1 ~~{\normalsize\rightarrow}^{\text{ACK } M_3}~ \text{queue }Q_0^1\ \text{queue }Q_0 ~\cdots\ $$

    4. If a consumer dies (its channel is closed, connection is closed, or TCP connection is lost) without sending an ack, RabbitMQ will understand that a message wasn't processed fully and will re-queue it.

      There are two \(\text{workers: } 1, 2\) and one \(\text{queue }Q\). \(\text{queue }Q\) contains one \(\text{message }M_1\) which has a long run time.

      \(\text{worker } 1\) is about to go offline. It will not complete it's transaction of work, and will not \(\text{ACK}\) that it has received the message. Instead, when \(\text{worker }1\) goes offline, it will send a basic \(\text{NACK}\) response and \(\text{queue }Q\) will know to re-queue \(\text{message }M_1\).

      $$ \text{queue }Q_1 ~~_{\normalsize\rightarrow}^{M_1}~ \text{worker }1\\ \text{queue }Q_0^1 ~\cdots\\ \text{worker }1 ~~_{\normalsize\rightarrow}^{\text{NACK } M_1}~ \text{queue }Q_0^1\\ \text{queue }Q_1 ~~_{\normalsize\rightarrow}^{M_1}~ \text{worker }2\\ \text{queue }Q_0^1 ~\cdots\\ \text{worker }2 ~~_{\normalsize\rightarrow}^{\text{ACK } M_1}~ \text{queue }Q_0^1\\ \text{queue }Q_0 ~\cdots $$

  3. Oct 2019
    1. This uses the special form if, a restricted type of conditional that can be used when there are precisely two cases in the case analysis.

      Lisp if is only usable if there are no else if conditions. All else if statements must be written in the form of a cond switch.

    2. This construct is called a case analysis, and there is a special form in Lisp for notating such a case analysis.

      if statements => case analysis

  4. Jul 2019
    1. You may have noticed that different types of elements are laid out differently. Some, such as paragraphs (<p>) or headings (<h1>), take up the whole width of the document and are rendered on separate lines. These are called block elements. Others, such as links (<a>) or the <strong> element, are rendered on the same line with their surrounding text. Such elements are called inline elements.

      <div /> elements are display: block

      <span /> elements are display: inline

    2. childNodes property that element nodes in the DOM have. This property holds an array-like object, with a length property and properties labeled by numbers

      Note: childNodes may only be looped over by their indices, as they are not a typical array.

      Note: the children property works similarly, but only for elements where nodeType === Node.ELEMENT_NODE;

    3. This representation is called the Document Object Model, or DOM

      very distinct from the SUB model.

      Some objects need to stay in the DOM, even when not in view. This may require an ng-show as opposed to an ng-if. Alternatively, as long as the object data does not need to be reloaded from the back end, the object could be re-instantiated on the front end.

  5. Jun 2019
    1. came around and adopted these attitudes in its Edge browser, which replaces Internet Explorer.

      Well yes, but actually no. MS Edge is just a re-skin of IE which is still trapped in its legacy code base.

      For instance, not this morning I ran into a bug where MS Edge and IE add in non-standard X marks in their forms: https://developer.mozilla.org/en-US/docs/Web/CSS/::-ms-clear

    2. A short HTML document might look like this:

      Finally some HTML to accompany our JS

    1. Implement something like this yourself as a regular function called Promise_all.
      async function Promise_all(promises) {
        let all = []; let sat = true;
        for (let i = 0; i < promises.length; i++) {
          await promises[i]
            .then((result) => { all.push(result); })
            .catch((result) => { sat = false; }); }
        return new Promise((resolve, reject) => {
          if (sat) { resolve(all); } }); }
      
    2. Do request failures properly show up as rejections of the returned promise in both versions? How?

      Good Question: It may be beneficial to include else reject() statements in the Promises:

      async function locateScalpel(nest) {
        let current; let next = nest.name;
        while (current != next) {
          current = next;
          next = await anyStorage(nest, current, "scalpel"); }
        return next; }
      
      function locateScalpel2(nest, source) {
        if (source === undefined) { source = nest.name; }
        return anyStorage(nest, source, "scalpel").then( (result) => {
          if (result === source) { return result; }
          else { return locateScalpel2(nest, result); } }); }
      
    3. If a given node wants to talk to a single other node, flooding is not a very efficient approach.

      flooding is a bad practice, even when all nodes need to receive a message. If a network's structure gets cached (either at one centralized server node or at every node in the network) there are much more efficient methods for node to node communication.

    4. then method. This registers a callback function to be called when the promise resolves and produces a value.

      Promise.resolve().then()

    1. Instead of calling a function to access a dependency, you use a special import keyword.

      This is overall a better approach to imports, here is a link to some documentation:

      https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import

    2. CommonJS modules

      This edition of the book is rather dated, and CommonJS is not supported by ECMA standards. But for reference:

      https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules

    3. The relations between modules are called dependencies.

      Clearly defined dependencies can help you navigate a complicated app structure to find where bugs can originate from.

    4. The phrase “big ball of mud” is often used for such large, structureless programs.

      structure-less programs are as applicable as children and as malleable as old folks.

    1. Refer to the table in the chapter summary for help.

      New Verify Function.

      NOTE: make sure to keep g global enabled

      // Fill in the Following Excercises
      
      verify(/.../g,
             ["my car", "bad cats"],
             ["camper", "high art",]);
      verify(/.../g,
             ["pop culture", "mad props"],
             ["plop", "prrrop"]);
      verify(/.../g,
             ["ferret", "ferry", "ferrari"],
             ["ferrum", "transfer A"]);
      verify(/.../g,
             ["how delicious", "spacious room"],
             ["ruinous", "consciousness"]);
      verify(/.../g,
             ["bad punctuation ."],
             ["escape the period"]);
      verify(/.../g,
             ["hottentottententen"],
             ["no", "hotten totten tenten"]);
      verify(/.../g,
             ["red platypus", "wobbling nest"],
             ["earth bed", "learning ape", "BEET"]);
      
      
      function verify(regexp, yes, no) {
        //ignore unfinished excercises
        if (regexp.source == "...") return;
        findStrings(regexp, yes, true);
        findStrings(regexp, no, false); }
      function findStrings(regexp, strings, yes) {
        let found = {}; let not_found = new Set();
        for (let input of strings){
          let selection = {}; let match;
            while (match = regexp.exec(input)) {
              selection[match.index] = match[0]; }
          if(Object.keys(selection).length === 0){
            not_found.add(input);
          } else { found[input] = selection; } }
        if (Object.keys(found).length > 0) {
          console.log(check(yes), "Matched:  ", found); }
        if (not_found.size > 0) {
          console.log(check(!yes), "Unmatched:", setPrint(not_found)); } }
      function check(yes){
        if (yes) { return "✔️"; } else { return "❌"; } }
      function setPrint(set){
        let line = "{";
        for (let item of set.keys()) { line+= item +", "; }
        return line.slice(0,-2)+"}"; }
      
    2. The difference between the global and the sticky options is that, when sticky is enabled, the match will succeed only if it starts directly at lastIndex, whereas with global, it will search ahead for a position where a match can start.
      let sticky = /abc/y;
      sticky.lastIndex = 4;
      console.log(sticky.exec("xyz abc"));
      console.log(sticky.lastIndex);
      
    3. lastIndex, which controls, in some limited circumstances, where the next match will start. Those circumstances are that the regular expression must have the global (g) or sticky (y) option enabled, and the match must happen through the exec method

      confused screaming

    4. repetition operators (+, *, ?, and {}) are greedy, meaning they match as much as they can and backtrack from there. If you put a question mark after them (+?, *?, ??, {}?), they become nongreedy and start by matching as little as possible

      in most use cases, the regexp would act more intentionally (and bug out less) using a non-greedy operator

    1. For extra points, make sure that if you call withBoxUnlocked when the box is already unlocked, the box stays unlocked.

      box should really be a class declaration, but we'll let it slide for today

      const box = {
        locked: true,
        unlock() { this.locked = false; },
        lock() { this.locked = true;  },
        _content: [],
        get content() {
          if (this.locked) throw new Error("Locked!");
          return this._content; } };
      
      function withBoxUnlocked(body) {
        let locked = box.locked;
        try {
          box.unlock();
          body();
        } finally {
          if (locked){ box.lock(); } } }
      
      // function calls
      withBoxUnlocked(() => { box.content.push("gold piece"); });
      box.unlock();
      try {
        withBoxUnlocked(() => { throw new Error("Pirates on the horizon! Abort!"); });
      } catch (e) {
        console.log("Error raised: " + e.message); }
      console.log(box.locked);
      withBoxUnlocked(() => { console.log(box.content); });
      
    2. If you reintroduce the typo, the undefined binding error will be properly reported.
      class SomeError extends Error {}
      
      foo = (garbage) => {
        if (garbage === "stuff"){ return "yep"; }
        throw new SomeError(garbage); }
      
      fools = () => {
        let stuff;
        try {
          stuff = foo(prompt("Enter some stuff:"));
        } catch (e) {
          if (e instanceof SomeError) {
            console.log("Invalid Stuff:", e.message, "\nHave a nice day!");
          } else { throw e; }
        } finally {
          if (stuff === "yep"){
            console.log("👌 That's the stuff! 👌"); } } }
      
      fools();
      
    3. I do not recommend trying to write assertions for every possible kind of bad input. That’d be a lot of work and would lead to very noisy code. You’ll want to reserve them for mistakes that are easy to make (or that you find yourself making).

      Use assert to correct your personal user error

  6. May 2019
    1. Make the Group class from the previous exercise iterable.
      class Group {
        constructor (){
          this.values = []; }
        val(iter){
          if ( iter > this.values.length ){ return undefined; }
          return this.values[iter]; }
        has(val){
          return (this.values.indexOf(val) !== -1); }
        add(val){
          if( !this.has(val) ){ this.values.push(val); } }
        delete(val){
          this.values = this.values.filter(n => n != val); }
      }
      Group.from = function(arr) {
        let temp = new Group;
        for(let i=0; i<arr.length; i++){
          temp.add(arr[i]); }
        return temp;
      }
      class GroupIterator {
        constructor(group) {
          this.loc = 0;
          this.group = group; }
        next() {
          if ( this.loc >= this.group.values.length ){
            return {done: true}; }
          let value = this.group.val(this.loc);
          this.loc++;
          return {value, done: false }; }
      }
      Group.prototype[Symbol.iterator] = function() {
        return new GroupIterator(this);
      };
      
    2. The use of the word extends indicates that this class shouldn’t be directly based on the default Object prototype but on some other class. This is called the superclass. The derived class is the subclass.

      Does extends allow for multi-tiered inheritance? Ex:

      class Array {...};
      class Matrix extends Array {...};
      class SuperMatrix extends Matrix {...};
      
    3. getters, and they are defined by writing get in front of the method name

      as opposed to

      const getSize => { return _size; }
      
    4. JavaScript comes with a class called Map that is written for this exact purpose. It stores a mapping and allows any type of keys.

      JS map allows for non-string < keyType, valueType >

    5. Arrow functions are different—they do not bind their own this but can see the this binding of the scope around them.
      this => $scope
      
    6. It is also common to put an underscore (_) character at the start of property names to indicate that those properties are private.
      _private
      _properties
      
      public
      properties
      
    1. arrayToList

      It would be much more elegant to have a node class, but for the sake of the exercise:

      prepend = (value, list) => {
        return {value:value, rest:list};
      }
      arrayToList = arr => {
        head = null;
        for (let i = arr.length-1; i >= 0; i--){
          head = prepend(arr[i],head);
        }
        return head;
      }
      listToArray = list => {
        arr = []; head = list;
        while ( head !== null) {
          arr.push(head.value); head = head.rest;
        }
        return arr;
      }
      nth = (list,loc) => {
        if (head === null) { return null; }
        if (loc === 0) { return list.value; }
        return nth(list.rest, loc-1);
      }
      
    2. There is an old programming tradition of writing the names of constant values in all caps.
      (() => {
          app.constant('constants', {
              SOMETHING: 'something',
              ELSE: 'else'
          });
      })();
      
      // constants.SOMETHING  ->  'something'
      
    1. The (U.S.-based) Unicode Consortium decided to treat them as a single writing system to save character codes. This is called Han unification and still makes some people very angry.

      phenomenal

    2. This function is a little less straightforward

      more complicated example of passing functions and the necessity of return statements:

      function unless(test, then, other) {
        if (test) { return then(); }
        else { return other(); } }
      function reduce(array, combine, start) {
        let current = start;
        for (let element of array) {
          console.log("current:",current,"element:",element);
          current = combine(current, element);
        } return current; }
      console.log("final value:", reduce([1, 2, 3, 4],
        (a, b) => { return unless( b % 2 == 1,
          () => { return a + b; },
          () => { return a * b; } ) }, 0 ));
      
    3. functions that provide new types of control flow

      function defined control flow ( eg. main ) Also:

      function unless(test, then, other) {
        if (!test) { then(); }
        else { other(); } }
      repeat(3, n => { unless(n % 2 == 1,
          () => { console.log(n, "is even"); }, 
          () => { console.log(n, "is odd");  }) });
      
    4. Functions that operate on other functions, either by taking them as arguments or by returning them, are called higher-order functions.

      functions are simply variables

    1. A pure function is a specific kind of value-producing function that not only has no side effects but also doesn’t rely on side effects from other code

      Function Purity

    2. People think that computer science is the art of geniuses but the actual reality is the opposite, just many people doing things that build on each other, like a wall of mini stones. Donald Knuth

      Elegantly Put

    1. A good programming language helps the programmer by allowing them to talk about the actions that the computer has to perform on a higher level.

      easily accessible surface code

  7. Oct 2018
  8. www.cs.rpi.edu www.cs.rpi.edu
    1. There are member function calls to our versions of theSchoolandStudentclasses, so you can deduce how some of the member functions in our solution work.

      School and Student have private classes on the Submitty Server. Figure out how they work to best understand how to write the homework

    2. Use STL lists

      See Lecture 9

    3. insert_student_into_school_preference_listrequest, which takes the name of the school, the name ofthe new student to be added, and the name of a student who is already on the list in front of which this newstudent should be inserted

      insert_student_into_school_preference U_of_M erin_jones john_smith

  9. Mar 2018
    1. also clarify the ways resistance movements can be a helpful site for understanding how to identify, critique, and transform ignorance.

      interesting the way she mentioned her examples as 'helpful for identifying and critiquing' before entering the main bodies.

  10. Feb 2018