Skip to content

Commit

Permalink
Chapter 11
Browse files Browse the repository at this point in the history
  • Loading branch information
EMCestari committed Apr 25, 2022
1 parent ed1e1f8 commit 6d706d4
Show file tree
Hide file tree
Showing 4 changed files with 346 additions and 1 deletion.
101 changes: 101 additions & 0 deletions Chapter 10 - Modules/EJS-Chapter 10.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// You can use JavaScript functions to create local scopes and objects to represent module interfaces

const weekDay = function(){
const names = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];

return{
name(number) { return names[number]; },
number(name) {return names.indexOf(name);}
};
}();

console.log(weekDay.name(weekDay.number("Sunday")));
// -> Sunday



// Special operator eval will execute a string in the current scope.
// This is usually a bad idea because it breaks some properties that scopes have, such easy predictability.

const x = 1;
function evalAndReturnX(code) {
eval(code);
return x;
}

console.log(evalAndReturnX("var x = 2"));
// -> 2
console.log(x);
// -> 1


// A less scary way of interpreting data as code is to use the Function constructor.
let plusOne = Function("n", "return n + 1;");
console.log(plusOne(4));
// -> 5



// The most widely used approach is called CommonJS modules.
// Node.js uses it and is the system used by most packages on NPM.
const ordinal = require("ordinal");
const {days, months} = require("date-names");

exports.formatDate = function(date, format) {
return format.replace(/YYYY|M(MMM)?|Do?|dddd/g, tag => {
if (tag == "YYYY") return date.getFullYear();
if (tag == "M") return date.getMonth();
if (tag == "MMMM") return months[date.getMonth()];
if (tag == "D") return date.getDate();
if (tag == "Do") return ordinal(date.getDate());
if (tag == "dddd") return days[date.getDay()];
});
};

const {formatDate} = require("./format-date");

console.log(formatDate(new Date(2019, 8, 13),
"dddd the Do"));
// → Friday the 13th


// We can define require, in its most minimal form, like this:
require.cache = Object.create(null);

function require(name) {
if (!(name in require.cache)) {
let code = readFile(name);
let module = {exports: {}};
require.cache[name] = module;
let wrapper = Function("require, exports, module", code);
wrapper(require, module.exports, module);
}
return require.cache[name].exports;
}


const {parse} = require("ini");

console.log(parse("x = 10\ny = 20"));
// → {x: "10", y: "20"}


// ES stands for ECMAScript.
// The notation is now integrated into the language.
// Instead of calling a function to access a dependency, you use a special import keyword.

import ordinal from "ordinal";
import {days, months} from "date-names";

export function formatDate(date, format) { /* ... */ }


// The export keyword is used to export things.
// It may appear in front of a function, class, or binding definition (let, const, or var).

export default ["Winter", "Spring", "Summer", "Autumn"];

import {days as dayNames} from "date-names";

console.log(dayNames.length);
// → 7
94 changes: 94 additions & 0 deletions Chapter 11 - Asynchronous Programming/EJS-Chapter 11.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
let fifteen = Promise.resolve(15);
fifteen.then(value => console.log(`Got ${value}`));
// -> Got 15


function storage(nest,name) {
return new Promise(resolve => {
nest.readStorage(name, result => resolve(result));
})
}

storage(bigOak, "enemies")
.then(value => console.log("Got", value));


new Promise((_,reject) => reject(new Error("Fail")))
.then(value => console.log("Handler 1"))
.catch(reason => {
console.log("Caught failure " + reason);
return "nothing";
})
.then(value => console.log("Handler 2", value));
// -> Caught failure Error: Fail
// -> Handler 2 nothing


class Timeout extends Error {}

function request(nest, target, type, content) {
return new Promise((resolve,reject) => {
let done = false;
function attempt(n){
nest.send(target, type, content, (failed,value) => {
done = true;
if (failed) reject(failed);
else resolve(value);
});
setTimeout(() => {
if (done) return;
else if (n < 3) attempt(n + 1);
else reject(new Timeout("Timed out"));
}, 250);
}
attempt(1);
});
}


function requestType(name,handler) {
defineRequestType(name,(nest,content,source,callback) => {
try {
Promise.resolve(handler(nest,content,source))
.then(response => callback(null,response),
failure => callback(failure));
} catch (exception) {
callback(exception);
}
});
}


requestType("ping", () => "pong");

function availableNeighbors(nest){
let requests = nest.neighbors.map(neighbor => {
return request(nest, neighbor, "ping")
.then(() => true, () => false);
});
return Promise.all(requests).then(result => {
return nest.neighbors.filter((_,i) => result[i]);
});
}



import {everywhere} from "./crow-tech";

everywhere(nest => {
nest.state.gossip = [];
});

function sendGossip(nest,message,exceptFor = null) {
nest.state.gossip.push(message);
for (let neighbor of nest.neighbors){
if (neighbor == exceptFor) continue;
request(nest, neighbor, "gossip", message);
}
}

