Automate the boring stuff with Python review

A few weeks ago I finished reading “Automate the boring stuff with Python” from Al Sweigart, In this review, I’ll try to make a good review of the book and talk about the main chapters.

It’s a book recommended for novices, for me, it’s a good book for beginners, but for people who already know how to program in other dynamic and interpreted programming language, I think is not necessary to read this book, go ahead and read something more advanced.

TL;DR: If you know how to program in another interpreted programming language like Ruby, go ahead and read something more advanced, if you are a beginner, start with this book, it’s a very good book to start coding.

If you want to know more about this book, you can check here: https://automatetheboringstuff.com/

Print / Publisher

The book publisher is the famous no starch press, that have a lot of famous books like:

And much more, I think every experienced programmer knows nostarch very well because they have a lot of famous and good books, if you are a beginner, you can trust them.

I didn’t have the physical edition of this book, I’ve read the digital edition on my Kindle Paperwhite, read technical books on digital readers is always it’s always a fear because some books don’t look good at the small screens, especially the code snippets, but this was not the problem of this book, I think large publishers like nostarch or O’Reilly you’ll never going to have this problem.

The physical edition I think should be excellent too, because I have other books from nostarch and no one disappointed me.

Content

The book is divided into two parts, the first one talks about all the basic things of any programming language like variables, loops, ifs/else and etc. This part is good to understand the basic of python. This part covers all between variables and manipulates text.

The second part and the most interesting show you how to automate boring stuff with python in a simple way, at this part you develop a lot of applications, for example reading Excel documents. This part has eleven chapters, talking about a lot of things, this is the best part of my opinion, the author shows you how to do a lot of cool things like web scraping 🙂

Final Conclusions

The most interesting is the second part when you create a lot of applications to automate the boring stuff, but the first part is good to understand and knows the python basic. One thing that I loved in this book is the fact that it has a lot of exercises (with answers) to you train what you learned in the chapter, if you do all the exercises your read will be funnier and you’ll learn much more.

The only bad thing on this book is that this is a simple book for people that already know how to program, but this is not a problem because the book doesn’t say that is something advanced, but even for who already knows how to program, the second part with practical projects can be very good.

Final thoughts

This is my first book review and I’ll try to get better on the next review posts, I’ll try to review every technical book that I read.

If you want to know more about this book, you can check here: https://automatetheboringstuff.com/

If you have any question that I can help you, please ask! Send an email (otaviopvaladares@gmail.com), pm me on my Twitter or comment on this post!

Follow my blog to get notified every new post:

Migrating from vim to neovim

This week I decided to migrate to neovim, and give it a chance after a recommendation and some discussions about the future of vim text editor.

If you have a question about if you need to start using neovim I pretty recommend that you search on the internet and make your own decision. You can start by reading the following things:

Downloading

The first thing that I loved is the facility on download, at the official repository they provide a lot of good options for each OS, for Linux, an appimage file and that is awesome, for who doesn’t know it is like MAC OS applications file, for MAC OS you can download using brew and for windows you can download using chocolatey.

You can download neovim in the following two sites:

https://github.com/neovim/neovim/wiki/Installing-Neovim#install-from-download https://github.com/neovim/neovim/releases/

As I described I choose the appimage, so I just downloaded and moved it to /usr/local/bin and all works fine, now just type nvim and it will open.

Using the same setup of vim

The next question of everybody is probably “Ok, but I’ll need to configure everything again? All my plugins?” and the answer is No, you won’t.

If you’re coming from vim like me, you can simply type :help nvim-from-vim and follow the instructions, simplifying is just create a file ~/.config/nvim/init.vim that will be like your .vimrc, you’ll paste all your custom config at this file.

touch ~/.config/nvim/init.vim

If you’re a simple guy and just want to use your nvim in the same way as you use your vim, just paste the following commands at your init.vim that you created.

set runtimepath^=~/.vim runtimepath+=~/.vim/after
let &packpath = &runtimepath
source ~/.vimrc

It will route your nvim config to your previous vim setup, but it’s important to know that some plugins may not work, nvim isn’t entirely compatible with vim, but almost all plugins work on nvim too, with me, all plugins worked fine.

