Build my own Hello World

It's just a personal note.

Using JavaScript, a new element is created when looping in the "for of" statement.

What's this?

  • I'm studying this book.

  • I'd not known it is ok that const is used in the "for of" loop.

What I learned

How to use const element in the for loop

Like this example, you can use const when initializing for loop for array.

At first glance, you might think that there would be more than one value in const.

const l = [1, 2, 3];

for (const i of l) {
    console.log(i);
}
// => 1
//    2
//    3

But, in fact, JavaScript creates a new variable in the each iteration.

So you can use const.

Note: Each iteration creates a new variable. Reassigning the variable inside the loop body does not affect the original value in the iterable (an array, in this case).

for...of - JavaScript | MDN

Note: Reassigning a variable does not change the original variable.

Stated above, each iteration creates a new variable, so you cannot change the value in the original array.

At most, only you can change is the variable you use in the iteration.

const L = [[1, 2], 3, 4];

for (let i of L) {
    i = 1000;
}

console.log(L);
// => [ [ 1, 2 ], 3, 4 ]

Side note: You can use destructuring to assign multiple local variables

I learned a tip when reading document.
You can use desructuring to assing multiple variables. I think it can be used in many situation you use array in array.

const LL = [[1, 2], [3, 4], [5, 6]];

for (let [i, k] of LL) {
    console.log(i, k)
}
// => 1 2
//    3 4
//    5 6

for...of - JavaScript | MDN

Impression on Implementation

  • I should notice the scope of the variable
  • Readng the official document enables me to learn some new topics and tips.

github.com

What you should take care of when you use Number type as keys in the Object type of TypeScript

What's this?

  • I'm learning this book.

  • I've found that I misunderstood some behaviors of Number type when used in key of Object.

What I learned.

basic use of Object value

Basically, you can get a value of the Object by using object.key.

Also, you can get the value by using object['key'] notation. What you should take care of is, if you use this format, you must use String notation.

const obj = {
    b: 1,
    c: 2
}

console.log(obj.b, obj.c); // => 1, 2
console.log(obj['b'], obj['c']); // => 1, 2
// console.log(obj[b], obj[c]); // => error Cannot find name 'c'.

When using Number type as a key

Notice1: you can use Number type when getting a value

Previously, I mentioned that you must use String when using object[key] notation.
But when using number as a key, you can also get a value by using Number type.

The reason for this specification seems to make the behavior the same as that of arrays.

const objNum = {
    1: 1,
    2: 2
}

console.log(objNum[1], objNum[2]); // => 1, 2

Of course, you can also use String notaion.

console.log(objNum['1'], objNum['2']); // => 1, 2

This behavior is reasonable because a key is dealt as a String inside of Object.

for (let num in objNum){
    console.log(typeof num);
}
// => string
//    string

Notice2: you cannot use object.key notation

This code will output error message.

// console.log(objNum.1, objNum.2); // => error ',' expected.

In fact, you may see this error even when using String keys.

const objStrDiff = {
    'diff name': 1
}

// console.log(objStrDiff.diff name); // => error ',' expected.

In short, if it's a key that's not an identifier, you can't access the value in the form object.key.

console.log(objStrDiff['diff name']); // => 1

Impression on Implementation

  • I should learn more about identifier and reserved word

developer.mozilla.org

github.com

short-circuit evaluation of OR operator and usuful technics

What's this?

  • I'm studying this book.

  • And I've learned a feature of OR operator.

developer.mozilla.org

What I leaned.

short-circuit evaluation

JavaScript logical operators has the short-circuit feature.

That means that two expressions are evaluated from left to right, and if left expression is truthy, right expression will not be evaluated.

This is a simple example. fuction A returns true, so function B was not called.

function A(){
    console.log('A');
    return true;
}

function B(){
    console.log('B');
    return false;
}

console.log(A() || B()); // => A
                         // true

// B() is not called!

a simple but useful usecase

you can express default values easily, using the feature of OR operator.