requestType("gossip",(nest, message, source) => {
if(nest.state.gossip.includes(message)) return;
console.log(`${nest.name} received gossip '${message}' from ${source}`);
sendGossip(nest, message, source);
});
94 changes: 93 additions & 1 deletion Chapter 9 - Regular Expressions/EJS-Chapter9.js
Original file line number Diff line number Diff line change
Expand Up @@ -295,4 +295,96 @@ console.log(" word".search(/\S/));
console.log(" ".search(/\S/));
// → -1

// No way to indicate that the match should start at a given offset
// No way to indicate that the match should start at a given offset


/* THE LAST INDEX PROPERTY */

// The exec method similarly does not provide a convenient way to start searching from a given position in the string.
// But it does provide an inconvenient way.

let pattern = /y/g;
pattern.lastIndex = 3;
let match = pattern.exec("xyzzy");
console.log(match.index);
// -> 4
console.log(pattern.lastIndex);
// -> 5

// Sticky option: match will succeed only if it starts directly at lastIndex
// Global option: match will search ahead for a position where a match can start
let global = /abc/g;
console.log(gobal.exec("xyz abc"));
// -> ["abc"]
let sticky = /abc/y;
console.log(sticky.exec("xyz abc"));
// -> null


let digit = /\d/g;
console.log(digit.exec("here it is: 1"));
// -> ["1"]
console.log(digit.exec("and now: 1"));
// -> null


console.log("Banana".match(/an/g));
// -> ["an", "an"]


/* LOOPING OVER MATCHES */

// We can scan through all occurrences of a pattern ina string, by using lastIndex and exec.
let input = "A string with 3 numbers in it... 42 and 88.";
let number = /\b\d+\b/g;
let match;
while (match = number.exec(input)){
console.log("Found", match[0], "at", match.index);
}
// -> Found 3 at 14
// Found 42 at 33
// Found 88 at 40


/* PARSING AN INI FILE */

function parseINI(string) {
// Start with an object to hold the top-level fields
let result = {};
let section = result;
string.split(/\r?\n/).forEach(line => {
// Since the format has to be processed line by line, splitting up the file into separate lines is a good start
// Some OSs use not just a newline character but a carriage return character followed by a newline ("\r\n").
let match;
if (match = line.match(/^(\w+)=(.*)$/)) {
section[match[1]] = match[2];
} else if (match = line.match(/^\[(.*)\]$/)) {
section = result[match[1]] = {};
} else if (!/^\s*(;.*)?$/.test(line)) {
// If a line is not a section header or a property, the function checks whether
// it is a comment or an empty line using the expression /^\s*(;.*)?$/.
throw new Error("Line '" + line + "' is not valid.");
}
});
return result;
}

console.log(parseINI(`
name=Vasilis
[address]
city=Tessaloniki`));
// → {name: "Vasilis", address: {city: "Tessaloniki"}}


/* INTERNATIONAL CHARACTERS */

// it is possible to use \p in a regular expression (that must have the Unicode option enabled) to match all
// characters to which the Unicode standard assigns a given property.
console.log(/\p{Script=Greek}/u.test(""));
// → true
console.log(/\p{Script=Arabic}/u.test(""));
// → false
console.log(/\p{Alphabetic}/u.test(""));
// → true
console.log(/\p{Alphabetic}/u.test("!"));
// → false
58 changes: 58 additions & 0 deletions Chapter 9 - Regular Expressions/RegexpGolf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
const log = (args) => {
console.log(args);
}

// Car and cat
let re1 = /^ca(t|r)$/;
log(re1.test("cat")); // -> True
log(re1.test("car")); // -> True
log(re1.test("cas")); // -> False
log(re1.test("cam")); // -> False
log(re1.test("scat")); // -> False
log(re1.test("cats")); // -> False

// pop and prop
let re2 = /^pr?op$/;
log(re2.test("pop")); // -> True
log(re2.test("prop")); // -> True
log(re2.test("pops")); // -> False
log(re2.test("pnop")); // -> False

// ferret, ferry, and ferrari
let re3 = /^ferr(et|y|ari)$/
log(re3.test("ferret")); // -> True
log(re3.test("ferry")); // -> True
log(re3.test("ferrari")); // -> True
log(re3.test("fernet")); // -> False
log(re3.test("ferrart")); // -> False
log(re3.test("ferriri")); // -> False


// Any word ending in ious
let re4 = /^[a-z]*ious$/
log(re4.test("ingenious")); // -> True
log(re4.test("abcious")); // -> True
log(re4.test("ious")); // -> True
log(re4.test("ab1ious")); // -> False
log(re4.test("abcioust")); // -> False


// Any whitespace character followed by a period, comma, colon, or semicolon
let re5 = /\s[.|,|:|;]/
log(re5.test("Hello , how are you?")); // -> True
log(re5.test("Still : what do you think?")); // -> True
log(re5.test("Precious advice, thanks!")); // -> False


// A word longer than six letters
let re6 = /\w{7}/
log(re6.test("abcdefg")); // -> True
log(re6.test("There is abcdefg here")); // -> True
log(re6.test("abcdef")); // -> False
log(re6.test("There is abcdef here")); // -> False


// A word without the letter e (or E)
let re7 = /\b[^e\s]+\b/i
log(re7.test("This hasn't the l3tt3r...")); // -> True
log(re7.test("These have the letter")); // -> False

0 comments on commit 6d706d4

Please sign in to comment.