Different setup for nvim

For a lot of people the previous solution will be satisfying, but for me no. I want to stop using vim, so the previous solution doesn’t solve my problem, I want to have my own nvim setup. Luckily it’s easy too, on vim I use vim-pathogen to manage my plugins, so all my plugins are located at ~/.vim/bundle/, I just need to make a copy of this folder but on my nvim directory.

cp -r ~/.vim/bundle ~/.config/nvim/bundle/

And do the same with the .vimrc file.

cp ~/.vim/.vimrc ~/.config/nvim/init.vim

Now, if I want to modify something, I just need to modify on init.vim as you want, or install plugins at ~/.config/nvim/bundle.

Repository with nvim files

I like to create a Github repo to store my configs, so I just started a git repo at ~/.config/nvim and pushed it, you can find my nvim setup here.

You could find my vim files here but now with neovim, it’s deprecated.

Nvim differences

Neovim has some differences from vim, you can check it by typing :help vim-differences, but the major features (copying from the vim-differences output) is:

  • API
  • Lua scripting
  • Job control
  • Remote plugins
  • Providers
    • Clipboard
    • Node.js plugins
    • Python plugins
    • Ruby plugins
  • Shared data
  • Embedded terminal
  • VimL parser
  • XDG base directories

But I pretty recommend that you read the full documentation at :help vim-differences.

Nvim has some plugins that take advantage of specific nvim features, you can check it here.

Final thoughts

It wasn’t a very long post, and it’s purposeful, I don’t have much to talk about neovim yet, the objective of this post It only talks about how I migrate from vim to neovim. On next weeks I’ll write about my plugins and describing some tricks of my vim/nvim configs.

If you have any questions that I can help you with, please ask! Send an email (otaviopvaladares@gmail.com), pm me on my Twitter or comment on this post!

Follow my blog to get notified every new post:

Logic Programming

Let’s talk about logic programming, I think everybody who completed the college or study computer science by yourself (like me), already have heard about logic programming, what it’s exactly? When talking about programming we have a lot of paradigms of programming languages and logic is one of them, but unfortunately isn’t very popular, to be sincere Prolog is most used by academia. But don’t worry learn logic programming can be good to expand your knowledge and see things from other perspectives, understanding a new paradigm of programming is a new way of thinking.

In this post, I’ll talk about what I’ve liked on Prolog and how to get started.

Warning

  • I’m not an expert of Prolog
  • This post doesn’t have advanced content
  • Every example of this post will be written in Prolog
  • This post has a strong theoretical content, if you don’t like, feel free to jump to "First Steps" paragraph.

“The inception of logic is tied with that of scientific thinking. Logic provides a precise language for the explicit expression of one’s goals, knowledge, and assumptions. Logic provides the foundation for deducing consequences from premises; for studying the truth or falsity of statements given the truth or falsity of other statements; fir establishing the consistency of one’s claims; and for verifying the validity of one’s arguments.” – Sterling, 1986 The art of Prolog.

What is logic?

I think the key to understanding logic programming is not your background in computer systems, the key is your knowledge of philosophy, you need to know and understand what is the Aristotelian logic, I’m not a philosopher so I’ll try to explain from my point of view on the simplest way, not going deep on advanced topics, only a resume.

Let’s go back to our high school and talk about mid 350 B.C, Aristotle the Ancient Greek philosopher developed something named term logic aka traditional logic or Aristotelian logic.

Aristotle

Warning: If you want only the hands-on part, stop here and go to “First Steps”.

Aristotle’s logical work is collected in the six texts that are collectively known as the Organon. Two of these texts, in particular, namely the Prior Analytics and De Interpretatione, contain the heart of Aristotle’s treatment of judgments and formal inference, and it is principally this part of Aristotle’s works that is about term logic.

Aristotle

The fundamental assumption behind the theory is that propositions are composed of two terms, where terms is a part of speech representing something, and that the reasoning process is in turn built from propositions.