Look at this example.

The point is how to initialize b.
when initializing b, I used OR operator. If you use it, you can define default values on the right side of OR operator because when left expression is falthy, right expression is evaluated automatically.

const a = null;
const b = a || 2;
console.log(`b = ${b}`); // => b = 2

Impression on Implementation

  • Of course, you can implement this situation using if statement, but it's important that you should remember some conventional ways of writing.

github.com

build a simple TypeScript environment with Docker

What's this?

  • I'll study TypeScript to use in business
  • Since building an environment from scratch, I tried building it with Docker.

What I learned.

Studying Docker

First, I studied basic Docker features and commands using the official tutorial.

I learned that a container is an isolated environment that runs some code.

Docker 概要 — Docker-docs-ja 24.0 ドキュメント

build an environment

Next, I've tried a simple Docker environment for myself.

When searching on the Internet, I found some articles that introduced some tips to build an environment quickly, but it was not my purpose.

To learn Docker, I tried building it from a simple OS image.

This is my Dockerfile. After launching an ubuntu, some command was called to install TypeScript.

FROM ubuntu:latest
WORKDIR /app
RUN apt-get update && \
    apt-get install -y curl && \
    curl -fsSL https://deb.nodesource.com/setup_16.x | bash - && \
    apt-get install -y nodejs && \
    npm install -g typescript
 CMD ["bash"]

Also, I wrote docker-compose.yml to study docker-compose and to simplify the setting of the bind mount.

Because I want to implement TypeScript code on the local host, I wanted to configure the bind mount.

version: '3'

services:
  typescript_environment:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - .:/app
    stdin_open: true
    tty: true

This is my output.

github.com

run the Docker container and run the TypeScript code

when you run this command in the directory that has the docker-compose.yml file, the container runs.

-d is the detach mode, and it make the container run in the background.

$ docker-compose up -d

docker-compose up — Docker-docs-ja 24.0 ドキュメント

This command shows which container is running.

$ docker ps

And, this command executes the container's command, so you can run the bash and operate in the container.

$ docker exec -it ${container ID} bash

Then, I ran the tsc(compile .ts file to .js).

/app# tsc hello.ts

Finally, I ran the .js file. Yes!! I can compile and run the TypeScript code.

/app# node hello.js
hello, TypeScript!

stop and remove a container

This command can remove the container.

$ docker rm ${container ID}

However, you must stop the container before removing it.

$ docker stop ${container ID}

Impression on Implementation

  • I don't know the internal structure of the Docker now.

When to use Lambda function?

What's this?

  • I'm studying this book.

  • I'm curious about when to use the Lambda function, so I'll investigate the topic.

What I learned

What is lambda function?

In Python, you usually use def to create functions.

But, the lambda function can create a small and anonymous function.

It's basically a syntactic sugar for a normal function.

4. More Control Flow Tools — Python 3.12.1 documentation

How to write it

You can create a one-liner function using the lambda function.

sum_a_b = lambda a, b: a + b
print(sum_a_b(1, 3)) # => 4

It is syntactically restricted to a single expression, but you can use an if statement to switch which to return.

return_bigger = lambda a,b: a if a > b else b
print(return_bigger(1, 3)) # => 3

When to use it

The above cases are not realistic use cases, because if you'd like to create a named function, you can use normal functions using def.

When you'd like to use functions as arguments, lambda functions are useful.

For example, let's check a case using map.
The map function returns an iterator that applies function to every item of an iterable.

Built-in Functions — Python 3.12.1 documentation

Of course, you can create a function and use it in the map function.

l = [1, 2, 3, 4]

def double(x):
    return x**2

print(list(map(double, l))) # => [1, 4, 9, 16]

Also, you can use the lambda function, and it makes the code simpler.

l = [1, 2, 3, 4]
print(list(map(lambda x: x**2, l))) # => [1, 4, 9, 16]

Impression on Implementation

  • Abbreviated notations like this may sometimes decrease readability. You should use it properly.

