Sunday, October 3, 2021

CSS text overflow: ellipsis

Single line ellipsis

Here is the code we use

  <div>
    Hello world once again!
  </div>

1 You first need to set:

  overflow: hidden;
  text-overflow: ellipsis;

Not enough, as you can see

Hello world once again!

2 You need to set a width

  width: 120px;
Hello world once again!

2 Or a max width

  max-width: 120px;
Hello world once again!

Still not enough...

3 You also need...

  white-space: nowrap;
Hello world once again!
Hello world once again!

4 Conclusion

  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 120px;
  white-space: nowrap;

Sunday, April 11, 2021

Javascript closure

This article presents shortly what is the closure concept in Javascript, it also applies to other programming languages.

I write this article because I recently read an article that clearly shows a misunderstanding about the concept.

I am first going to present functions, then closures.

Functions

When you write code you usually write functions that you call at several places in your application.

Functions are useful if they can do something that is different based on the context: arguments you pass.

What is going on about "passing arguments"?

Imagine you are talking to someone, function, you give your name. That person knows your name, he/she could think about you but cannot change your name.

Now, imagine you give to someone a bag containing some candy. You wait as long as that person has your bag, he/she can take some candy or add anything.

In both cases you give something to someone but that person cannot do the same thing with "it".

The same applies to programming (the explanation here is for ´Javascript` but could be different in other programming languages).

function say(you) {
  console.log("Hello", you); // (A)

  you.replace("mes", "y");

  console.log("Hello again", you); // (B)

  you = "Me";

  console.log(you); // (C)
}

let you = "James";

say(you);
// (A) => Hello James
// (B) => Hello again James
// (C) => Me

console.log(you); // (D)
//=> James

Here we define a function named say, the function first outputs the value it receives (A) then calls the replace function, outputs it again and it is unchanged (B).

It then does you = "Me", outputs and now we see "Me" (C).

After the call, the output shows that the you is unchanged (D).

The reason why (B) is unchanged is that strings are immutable, I mean the value cannot be changed, so replace does not change the string, it creates a new one.

At (C) and (D), the you thing is just a way to "communicate with the programming language", it means "from now on when I say 'you', I mean 'James'". The sentence you = "Me" in the say function means "BTW, from now on when I say 'you', I mean 'Me'" (heu).

The say function communicates with the language using the same name (you), but the you from the caller is caller's own way to give a name to "James".

It's like when James talks to me, he says "you" (caller), but when I hear someone in the train saying "you", I know it's not me 😉 (the say function).

What about the bag...

function yoursForAWhile(bag) {
  bag.pop(); // (E)

  bag.push("Jelly beans"); // (F)
}

let bag = ["Chocolate", "Gumdrops"];

yoursForAWhile(bag);

console.log(bag);
//=> Array [ "Chocolate", "Jelly beans" ]

Here the yoursForAWhile function receives a bag (a Javascript array), it first removes something from the bag (pop) (E), then adds something (push) (F). When the caller gets back and outputs the bag content, the bag does not contain "Grumdrops" anymore... the bag is not immutable.

Closures

Closure has nothing to do with passing arguments, it is a place where you know about something.

Imagine you are sitting in a café, in front of you, you see an empty table. A while later some people come at that table, you see them, because you know about the table, nobody gave you the information.

let you = "James";

function say() {
  console.log("Hello", you); // (A)

  you = "Me";

  console.log(you); // (B)
}

say();
// (A) => Hello James
// (B) => Me

console.log(you);
//=> Me

you = "Mary";

say();
// (A) => Hello Mary
// (B) => Me

The code here looks very similar to the previous one (the first example) but the difference is huge.

First, the say function does not expect any parameter hence the call say(). Next, giving the name you to refer to "James" happens before the function definition, this way the function knows about it (the table in the café). This way both the caller and the function are talking about the same thing when they say you.

Because they share the same knowledge, when the say function does you = "Me" it also affects caller's you. And when I write from now on you is "Mary" (you = "Mary), the say function outputs the new name when called again.

(getting back to the train, we are 3 buddies: James, Frank and I. When James tells me something using you both James and Frank mean me 😉)

Friday, December 27, 2019

Write a compiler for brainfunk

I finally published the version 1.0 of the book about writing development tools using the "brainfuck" programming language, see Write a compiler for brainfunk.

The source code is published on Github (rbfc / Ruby brainfuck compiler).

Saturday, October 13, 2018

Postfix expressions revisited

Let's revisit the postfix expressions calculator of the previous entry and improve the code we wrote so far...

Read the full entry at http://www.alef1.org/articles/2012/postfix_expressions_revisited.html.

Note: The article was first published on October 14, 2012

Ruby: postfix expressions

Following a previous entry about the Ruby Fiber class that implemented a Tokenizer, here we implement a postfix expressions calculator.

Read the full entry at http://www.alef1.org/articles/2012/ruby_postfix_expressions.html.

Note: The article was first published on October 14, 2012

Ruby and Fiber

Writing a method that returns at some point and can resume later to return a new value is possible when using the Fiber class. This entry presents the Fiber class by implementing a tokenizer (a tokenizer analyzes an input stream, searches for sequences that matches some patterns and produces tokens).

Read the full entry at http://www.alef1.org/articles/2012/ruby_and_fiber.html.

Note: The article was first published on October 14, 2012

Sunday, September 23, 2018

Mastermind (part 2)

The second part presents an implementation of a simple text user interface (text UI). .

Read the full entry at http://www.alef1.org/articles/2012/mastermind_p2.html.

Note: The article was first published on December 22, 2012