Propositions need to follow the Three Laws of Thought.

  • Law of Identity, A is A. Everything is the same as itself.
  • The Law of Noncontradiction, NOT ( A and not A) – Nothing can both exist and not exist at the same time and in the same respect, or no statement can be both true and false.
  • Law of Excluded Middle, EITHER (A or not A) – Something either exists or doesn’t exists, or every statement is either true or false.

This reasoning process is often called syllogism (“conclusion, inference”), that is when you apply deductive reasoning to arrive at a conclusion based on two or more propositions that are asserted or assumed to be true.

The syllogism is basically one conclusion based on prepositions.

When talking about syllogism, the most common example is the one given by Socrates.

All men are mortal.
Socrates is a man.
Therefore, Socrates is mortal.

Each syllogism consists of three parts:

Major premise
Minor premise
Conclusion

In the rest of this text, you’ll learn that Prolog can do that, based on fact and rules.

This is only a simple resume of what is logic and syllogism, if you felt interested, you can continue studying by yourself.

“Logic is an instrument for advancing knowledge”

What is Logic Programming?

Most programmers at day to day work deal with imperative languages, the main characteristic of imperative languages is the way that you change the programs state giving a statement, step by step (How to).

Programs written in a logic programming languages, computation is dealing with relations rather than with single-valued functions, these relations are defined by a set of rules about some problem domain and these rules are written by the programmer, this concept leads us to one of the main characteristics of logic programming:

“Logic programming is composed of two things, the logic, and the control.”

The logic component is the definition of the problem while the control is more like the way to get the solution, the rules.

We can define a logic programming algorithm by the following formula:

Algorithm = Logic + Control

Where “Logic” represents a logic program and “Control” represents different theorem-proving strategies.

Logic programming is a type of programming paradigm which is largely based on formal logic, that’s more like “What is”, with you asking the computer for answers, it is known as “declarative programming”.

So, in a simple conclusion, logic programming is much like telling the system the problem, the rules based on formal logic, the facts, and asking for the answer (declarative) than giving a step by step instructions to solve the problem.

What is Prolog?

Follow my blog to get notified every new post:

It’s hard to talk about logic programming without talk about Prolog. Prolog is a logic programming language based on first-order logic and formal logic, designed in 1970 by Alain Colmerauer. The program logic is expressed in terms of relations, represented as facts and rules. A computation is initiated by running a query over these relations. Today, I think Prolog is the most popular logic programming language.

The name is a French abbreviation for “Programming in Logic”.

First Steps

All the pillars of logic programming inherit from logic (that we studied above), terms and statements.

We’ve three basic statements: Facts, Rules and Queries and a single data structure called Logical Term

Facts

The simplest kind of statement in Prolog is called fact, and we’ll start our study talking about it.

Fact is basically the relation the objects hold between each other:

mother(elizabeth, charles).

This is the most basic example of the fact, it holds the relation between Elizabeth and Charles a tell that this relation is a mother.

We say atoms to refer to the name of the things that the predicate is telling the relations, on this example, Elizabeth and Charles are both atoms.

You can also speak predicate, fact, and predicate means the same.

Note that both predicate and atoms start with a lowercase letter, the reason we’ll talk soon.

A set of facts can describe a situation or a series of relations, which will be used by Prolog to execute computations.

In Prolog, you need to use dot to say that you finished your statement, don’t forget the dot.

With facts we can define simple relations, for example, a family tree, this example is considered the “Hello World program of Prolog”, and that’s what we’re going to do now.

For this example, we’ll use the left side of the Britsh royal family tree. (We’ll use only the left side because the entire tree is too big, and would escape the main goal of this text).

Left side of royal family tree

Ok, take a look at this tree, how many facts can we define? I think that we can define a lot of predicates, since parental relations till dates like birth or marriage.

To keep this example as simple as possible, let’s define only three, mother, father, male/female.

female(elizabeth).
female(charlotte).

male(philip).
male(harry).
male(george).
male(louis).
male(charles).
male(william).

father(philip, charles).
father(charles, william).
father(charles, harry).
father(william, george).
father(william, charlotte).
father(william, louis).