What do boolean operations return?

What's this?

  • I'm studying this book.

  • I've misunderstood the boolean operations, so I'll write the correct information about them.

What I learned

What are boolean operations?

They provide boolean operational features.

But, to be more precise, they return original values that can be interpreted as boolean outputs when it is used in the bool() function.

This is the point I'd misunderstood.

Some examples

I'll use and as a sample of the boolean operations.

There's no problem when boolean values are operated. As and is defined, the particular boolean values are returned.

print(True and True) # => True
print(True and False) # => False
print(False and True) # => False
print(False and False) # => False

Then, I'll revise the above code to int values. What would happen?
Look! I got int values.

print(1 and 1) # => 1
print(1 and 0) # => 0
print(0 and 1) # => 0
print(0 and 0) # => 0

Not to mention, each number can be interpreted as the corresponding boolean values when used in bool().

print(bool(1 and 1)) # => True
print(bool(1 and 0)) # => False
print(bool(0 and 1)) # => False
print(bool(0 and 0)) # => False

Strict definitions

These are the strict definitions.

The operator not yields True if its argument is false, False otherwise.

The expression x and y first evaluates x; if x is false, its value is returned; otherwise, y is evaluated and the resulting value is returned.

The expression x or y first evaluates x; if x is true, its value is returned; otherwise, y is evaluated and the resulting value is returned.

6. Expressions — Python 3.12.1 documentation

The point you should check is and and or return the last evaluated argument.

You may easily understand these concepts if they are written as code.

def operate_and(x, y):
    if bool(x) == False:
        return x
    else:
        return y

print(operate_and(1, 1)) # => 1
print(operate_and(1, 0)) # => 0
print(operate_and(0, 1)) # => 0
print(operate_and(0, 0)) # => 0

Use case

For example, you can use boolean operations to set default values.

a = ''
print(a or 'default value') # => default value

Impression on Implementation

  • I've realized that when I implement the features of a particular concept for myself, I can correctly understand it.

What is "walrus operator"?

What's this?

  • I'm studying this book.

  • I found the concept of walrus operator interesting, so I'll summarize it.

What I learned.

What is "walrus operator"?

The walrus operator is one of the features that were added when Python was updated to 3.8ver.

What’s New In Python 3.8 — Python 3.12.1 documentation

The official name of it is "assignment expression", and as its name expresses, it acts as both an assignment and an expression.

In this code, you can find a walrus operator.
test := 1 assigns 1 to test, and also returns the value of 1.

print(test := 1) # => 1
print(test) # => 1

As a side note, "walrus" derives from its resemblance to the eye and tusks of a walrus.

:=

en.wikipedia.org

When to use?

To execute an assignment and conditional statement simultaneously

This is code for solving the Fibonacci sequence.

Like this code, you must often implement assignment and conditional statements separately.

def output_fibonacci_1(n):
    one = 0
    two = 1

    next = one + two
    while next < n:
        print(next)
        one, two = two, next
        next = one + two

On the other hand, using the walrus operator, you can do them simultaneously and make your code simpler.

def output_fibonacci_2(n):
    one = 0
    two = 1

    while (next := one + two) < n:
        print(next)
        one, two = two, next

Heads up: assignment expression has the lowest precedence, so you must use brackets in the above code.

6. Expressions — Python 3.12.1 documentation

To use it when in list comprehension

The list comprehension is a typical situation you can use the walrus operator.

Without it, you must write i**2 twice in this code, because it is only used for the conditional statement.

l = [1, 10, 4, 7, 8]

l = [i**2 for i in l if i**2 > 50]

The walrus operator can make the code simpler.

l = [y for i in l if (y := i**2) > 50]

Impression on Implementation

  • I thought it was a syntactically big change. I should grasp changes of language carefully.
  • As is mentioned in the official document, I should limit the use of it only when you can reduce the complexity of your code.

    Try to limit use of the walrus operator to clean cases that reduce complexity and improve readability.