This is a searchable description of the content of a live stream recording, specifically "Episode 0 - Getting our feet wet" in the "Hands-on SAP dev with qmacro" series. There are links directly to specific highlights in the video recording. For links to annotations of other episodes, please see the "Catch the replays" section of the series blog post.
This episode, titled "
Getting our feet wet", was streamed live on Fri 18 Jan 2019 and is approximately one hour in length. The stream recording is
available on YouTube.
Below is a brief synopsis, and links to specific highlights - use these links to jump directly to particular places of interest in the recording, based on 'hh:mm:ss' style timestamps.
Brief synopsis
In this initial episode of the "Hands-on SAP dev with qmacro" series, we take a brief look at what using SAP's Cloud Application Programming Model in a Node.js context means for us JavaScript developers, and warm our brains up by solving some puzzles with a bit of ES6 flavoured code (with some functional aspects thrown in for good measure).
Links to specific highlights
00:00:49: Shoutout to the
Coffee Corner Radio podcast show.
00:02:20: A callout to just be nice to each other (which I'm sure you all are and will continue to be), and reference to the Participation Etiquette in the
SAP Community Rules of Engagement.
00:03:47: A quick look at my
Streamlabs setup.
00:05:02: Taking a first look at the
tutorial navigator on
developers.sap.com and specifically the
Create a Business Service with Note.js using Visual Studio Code tutorial.
00:07:12: Jumping ahead to the "Provide Mock Data" step in the tutorial we see that the JavaScript used is quite modern, specifically embracing many ECMAScript 6 (ES6) features, possibly less recognisable to many of us.
00:08:27: We see a similar pattern with the "Add custom logic" step later on in the tutorial, with modern JavaScript, including ES6 aspects such as destructuring and the fat arrow syntax.
00:09:37: Moving into the terminal for the rest of this episode, and bringing up a simple task for us to work on and practise our JavaScript. We'll be using the Christmas themed
Advent of Code day 1 pair of puzzles to warm up our brains a little bit.
00:11:17: Diving straight into part 1 of the puzzle, looking at what's required.
00:13:07: Looking at the puzzle input (which is user-specific), and then grabbing the example input from the puzzle description itself.
00:13:37: Thinking about a good development environment for this, with quick feedback turnaround.
00:13:57: Initialising a new repo for the solution project with
npm init
.
00:14:05: Looking at
package.json
as it initially is generated.
00:15:40: Examining the 'test harness' in the form of
index.js
(which is referenced in
package.json
) - this works as a test runner for the solutions, which provides a
clean
function, loads the day's solvers (for parts 1 and 2) and then loads the puzzle input and tries each solution.
00:16:13: Taking a brief look at two beautiful Vim plugins
Goyo and
Limelight.
00:17:23: Taking a bit of a closer look at how the
clean
function processes the puzzle data that's read in, turning the string into a clean array of values.
00:19:05: Starting with a basic skeleton solver module with functions
a
and
b
for parts 1 and 2 of the day's puzzle, respectively.
00:20:42: Creating the initial contents of the
day1.input
file from the test data in the example.
00:21:21: Initial run of
index.js
shows that we have some work to do, not least creating a
day1.js
from the
day0.js
skeleton.
00:21:39: Using
tmux to let us see the execution output of our tests as well as the contents of what we're editing. My tmux configuration is
available online if you're interested, in my
scripts repo.
00:22:36: Looking at the less than ideal situation of having to manually flip over from editor to runtime to test changes to the puzzle solutions.
00:23:46: The answer here is
nodemon which we install directly into our project as a dev dependency, with
npm i nodemon --save-dev
, looking at the addition to the
package.json
that this caused.
00:24:27: First run of
nodemon
directly, using the path via the project's
node_modules
directory (
node_modules/nodemon/bin/nodemon.js
) which will automatically run the existing
index.js
and rerun it if anything is modified.
00:26:02: Reminding ourselves of the challenge at hand, and considering an "old fashioned" approach with a for-loop, adding one such loop to the
a
function (as this is part 1 from this day's pair of puzzles).
00:27:12: First, simply getting
a
to return the input so we can see and confirm what the function is receiving and must act upon.
00:28:02: Using a shortcut to get to my Vim configuration, so we can examine an alternative way of saving file content (with
<leader>w
). Check out my entire Vim config in my
dotvim repo online.
00:28:45: Just going for a first attempt, in the knowledge that something with the input data isn't yet quite right. Building a simple for-loop as the basis for the solution first.
00:29:32: Talking about
fold
and its close relation to
reduce
(they're pretty much the same thing, see
Fold (higher-order function)).
00:30:32: Seeing the result of the data not being quite right ... JavaScript is taking the values literally, i.e. is adding the strings together. We therefore have to turn the strings into numbers which we do with the
Number
class. We get the right answer now.
00:31:32: Referencing
Luke Smith from whom I've learned a great deal in the *nix shell and tools configuration area.
00:32:11: Getting rid of the for-loop to embrace a modicum of functional programming, using
map
and also
reduce
. Also a quick look at the fat-arrow syntax for function definitions, not requiring curly braces to denote a block or even a return statement (if there's only a single expression to evaluate).
00:35:27: Copying in the real puzzle input, using
pbpaste
and rerunning the solution, which gives us the correct answer.
00:36:22: Getting ready to solve part 2 of this puzzle.
00:38:29: Examining the details of part 2.
00:40:44: Starting to build the solution to part 2 in the
b
function. We use the rather stylish (IMHO)
xs
as the parameter name for the input. "X over XS" is a phrase I remember fondly from Erik Meijer's wonderful videos on Functional Programming, F# and Haskell which you can find on YouTube here:
Haskell - Functional Programming Fundamentals (Dr. Erik Meijer).
00:42:02: Switching back to the test input ready to code and test our solution for this part 2.
00:42:42: Starting to build out the
b
function, looking at a functional approach, and using the concept of a
closure which is a super powerful idea which is implemented in many languages including of course JavaScript.
00:44:12: We create the closure in the form of an Immediately Invoked Function Expression (IIFE) which you can find details about here:
https://developer.mozilla.org/en-US/docs/Glossary/IIFE.
00:46:49: We now have a little function that has some memory, that we can use to check whether we've already seen a value or not. We evaluate the call to the lambda function (immediately invoke it) and capture the returned value in the
seen
constant - this value is actually the function that is defined, taking a single parameter
x
, directly following the
return
statement:
const seen = (() => {
const values = []
return x => {
if (values.indexOf(x) > -1) {
return true
} else {
values.push(x)
return false
}
}
})()
00:50:12: We try this out with the following test invocation:
return [1, 2, 3, 2, 1].map(seen)
which gives us, correctly,
[ false, false, false, true, true ]
.
00:51:02: Now we start to build out the latter part of this solution, that uses
seen
. Starting with an initial frequency of 0, iterating over the list of frequencies with a view to having to wrap around in case the list is exhausted before we get to the solution (which it will be) - modulo arithmetic is required here.
00:52:57: Now we bring in the real input again, and run the solution upon it, and the answer it returns is the correct one (hurray). Adding a bit of code to count how many frequency changes the solution must iterate through shows a value of more than 139k!