mother(elizabeth, charles).
mother(diana, william).
mother(diana, harry).
mother(catherine, george).
mother(catherine, charlotte).
mother(catherine, louis).

You can download this fact [at this gist.

A little bit big, right? Now imagine if we wrote all the facts about the royal family, like dates, marriage, etc.

Now would be fabulous if we can consult these facts, would it?

Queries

Queries are the second form of a statement in logic programs, they are the way to retrieve information from facts. We can also speak the goal.

A query asks Prolog what’s the relationship between objects, for example, we want to know if Charles is the father of William, just ask for Prolog:

?- father(charles, william).

During this text every time that you see ?- before a statement is because we’re working on query context.

And Prolog will return true, and it will return false with we ask something that’s not true:

?- father(diana, william).

One nice trick is to think like we’re asking a question, and Prolog will respond based on facts that it already knows, this is possible because we’re working with declarative programming.

The prolog interpreter

When working with simple problems like this, we usually load our prolog file into Prolog interpreter to start querying, assuming that you’re using SWI-prlog, you’ve two ways:

  • Start prolog shell using swipl and after this load prolog file writing consult('path/to/file.pl').
  • Already loads swipl with your database, using -s option, for example: swipl -s royal_family.pl

Some useful commands that can help you in your Prolog journey:

  • halt. closes your interpreter.
  • listing. shows facts and rules loaded.
  • help. obviusly.
  • assert(fact). adds fact to your base.
  • retract(fact). removes fact of your base.

Don’t feel scared, this is like any REPL of an interpreted language.

This aspect of Prolog can look strange and make some people feel confused at the beginning but don’t worry.

Syntactically both queries and facts can look the same, but you can easily differ by the context.

The logical variables

Related Posts

Unlike facts or queries, variables aren’t a statement, but we need to talk about it too.

Variables in Prolog is very different from other languages, they don’t store a specific value at is memory, so, the first step is to stop thinking that variables are to store values, not here. Variables in logic programming stand for an unspecified entity and the interpreter will try to instantiate the variables for us respecting the facts previously defined. Let’s understand it better by example, imagine that you want to know who is William’s children?

?- father(william, X).

Remember, this is query context, not fact context.

The first thing we note at this query is that for the first time, we’re using uppercase letter at X, this is because variables in Prolog start with an uppercase letter. This query now has a variable, what’s it means?

If we run the previous query, you’ll get the following result:

X = george

Ok, Prolog has solved it for you, they found that William is the father of George, now he’s telling you that, but… William is father of more children and Prolog has returned only one, simple, when Prolog is promoting something to you and your variable can have more than one result, you can press dot for end your query (signaling to Prolog that this answer is ok for you), or you press semicolon to go to the next answer (this doesn’t work when Prolog found only one possible answer).

?- father(william, X).
X = george ;
X = charlotte ;
X = louis.

Prolog gives to us all possibles value for X.

This can look very hard, but it isn’t when talking about rules this can look more simple. One way to better understand what we’re asking to Prolog is to read the query like:

“Does there exist an X such that William is the father of X?”

Rules

Rules are the third and the most important statement of Prolog.

Rules are the way of define patterns/rules to Prolog make decisions based on facts previously defined. Let’s think about, on our base we’ve all the information about father, moms, and sex. We’re humans and if our intelligence we can make conclusions based on these facts, Prolog can make conclusions too, but we need to teach how to make these conclusions.

For example, we can define who is grandparents of each other, right? What is the rule for define grandparent?

Grandparents Rules

The rule is simple, for someone to be your grandfather, he needs to be the father of your father, right? How do we define that in Prolog? Simple, we create a rule, it will be called grandfather.

grandfather(X, Y) :-
father(X, Z),
father(Z, Y).

We can read this rule like this:

For all X, Y. X is the grandfather of Y, if X is the father of Z and Z is the father of Y.

Now if we reload our base at Prolog interpreter, we can use our new rule! Let’s try it:

?- grandfather(X, louis).
X = charles.

Nice, we have found Louis grandfather and it’s Charles. How our rule behaved when we asked who is the grandfather of Louis?

First, of step, Louis on our rule is the Y, so every Y becomes Louis.

grandfather(X, luis) :-
father(X, Z),
father(Z, louis).

The second step, solve father(Z, louis). and found that Z = william.

grandfather(X, luis) :-
father(X, william),
father(william, louis).

The last step, now fallowing your defined rule, we need to solve father(X, william). to find who is the grandfather of Louis, the answer is X = charles, and we have found our goal.

grandfather(charles, luis) :-
father(charles, william),
father(william, louis).

It’s not that hard, right? The most interesting thing about this rule is that it can find grandchildren too, just replace X by the name of grandfather and find all grandchildren:

?- grandfather(philip, Y).
Y = william,
Y = harry

And obviously, we can make assertions without variables:

?- grandfather(philip, william).
true

You can use one rule to define another rule, for example, you can use grandfather/2 rule, inside the great-grandfather rule.

greatgrandfather(X, Y) :-
father(X, Z),
grandfather(Z, Y).

With this power, you actually can build nice things using logic programming.

Now we know the three states of logic programming, and solved the most basic exercise of Prolog, the “family tree”, this problem as I said, is like the “hello world” of Prolog.

With our current knowledge, we can rewrite the most famous example of a syllogism that we discussed above in Prolog:

All men are mortal.
Socrates is a man.
Therefore, Socrates is mortal.

mortal(X) :- man(X).
man(socrates).

...

? - mortal(socrates).
true

Solving Four color theorem

Check my last posts:

The four color theorem is a nice example of something that would use a lot of lines to be completed in most common programming languages like Java or Python that in Prolog consume only a few lines of code.

The four color theorem is a theorem of mathematics. It says that in any plane surface with regions in it (people think of them as maps), the regions can be colored with no more than four colors. Two regions that have a common border must not get the same color. They are called adjacent (next to each other) if they share a segment of the border, not just a point. Interested? Read more about it here.

On this example, I’ll paint the map of an imaginary country that has only five states, I think that’s enough for this exercise.

Map

To get started, the best thing to do is to define the facts, we can start defining the four colors of our map. What colors do you like? Choose four.

color(black).
color(byzantine).
color(sapphire_blue).
color(screamin green).

With the colors of our map defined, it’s time to define the rule of the problem, two adjacent states can’t have the same color. We will need to use the =/= not equal operator.

We’ll create a rule that says "if two states are neighbors they don’t have the same color"

adjacent(state1Color, state2Color) :-
color(state1Color), color(state2Color),
state1Color =/= state2Color.

And now map all states that are adjacent to each other, defining a new rule called country/5.

country(A, B, C, D, E) :-
adjacent(A, B), adjacent(A, C), adjacent(A, D),
adjacent(B, E), adjacent(B, C),
adjacent(C, D), adjacent(C, E),
adjacent(D, E).

Note, if we already defined adjacent(A, C) we don’t need to define adjacent(C,A).

If you open your prolog shell now and call your country rule, you’ll get the output with the colors needed.

?- country(A, B, C, D, E).
A = black,
B = D, D = byzantine,
C = sapphire_blue,
E = screamin_green

If we paint our map again based on Prolog output.

Colored Map

And the problem is done, you can replicate this problem to every map and we’ll have a correct answer.

One courious think about this problem, is that it was the first major theorem to be proved using a computer.

My conclusion about logic programming

Follow my blog to get notified every new post:

On the last months I’ve been studying logic programming and I’m loved it, it opened the doors for a new way of thinking and the way of logic programming works has fascinated me.

Unfortunately, as I said, my feeling is that logic programming and Prolog is most used in academia, when I search for big cases of use, I don’t find many things.

It’s very funny to solve a lot of problems like four color theorem or N-queens problem using Prolog, I think Prolog shines on that kind of problem, I tried to build an API using prolog, it’s possible, but it very complex, it’s not a thing that you’ll choose over tradional languages.

The best thing in Prolog that gained my attention is the capacity of query over the database of facts, for me, it’s incredible how prolog solve and express queries, on this cases, Prolog for me is very straightforward and powerful.

My conclusion is that Prolog is worth learning to open your mind and learn new things, the documentation is good and community too.

What’s next?

If you feel interested in Prolog, you can continue studying by a lot of ways, while writing this post, I was reading Art Of Prolog and it was very good. On the internet, you can find a lot of excellent tutorials, and an official site of SWI-Prolog you can find the documentation and tutorials.

Here’s my list of interesting resources to keep studying Prolog:

Final thought

I’m glad if I helped you understand Prolog or remember it, I hope you enjoyed.

If you have any question that I can help you, please ask! Send an email (otaviopvaladares@gmail.com), pm me on my Twitter or comment on this post!

Appendix

Execute Prolog without installing it

Just enter on this site https://swish.swi-prolog.org/ and start using, on the left side your base and at right bottom corner your queries, just click on "run" and the magic begins.

Reference / Useful Links

Follow my blog to get notified every new post:

Pointers, a brief view

Some weeks ago I was reading Pat Shaughnessy, Ruby Under a Microscope that is an excellent book about all the engineering behinds Ruby language, and when reading, sometimes I was feeling lost with myself when reading some C codes from Ruby implementation then I decided to stop reading the book and start a little review about C programming language because the last time that I wrote some C code that wasn’t on Arduino was ~3 years ago at my university. When I was at my first university, I clearly remember how some students feel lost and some students feel delighted with the theory and concept of pointers, and for me, it was fascinating.

In this post, I’ll try to explain in a simple and practical way all the theory behind C pointers, for on the next posts I write about topics like Static and Dynamic memory allocation and function pointers.

It’s easy to create programs impossible to read and alter if you don’t give the appropriate attention to the pointers that you’re creating.

This post talks about

  • What are pointers
  • How to use pointers
  • Strings and Arrays
  • Pass by reference and pass by value

The computer memory

To understand pointers correctly, first, we need to understand from a top-level view of how the computer memory works.

The computer memory is like an array, is a block of consecutively memory cells order by their addresses, that memory can be manipulated alone or in groups.

Computer Memory

When you create an integer for example:

int counter = 0;

The C Lang picks 4 consecutive memory cells (bytes) from the memory and stores the value that you assigned to the variable.

Memory with integer allocated

And remember each memory cells that you requested to store your integer have a memory address that can be referenced by hexadecimal.

Address of allocated memory

This address will vary on each execution of the program.

To see this address of a variable in C we can use the ampersand operator:

int counter = 0;

printf("Variable Address: %p\n", &counter);
Variable Address: 0x7ffeccd5f0d4

The %p is the correct specifier to an output the memory address.

Another good experiment to do is to create two variables and see the address of each one:

int counter = 0;
int age = 0;


printf("Variable Address: %p\n", &counter);
printf("Variable Address: %p\n", &age);
Variable Address: 0x7ffe3606fd60
Variable Address: 0x7ffe3606fd64

Pay attention to how C allocates the variable age exactly 4 bytes after the first one, this is because the integer needs 4 bytes to be stored.

The memory address is very interesting and it would be good that we can store it at variables and make nice operations this, and that’s is what pointers consist.

Pointers

Follow my blog to get notified every new post:

Pointers in computer science is an object (usually a variable) that stores the memory address of another value. In C you can declare a pointer using an asterisk before the name of the variable and store an address of a variable of the same type of the pointer.

int counter = 0;

int *pointerCounter = &counter;

Note: Pointers always point to a specific data type, we have one exception on type void.

In C we can see the value stored at the address of pointed memory too, for this, use the asterisk before the name of the pointer:

printf("Pointer value of the pointed memory: %i\n", *pointerCounter);

When a pointer is pointing to a value, the pointer only stores the address of the first byte of this value, when asked, C uses the data type of the pointer to walk over the next `n` bytes to see the full pointed value.

For example, if we’re pointing to an integer and the first byte of this integer is located on 0x7ffe3bc5e164 (see the previus image), the pointer will only store the 0x7ffe3bc5e164 and when asked for the vallue will know to walk +4 right because integer is a datatype of 4 bytes.

To understand better, is nice to examine and run the fallowing example:

int counter = 10;
int *pointerCounter = &counter;

printf("Variable counter address: %p\n", &counter);

printf("Pointer value: %p\n", pointerCounter);

printf("Pointer address: %p\n", &pointerCounter);

printf("Pointer vale of the pointed memory: %i\n", *pointerCounter);
Variable counter address: 0x7ffe19cd26fc
Pointer value: 0x7ffe19cd26fc
Pointer address: 0x7ffe19cd2700
Pointer vale of the pointed memory: 10

It is nice to note that the address of a counter variable is exactly the value pointed by the pointer.

You can do arithmetic and logic operations with pointers too, on this example I sum 10 to the value pointed by pointerCounter.

int counter = 10;
int *pointerCounter = &counter;

*pointerCounter = *pointerCounter + 10;

printf("Pointer vale of the pointed memory: %i\n", *pointerCounter);

printf("Pointer vale of the pointed memory: %i\n", counter);
Pointer vale of the pointed memory: 20
Pointer vale of the pointed memory: 20

“Ok, this is so cool but what can I do with that? I’m only storing the address of some value into one kind of variable.”

With pointers we can do a lot of things, one of the main things is pass values by reference to functions.

Pass by reference and pass by value

When you pass a something to a function in C and make changes to it, that changes won’t exist outside of that function scope, what its means?

void sum(int counter, int age) {
    counter = counter + age;

    printf("counter value: %i\n", counter);
}

int main() {
    int counter = 10;
    int age = 5;

    sum(counter, age);

    printf("response value: %i\n", counter);
}
counter value: 15
response value: 10

On this example, we send the counter variable to the void function sum that stores at counter the sum of counter and age, after this, we print the value of counter inside the function an we see the value 15 printed, but on the printf outside the function at main, we got 10, why? This is what we call pass by value and C passes arguments to function by value, almost all languages pass by value (Java, C#, Ruby, Python), and there isn’t a direct way for the called function to alter a variable in the calling function.

Pass by value

But in C we can do what we call pass by reference, we call the function passing variable address and receiving as a pointer, doing this you’re saying to function “Hey, that’s the value memory address, pick this and alter as you want”.

Pass by reference

void sum(int *counter, int age) {
    *counter = *counter + age;

    printf("counter value: %i\n", *counter);
}

int main() {
    int counter = 10;
    int age = 5;

    sum(&counter, age);

    printf("response value: %i\n", counter);
}

If you run this code you’ll realize that on the last printf the counter is 15, that’s why we’ve passed the counter address to sum function, and at the function, we do the operation directly on the counter address on memory. This is what we call pass by reference, we aren’t passing the value to function but it’s a reference at the memory.

What’s next?

On this post we talked about all the basics behind pointers in C, it’s not a simple topic and if you don’t understand keep trying and run the examples of this post on your own machine, you can also read the sections 5.1 and 5.2 of the legendary K&R C Programming Language that’s, in my opinion, is the best book of ANSI C.

On next three posts I’ll talk more about pointers, I will write about pointers in arrays and strings, dynamic and static memory allocation and function pointers.

Feel free to ask any questions at my twitter, email or comment on this post.

Follow my blog to get notified every new post:

Yet, another post about tell don’t ask

Tell, don’t ask is a useful key concept when talking about object-oriented programming, it consists in to send messages to object (whenever possible) telling objects what you want and that we shouldn’t ask questions to it about its state and make decisions for him, it bypasses encapsulation.

In a more abstract mindset, every object needs to trust that other objects can make decisions alone, without his help.

In a more abstract mindset, every object needs to trust that other objects can make decisions alone, without his help.

If you’re treating objects like structs you’re wrong, the key difference between they is that structs stores only data and was made to represent a record, and this is one of the key difference betwween procedural and object oriented code, objects have behavior.

Stop treating objects like C structures

Structures vs Objects

Defining a simple People struct in C lang and asking for its name if not empty:

struct People {
    int age;
    int weight;
    char name[50];
};
struct People ronald = { name: "", age: 42, weight: 140};

if (strcmp(ronald.name, "") != 0) {
    printf("Person Name: %s\n", ronald.name);
}

This C code in Ruby will look something like this in Ruby:

class People
  attr_reader :name

  def initialize(age:, weight:, name:)
    @age = age
    @weight = weight
    @name = name
  end
end

people = People.new(age: 45, weight: 140, name: "Ronald")

puts "People name: #{people.name}" unless people.name.empty?

The error is treating only like a record, objects have behavior too.

class People
  def initialize(age:, weight:, name:)
    @age = age
    @weight = weight
    @name = name
  end

  def name
    "People name: #{@name}" unless @name.empty?
  end
end

people = People.new(age: 42, weight: 140, name: "Ronald")

puts people.name

Ok… This is just a mediocre example, we only extracted a simple logic, but it was good to see the difference between structs (only data) and objects (behavior/state).

Another Example

Related Posts

Ok, let’s go to another example more real, let’s imagine a simple system that has Books and Stock and we want to store books at stock and print every book of stock:

class Book
  attr_reader :name, :author, :year

  def initialize(name, author, year)
    @name = name
    @author = author
    @year = year
  end
end

class Stock
  attr_reader :capacity, :maximum_capacity
  attr_accessor :books

  def initialize(books: [], capacity: 0, maximum_capacity: 10)
    @books = books
    @capacity = capacity
    @maximum_capacity = maximum_capacity
  end
end

def add_books(book, stock)
  if stock.capacity < stock.maximum_capacity
    stock.books << book
  end
end

def print_books(stock)
  stock.books.each do |book|
    puts "Name: #{book.name}, Author: #{book.author}"
  end
end

book1 = Book.new("Practical Object-Oriented Design in Ruby","Sandi Metz","2012")
book2 = Book.new("Ruby Under a Microscope","Pat Shaughnessy","2013")

stock = Stock.new

add_books(book1, stock)
add_books(book2, stock)

print_books(stock)

This code works good but what’s the problem? This code is so procedural, let’s refactor to become more OOP.

Starting from add_books, it’s asking a lot of information about object(stock) state for making decisions, this is wrong and the logic or add books to stock and check about stock capacity needs to belong to a stock object, with Tell don’t ask thinking this logic would be written like this:

class Stock
  attr_reader :quantity, :maximum_quantity
  attr_accessor :books

  def initialize(books: [], quantity: 0, maximum_quantity: 10)
    @books = books
    @quantity = quantity
    @maximum_quantity = maximum_quantity
  end

  def <<(book)
    books << book unless crowded
  end

  def crowded
    quantity == maximum_quantity
  end
end

Now if we need to one book to stock we just need to write:

stock << book1

We don’t need to ask questions about state and then add, all this logic is encapsulated at an object, much better right?

print_books need to be refactored too, let’s make this logic more OOP, first of all, we can create a method at Stock to print all books and their information.

class Stock
  ...

  def print_books
    books.each do |book|
      puts "Name: #{book.name}, Author: #{book.author}"
    end
  end
end
class Book
  ...

  def full_description
    "Name: #{name}, Author: #{author}, Year: #{year}"
  end
end

Now we refactor again our print_books for just call full_description on each book.

class Stock
  ...

  def print_books
    books.each do |book|
      puts book.full_description
    end
  end
end

Much better our code now, right? If you got lost you can check full code here, or ask me on twitter/email.

Comparing two codes

On the first version of the code, objects was asking for state like this image:

Objects asking for other object state

Now our objects are telling what want:

Objects telling what want

Luckily on internet we’ve hundreds of examples in many languages, you should search for it after read this post.

“The distinction between a message that asks for what the sender wants and a message that tells the receiver how to behave may seem subtle but the consequences are significant. Understanding this difference is a key part of creating reusable classes with well-defined public interfaces”

Final thoughts

This isn’t easy get started thinking like this and correcting your errors, but you need to get used to not ask your object about his state and tell him what you want every that is possible, at the beginning will be hard to think like this (it’s have been difficult for me), but with time you’ll master this skill.

Thanks all for read this post, don’t forget to follow me on twitter, any questions you can send me an email, have good days.

Useful links

Follow my blog to get notified every new post: