WEBVTT

00:00.000 --> 00:11.000
Hello Kitty, so Kitty will explain some particularities of Python and because Python was based

00:11.000 --> 00:13.000
on some other languages and maybe...

00:13.000 --> 00:15.000
There's my Python in this talk.

00:15.000 --> 00:18.000
OK, it's for a spell or something like that.

00:18.000 --> 00:19.000
Oh my gosh.

00:19.000 --> 00:22.000
I'm not in the good room, sorry, bye.

00:22.000 --> 00:25.000
OK, hello everyone, let's talk about JavaScript.

00:26.000 --> 00:30.000
In, I think I have 25 minutes.

00:30.000 --> 00:33.000
In JavaScript, what is 4 plus 2?

00:33.000 --> 00:36.000
It's 6, what is 4 minus 2?

00:36.000 --> 00:40.000
It's 2, what is 4 minus the string 2?

00:40.000 --> 00:44.000
It's 2, so of course, 4 plus the string 2 is 42.

00:44.000 --> 00:49.000
Let's talk about JavaScript in JavaScript is 1 equal to the string 1.

00:49.000 --> 00:52.000
Hands up for true, hands up for false.

00:52.000 --> 00:56.000
It's true, but if you add an extra equals, it's true, it's false.

00:56.000 --> 00:58.000
It's fine, everything's fine.

00:58.000 --> 01:00.000
Let's talk about JavaScript in JavaScript.

01:00.000 --> 01:02.000
What is the sum of 2 empty arrays?

01:02.000 --> 01:07.000
It's an empty string, what's the sum of an empty array and an empty object?

01:07.000 --> 01:11.000
Object objects, what about the sum of an empty object and an empty array?

01:11.000 --> 01:14.000
Zero, what about the sum of 2 empty objects?

01:14.000 --> 01:17.000
Not a number!

01:17.000 --> 01:21.000
Ah, I see you have seen this talk before.

01:22.000 --> 01:24.000
Oh, Gary Bernhardz, what's talk?

01:24.000 --> 01:27.000
Which is now over a decade old?

01:27.000 --> 01:28.000
I'm sorry.

01:28.000 --> 01:30.000
It was from 2012.

01:30.000 --> 01:33.000
That talk goes on the wats.

01:33.000 --> 01:35.000
I want to do something more.

01:35.000 --> 01:37.000
I want to talk about the wats.

01:37.000 --> 01:40.000
We're going to focus on the wide during this talk and work out.

01:40.000 --> 01:41.000
What the heck was all that?

01:41.000 --> 01:46.000
But well, specifically, does Python have the same problems?

01:46.000 --> 01:50.000
Woo!

01:50.000 --> 01:53.000
In this example, it's an issue of overloaded operators.

01:53.000 --> 01:55.000
The first one we have implicit coercion.

01:55.000 --> 01:58.000
Subtraction is only defined for numerics.

01:58.000 --> 02:00.000
So it coerses the string into a number.

02:00.000 --> 02:04.000
The second one, it's the plus operator that is overloaded.

02:04.000 --> 02:09.000
It can act as both numeric addition or in this case, string concatenation.

02:09.000 --> 02:15.000
In JavaScript, double equals will only compare the values after it coerses it into the same type.

02:15.000 --> 02:21.000
That triple equals will also confirm that the types it equal and exit early if they're not.

02:21.000 --> 02:26.000
And our third case is a little bit more complicated than this.

02:26.000 --> 02:30.000
So to explain this, we're going to have to dive more into the addition operator.

02:30.000 --> 02:31.000
What is it exactly?

02:31.000 --> 02:35.000
Well, thankfully, we have a way to know exactly what the plus does in JavaScript.

02:35.000 --> 02:41.000
Thanks to AgmasScript 2024 standard specification as defined by ECMA262.

02:41.000 --> 02:45.000
This is a standard that defines the JavaScript you use in the browser today,

02:45.000 --> 02:48.000
and it covers JScript as well as actionscript.

02:48.000 --> 02:51.000
And within that standard, we can go into section 138.1,

02:51.000 --> 02:54.000
which denotes the week and then go into the runtime semantics,

02:54.000 --> 02:56.000
which then denotes the week and go into a value,

02:56.000 --> 02:58.000
it's string on numeric binary expression.

02:58.000 --> 03:01.000
If we go there, it says apply string on numeric binary expression.

03:01.000 --> 03:04.000
And from there, it says exactly what we need to do.

03:04.000 --> 03:07.000
Just that.

03:07.000 --> 03:16.000
Now, if a language has a standard, you probably won't learn how to use the language by trying to read this.

03:16.000 --> 03:20.000
So, but for our purposes, it's useful to see like what a standard looks like,

03:20.000 --> 03:22.000
but let me simplify this down.

03:22.000 --> 03:26.000
Consider the addition of two placeholder values A and B.

03:26.000 --> 03:30.000
Step one, convert A and B to primitives.

03:30.000 --> 03:36.000
If after converting A or B are a string, then can cadinate them together.

03:36.000 --> 03:42.000
Otherwise, convert both to numbers and then return the operation in this case plus,

03:42.000 --> 03:45.000
who can see where the problem starts.

03:45.000 --> 03:49.000
To primitive is also its own separate defined method,

03:49.000 --> 03:54.000
where if it is an object, then first try to get the value of that object.

03:54.000 --> 03:58.000
And if that itself is not an object, then return it.

03:58.000 --> 04:01.000
Otherwise, can't the object to a string.

04:01.000 --> 04:04.000
And then return it, and if it wasn't an object in the first place,

04:04.000 --> 04:06.000
then you'll find you're already in a primitive.

04:06.000 --> 04:10.000
So, let's try one of our examples, empty array and empty object.

04:10.000 --> 04:14.000
According to our algorithm, the first thing we need to do is convert both to primitives.

04:14.000 --> 04:19.000
So, bringing up that algorithm, we start by converting the empty array into a primitive.

04:19.000 --> 04:24.000
So, we try the type of, which is an object, so we have to go further,

04:24.000 --> 04:25.000
and so we check the value of.

04:25.000 --> 04:29.000
And the value of an empty list is an empty list,

04:29.000 --> 04:32.000
and if we cast that to a string, it's an empty string.

04:32.000 --> 04:34.000
Well, how does that work?

04:34.000 --> 04:39.000
Well, this is defined because if you take an array and you go to string on it,

04:39.000 --> 04:43.000
it calls the join of all the elements in that string.

04:43.000 --> 04:47.000
So, if we join the array 1, 2, 3, we'll get 1, 2, 3,

04:47.000 --> 04:51.000
and if it's an empty string, empty list, it will be an empty string.

04:51.000 --> 04:53.000
This makes sense.

04:53.000 --> 04:55.000
So, we can do the exact same thing to object.

04:55.000 --> 04:58.000
We first check what's the type of an object, it's an object,

04:58.000 --> 05:00.000
and what is the value of that?

05:00.000 --> 05:03.000
Well, it's still the same squiggly brackets, hello again,

05:03.000 --> 05:06.000
and then if we try to cast that to a string, of course, we get object object.

05:06.000 --> 05:08.000
Well, how does that happen?

05:08.000 --> 05:10.000
Well, again, it's defined.

05:10.000 --> 05:13.000
If you call two string from an object,

05:13.000 --> 05:17.000
the method will return the string object tag,

05:17.000 --> 05:20.000
where tag is determined by the object type,

05:20.000 --> 05:23.000
or in this case, literally, the string object.

05:23.000 --> 05:27.000
So, in JavaScript, any time you try to do a two string on an object,

05:27.000 --> 05:30.000
and you get this, mostly in your console error logs,

05:30.000 --> 05:33.000
that is what is supposed to happen.

05:33.000 --> 05:37.000
A lot of programming languages will instead have this type of method,

05:37.000 --> 05:41.000
give a string-based representation of the contents of the object,

05:41.000 --> 05:44.000
but here, it's hopefully telling you, yes, I am object.

05:44.000 --> 05:49.000
You can use Core JavaScript to get the contents of an object

05:49.000 --> 05:51.000
by using stringify.

05:51.000 --> 05:54.000
Instead, JSON.stringify will give you a stringy representation

05:54.000 --> 05:56.000
of the contents of an object.

05:56.000 --> 06:00.000
So, we know what the primitive types for our two objects are,

06:00.000 --> 06:03.000
and so we can start putting them together.

06:03.000 --> 06:05.000
We can concatenate an empty string, an empty object,

06:05.000 --> 06:08.000
and so we know that the concatenation of an empty list,

06:08.000 --> 06:10.000
an empty object, is object object.

06:10.000 --> 06:12.000
Great, and we can do the same thing for two empty lists.

06:12.000 --> 06:15.000
We can concatenate their two primitive together,

06:15.000 --> 06:17.000
and we know that it's an empty string.

06:17.000 --> 06:20.000
But what about the other permutations?

06:20.000 --> 06:22.000
Because we know that they don't match,

06:22.000 --> 06:24.000
and we would presume that, in JavaScript,

06:24.000 --> 06:26.000
addition would be commutative, A and B

06:26.000 --> 06:28.000
as the same as B plus A.

06:28.000 --> 06:31.000
So, based on our knowledge, we know that something's not right here.

06:31.000 --> 06:32.000
But guess what?

06:32.000 --> 06:34.000
That's defined in this specification.

06:34.000 --> 06:37.000
Well, because in the runtime semantics,

06:37.000 --> 06:40.000
it says what to do if you have an empty object,

06:40.000 --> 06:44.000
or in this case an empty block, is to return empty.

06:44.000 --> 06:48.000
So, when we have an empty object here,

06:48.000 --> 06:51.000
that's actually being interpreted as an empty block.

06:51.000 --> 06:55.000
So, when we try to do anything with an empty block,

06:55.000 --> 06:58.000
it actually does unary addition,

06:58.000 --> 07:02.000
which tries to then, as per the specifications,

07:02.000 --> 07:04.000
cast it to a number.

07:04.000 --> 07:06.000
And in this case, we know that the primitive,

07:06.000 --> 07:08.000
this is an empty string, an empty string, is falsely,

07:08.000 --> 07:10.000
and so it's zero.

07:10.000 --> 07:14.000
And that is actually defined as what happens

07:14.000 --> 07:17.000
when you have a white space, this term is zero.

07:17.000 --> 07:20.000
So, if we try to do the same thing with our objects,

07:20.000 --> 07:23.000
we're trying to add together two objects,

07:23.000 --> 07:24.000
which is actually an empty block,

07:24.000 --> 07:26.000
and a unary addition of an object,

07:26.000 --> 07:28.000
and we know that the primitive of the object

07:28.000 --> 07:32.000
starts with a bracket, which is not a number.

07:32.000 --> 07:35.000
And therefore, we have our entire collection of things

07:35.000 --> 07:38.000
that we know exactly what's going on, except I cheated.

07:38.000 --> 07:42.000
Earlier, I was wrapping the objects in parentheses

07:42.000 --> 07:46.000
to make sure that I could actually get the value of an empty object,

07:46.000 --> 07:48.000
as a switch to an empty block.

07:48.000 --> 07:52.000
And so, this original example will run correctly

07:52.000 --> 07:54.000
if you actually use variables,

07:54.000 --> 07:56.000
and not just throw this in a repel,

07:56.000 --> 08:00.000
because those last two examples are doing strange things.

08:00.000 --> 08:03.000
So, you can actually preserve community

08:03.000 --> 08:05.000
if you use parentheses.

08:05.000 --> 08:06.000
Ta-da!

08:06.000 --> 08:08.000
Ta-da!

08:08.000 --> 08:09.000
Ta-da!

08:09.000 --> 08:11.000
Ta-da!

08:11.000 --> 08:13.000
Ta-da!

08:13.000 --> 08:15.000
So, now's the question.

08:16.000 --> 08:19.000
Does Python have this particular peculiarity?

08:19.000 --> 08:23.000
Is Python prone to the same potential problem, perhaps?

08:23.000 --> 08:29.000
Well, in Python, what is the concatenation of two empty lists?

08:29.000 --> 08:31.000
It's an empty list.

08:31.000 --> 08:35.000
What about the concatenation of an empty list, an empty dictionary?

08:35.000 --> 08:36.000
It's a typo.

08:36.000 --> 08:40.000
What about the concatenation of an empty dictionary, an empty list?

08:40.000 --> 08:41.000
It's a typo.

08:41.000 --> 08:44.000
What about the concatenation of two empty dictionaries?

08:44.000 --> 08:47.000
It's a typo.

08:47.000 --> 08:49.000
But different typoers.

08:49.000 --> 08:51.000
So, to see what's going on here,

08:51.000 --> 08:54.000
we're going to have to look at the Python standard.

08:54.000 --> 09:05.000
Now, Python, like a few modern programming languages,

09:05.000 --> 09:07.000
doesn't have a capital S standard.

09:07.000 --> 09:10.000
Some languages have standards, held by bodies like ISO,

09:10.000 --> 09:12.000
ECMA, I tribally, etc.

09:12.000 --> 09:14.000
But some have defector standards.

09:14.000 --> 09:16.000
In PHP, we have Python enhancement proposals,

09:16.000 --> 09:18.000
and we have the defector standard,

09:18.000 --> 09:21.000
which is the C-Python implementation of Python,

09:21.000 --> 09:23.000
which we can reference.

09:23.000 --> 09:26.000
And in C-Python, there is the Python standard library.

09:26.000 --> 09:29.000
And within that, there is documentation for sequence types,

09:29.000 --> 09:31.000
that being list, tuple, and range.

09:31.000 --> 09:34.000
And within that, it includes that the plus parameter

09:34.000 --> 09:37.000
does concatenation of two types.

09:37.000 --> 09:40.000
And if we were to search the source code for this error,

09:40.000 --> 09:42.000
can only concatenate list.

09:42.000 --> 09:46.000
We would get the C-Python C implementation of

09:46.000 --> 09:48.000
what list concatenation does.

09:48.000 --> 09:52.000
And the first thing it does is goes, if B is not a list,

09:52.000 --> 09:56.000
and we can also see this within Python itself

09:56.000 --> 09:59.000
in a roundabout way, because the Python language

09:59.000 --> 10:01.000
refers to special method names,

10:01.000 --> 10:04.000
also known as double underscores,

10:04.000 --> 10:09.000
Australia, Dundah, nana, nana, nana, nana, nana, nana.

10:09.000 --> 10:12.000
So these double underscores methods in this case,

10:12.000 --> 10:15.000
we have Dundah add, which is defined for all the other

10:15.000 --> 10:16.000
in fixed operators as well,

10:16.000 --> 10:18.000
multiplication, subtraction, etc.

10:18.000 --> 10:23.000
We can check, well, this is a type of list,

10:23.000 --> 10:26.000
and what we can do is instead of having the in fixed operator

10:26.000 --> 10:29.000
between our two lists, we can go list.

10:29.000 --> 10:32.000
Dundah add our two lists and get the same result.

10:32.000 --> 10:35.000
And there are many other Dundah methods implemented in Python,

10:35.000 --> 10:38.000
including the doc string, which will give you

10:38.000 --> 10:41.000
what the doc string of the concatenation method

10:41.000 --> 10:45.000
Dundah add is in the Python implementation,

10:45.000 --> 10:48.000
which is overloaded by other things.

10:48.000 --> 10:51.000
For shadowing is a literary device, where we can also use

10:51.000 --> 10:54.000
the same logic to check our other concatenation methods.

10:54.000 --> 10:57.000
In this case, we can see that this is a dict,

10:57.000 --> 10:59.000
and if we go Dundah add on a dict,

10:59.000 --> 11:02.000
we can see that it's attribute error.

11:02.000 --> 11:04.000
This is not implemented.

11:04.000 --> 11:07.000
This also explains why the different type errors

11:07.000 --> 11:09.000
we're getting different descriptions depending on whether we

11:09.000 --> 11:12.000
will list forward or dict forward.

11:12.000 --> 11:16.000
Take a drink of Watergate.

11:16.000 --> 11:19.000
All right, let's talk about Java.

11:19.000 --> 11:23.000
In Java, if I declare an integer A as 127,

11:23.000 --> 11:26.000
an integer B as 127 is A equal to B,

11:26.000 --> 11:31.000
hands up for true, hands up for false.

11:31.000 --> 11:34.000
Guys, come on.

11:34.000 --> 11:37.000
In Java, if I declare an integer A as 128,

11:37.000 --> 11:40.000
and B as 128 is A equal to B, hands up for true,

11:40.000 --> 11:42.000
hands up for false.

11:42.000 --> 11:46.000
There we go. We're learning.

11:46.000 --> 11:48.000
So let's talk about Java.

11:48.000 --> 11:51.000
When you're running Java, you're probably running something like OpenJDK,

11:51.000 --> 11:54.000
and in OpenJDK, there is an optimization to create

11:54.000 --> 11:58.000
a list of integers for you from negative 128 to 127,

11:58.000 --> 12:01.000
and if you define an integer within this cache,

12:01.000 --> 12:03.000
it points to that part of memory.

12:03.000 --> 12:07.000
But in this case, we're using integers,

12:07.000 --> 12:10.000
and double equals for capital I integers,

12:10.000 --> 12:13.000
is identity checking.

12:13.000 --> 12:16.000
And if you declare your integers outside of this case,

12:16.000 --> 12:19.000
you will actually point to other parts of memory,

12:19.000 --> 12:21.000
and these are not the same object,

12:21.000 --> 12:25.000
or identity check fails.

12:25.000 --> 12:29.000
If you're working with capital I integers in Java,

12:29.000 --> 12:32.000
you need to use dot equals to check for a quality,

12:32.000 --> 12:34.000
but if you drop down to ints,

12:34.000 --> 12:39.000
you can actually do double equals as being a quality.

12:39.000 --> 12:42.000
So Python doesn't have this issue, right?

12:42.000 --> 12:46.000
If I declare an Python, the variable A as one,

12:46.000 --> 12:50.000
there's 256 and B as 256 is AB.

12:50.000 --> 12:54.000
Hands up the true, hands up the false.

12:54.000 --> 12:57.000
It's true, oh my god, there's no trick questions.

12:57.000 --> 13:03.000
If I declare in Python, variable A is 256 and B is 256 and AB.

13:03.000 --> 13:06.000
Hands up the true, hands up the false.

13:06.000 --> 13:09.000
Great, but if I declare it on the same line,

13:09.000 --> 13:12.000
and then check again, they are.

13:12.000 --> 13:15.000
Let's talk about Python.

13:16.000 --> 13:18.000
In Python, when you load the interpreter,

13:18.000 --> 13:20.000
you're probably using C Python,

13:20.000 --> 13:23.000
and an optimization of C Python is to create a list of integers

13:23.000 --> 13:26.000
from negative 5 to 256 for you,

13:26.000 --> 13:28.000
and when you assign that variable,

13:28.000 --> 13:30.000
it can point to that part of memory.

13:30.000 --> 13:32.000
So when we declare A and B is 256,

13:32.000 --> 13:34.000
where point is to that same part of memory,

13:34.000 --> 13:37.000
and if we ask for is, it's an identity check.

13:37.000 --> 13:39.000
These actually are the same thing,

13:39.000 --> 13:41.000
not that they're represented values are equal,

13:41.000 --> 13:43.000
is this the same thing,

13:43.000 --> 13:45.000
and in this case, they are.

13:45.000 --> 13:49.000
But if we declare a variables outside of this integer case range,

13:49.000 --> 13:51.000
we're assigning them to different parts of memory,

13:51.000 --> 13:53.000
and so they are not the same object except,

13:53.000 --> 13:55.000
if you define them on the same line,

13:55.000 --> 13:58.000
and optimization only allocates the memory once,

13:58.000 --> 14:01.000
and so when identity checks exceeds,

14:01.000 --> 14:05.000
the way to avoid this in Python is simple.

14:05.000 --> 14:08.000
Don't use is, is equals.

14:08.000 --> 14:11.000
If you want to check it for a quality user quality,

14:11.000 --> 14:13.000
a quality, double equals,

14:13.000 --> 14:15.000
a quality is the same in every language, right?

14:15.000 --> 14:17.000
Let's talk about Pell.

14:19.000 --> 14:23.000
In Pell, if I want to check if the string A is equal to string B,

14:23.000 --> 14:25.000
I can do a print statement and tell me if they match or not.

14:25.000 --> 14:28.000
So, who thinks that this will print match?

14:28.000 --> 14:30.000
Who thinks that this won't print anything?

14:30.000 --> 14:32.000
What do you mean A is equal to B?

14:34.000 --> 14:38.000
In Pell, if we want to check for numeric equality,

14:39.000 --> 14:42.000
then we use double equals, and in this case in Pell,

14:42.000 --> 14:45.000
it will cast both sides to numbers.

14:46.000 --> 14:48.000
So, if we actually want to do string equality in Pell,

14:48.000 --> 14:53.000
we should use EQ to make sure that we're actually working in the type we meant.

14:54.000 --> 14:56.000
Let's talk about bash.

14:56.000 --> 14:59.000
In bash, I can use conditions to test values,

14:59.000 --> 15:05.000
so I can do if A is equal to B, then print match, otherwise print nothing.

15:05.000 --> 15:07.000
Who thinks this will print match?

15:07.000 --> 15:09.000
Who thinks this won't?

15:09.000 --> 15:11.000
What do you mean by match?

15:12.000 --> 15:18.000
Because in bash, EQ and N E are arithmetic binary operators.

15:18.000 --> 15:22.000
Because they will cast the things as if they were numbers,

15:22.000 --> 15:25.000
and in this case A and B both cast down to zero and so they're the same.

15:25.000 --> 15:30.000
So, in bash, you should use double equals for string equality.

15:30.000 --> 15:33.000
Double equals the same everywhere, y'all.

15:34.000 --> 15:38.000
So, does Python have this particular issue?

15:38.000 --> 15:43.000
Well, at the very least, double equals and done to EQ, they're the same.

15:43.000 --> 15:46.000
They're the exact same thing, so we don't have to worry about that.

15:46.000 --> 15:48.000
But what does this actually do?

15:48.000 --> 15:55.000
Well, by default, object implements done to EQ as an identity check.

15:55.000 --> 16:01.000
It's onto the lower level of objects to define what EQ means for them.

16:03.000 --> 16:08.000
Different standard types will override this implementation, depending on what's logical.

16:08.000 --> 16:13.000
So, maybe for some complex class that you've had, you'd implement your own words,

16:13.000 --> 16:18.000
like check that the first and last name of the same and then this is the same person or something like that.

16:18.000 --> 16:20.000
You can override this.

16:20.000 --> 16:25.000
But we had overriding, with just using the standard language.

16:25.000 --> 16:27.000
We had some problems.

16:27.000 --> 16:29.000
Thankfully, had.

16:29.000 --> 16:31.000
Let's talk about Python too.

16:32.000 --> 16:36.000
In Python too, is full less than 2?

16:36.000 --> 16:39.000
No, okay, so, called Python 2 knows math.

16:39.000 --> 16:42.000
Great. So, we know that 4 is greater than 2.

16:42.000 --> 16:44.000
Yes, okay, excellent.

16:44.000 --> 16:47.000
So, is 4 greater than the string 2?

16:47.000 --> 16:49.000
No.

16:49.000 --> 16:54.000
So, the string 4 is that greater than 2?

16:54.000 --> 16:56.000
Well, yes, let's keep going.

16:56.000 --> 17:00.000
Is 4 less than a list of just 4?

17:00.000 --> 17:01.000
Yes.

17:01.000 --> 17:03.000
Is it also less than a string of 4?

17:03.000 --> 17:04.000
Yes.

17:04.000 --> 17:07.000
Is it also less than a 2 pull of just 4?

17:07.000 --> 17:08.000
Yes.

17:08.000 --> 17:12.000
Let's talk about Python 2.

17:12.000 --> 17:16.000
Python 2 7 defines comparisons thusly.

17:16.000 --> 17:21.000
Objects are different types, except different numeric types, and different string types, never compare equal.

17:21.000 --> 17:29.000
Subjects are ordered consistently, but arbitrarily, so that sorting a heterogeneous array yields a consistent result.

17:29.000 --> 17:34.000
A C Python implementation detail of that.

17:34.000 --> 17:41.000
Different types, except numbers are ordered by their type names.

17:41.000 --> 17:48.000
An integer comes before a list, comes before a string, comes before a tuple.

17:48.000 --> 17:53.000
Now, I think we all understand that the way to avoid this is,

17:54.000 --> 17:57.000
God, it's been 5 years, please stop using Python 2.

17:57.000 --> 17:58.000
Yes.

17:58.000 --> 17:59.000
Agreed?

17:59.000 --> 18:00.000
Okay, great.

18:00.000 --> 18:01.000
Good.

18:01.000 --> 18:02.000
Yes.

18:02.000 --> 18:05.000
Okay, great.

18:05.000 --> 18:08.000
If you've only ever had to use Python 3, great.

18:08.000 --> 18:09.000
That's great.

18:09.000 --> 18:11.000
You've never had to deal with this.

18:11.000 --> 18:15.000
Particularly because if you try to do the same thing in Python 3, you get a type error.

18:15.000 --> 18:16.000
Yeah.

18:16.000 --> 18:22.000
Saying that the less than is not supported between instances of and list.

18:22.000 --> 18:23.000
And very helpful.

18:23.000 --> 18:32.000
The Python 3 tutorial says in the data structure section, rather than providing an arbitrary ordering the interpretable raise a type error.

18:32.000 --> 18:33.000
Amazing.

18:33.000 --> 18:34.000
Excellent.

18:34.000 --> 18:37.000
One last bugbear to worry about.

18:37.000 --> 18:40.000
Let's talk about elixir.

18:40.000 --> 18:48.000
In elixir, if I want to map over a range, and in this case, for every element in this range, I want to get the square number.

18:48.000 --> 18:51.000
I'd get a list of the first 5 square numbers.

18:51.000 --> 18:52.000
Yeah?

18:52.000 --> 18:53.000
Cool.

18:53.000 --> 18:59.000
I did the same thing, but changed the range from 1 to 5 to be 6 to 10.

18:59.000 --> 19:02.000
I guess, wearing.

19:02.000 --> 19:04.000
Well, something's going on here.

19:04.000 --> 19:05.000
Let's investigate further.

19:05.000 --> 19:12.000
If instead, I was to assign the result of this mapping into a variable.

19:12.000 --> 19:16.000
And then iterate over that variable and use IO.puts.

19:16.000 --> 19:19.000
I would get the expected list of numbers.

19:19.000 --> 19:22.000
So, what did our first example break in our second one, didn't?

19:22.000 --> 19:24.000
Well, let's try a different range.

19:24.000 --> 19:29.000
Let's say random numbers off the top of my head are 65 to 90.

19:29.000 --> 19:37.000
And we'll just return as is.

19:37.000 --> 19:43.000
For those who aren't familiar with different encoding standards, good.

19:43.000 --> 19:50.000
But also let me teach you that in 8-bit variable encoding ASCII, ASCII starts at sequence

19:50.000 --> 19:52.000
capital A is 65.

19:52.000 --> 19:54.000
I haven't available 255 characters.

19:54.000 --> 19:57.000
So, we get the alphabet.

19:57.000 --> 19:59.000
Because ASCII is cool.

19:59.000 --> 20:04.000
Elixir was built on top of Erlang, and Erlang dates back to the mid 80s.

20:04.000 --> 20:10.000
And in many languages, strings are just a list of characters, but in Erlang strings are a list of

20:10.000 --> 20:13.000
integers representing their ASCII character code points.

20:13.000 --> 20:19.000
So, in Elixir, if it sees a list of numbers that look like ASCII code points, it thinks it's a string.

20:19.000 --> 20:21.000
Cool.

20:21.000 --> 20:24.000
Despite that, have this problem.

20:24.000 --> 20:29.000
In Python, if I import date time from the standard library and have a variable now as date

20:29.000 --> 20:36.000
time date time now, and I print the result of now, I get a nicely formatted date for my particular locale.

20:36.000 --> 20:43.000
And if I ask just for now, I get something that looks very weird to anyone who's not a programmer.

20:43.000 --> 20:45.000
One of these is human readable.

20:45.000 --> 20:50.000
The other one might confuse as it appears printed on or received from a coffee shop ask me how I know.

20:50.000 --> 20:56.000
In this case, when we print, we're getting the string representation of an object something which is readable, but when we don't print,

20:56.000 --> 21:02.000
we're getting the rep or representation, which clearly defines that this is a date time object.

21:02.000 --> 21:09.000
It's important to remember this one if you're working in the Python shell or a rep or a Python notebook.

21:09.000 --> 21:15.000
Because if you just try to get the rep of an object as your output, it will not work if you try to convert it to a script.

21:15.000 --> 21:24.000
And it may or may not return a different output to what a string representation would ask me how I know.

21:24.000 --> 21:26.000
Let's talk about PowerShell.

21:26.000 --> 21:28.000
This is the last word.

21:29.000 --> 21:35.000
If I check if 36 is greater than 42, print true or print false, who thinks this will be true?

21:35.000 --> 21:37.000
Who thinks this will be false?

21:37.000 --> 21:41.000
Great. PowerShell understands math. We all understand math. This is great.

21:41.000 --> 21:49.000
So if I try the reverse, if I try it is 32, less than 42, who thinks this will print true? Who thinks this will print false?

21:49.000 --> 22:05.000
So PowerShell is a combination compiler and interpreter. And in this case, that is in greater than.

22:05.000 --> 22:08.000
That is file redirection.

22:08.000 --> 22:13.000
I have a file called 42 with the contents of 36.

22:13.000 --> 22:19.000
But in this case, the file redirection operation was successful and returned to no value.

22:19.000 --> 22:24.000
But because no value is false, the false side of the conditional was invoked.

22:24.000 --> 22:35.000
So the powerShell.ca, the greater than operator, shouldn't be confused with the greater than comparison operator as often denoted by alligators in other languages.

22:35.000 --> 22:37.000
And then it shows an example.

22:37.000 --> 22:42.000
It shows my example because the powerShell docks are open source.

22:42.000 --> 22:48.000
I got code and powerShell before I got code and see Python, Jesus.

22:48.000 --> 22:57.000
The way to avoid this is to use actual comparison operators because like powerShell and like other languages, you don't have to remember which way the crocodile goes.

22:57.000 --> 23:00.000
The crocodile eats the bigger number.

23:00.000 --> 23:03.000
So, does Python have this issue?

23:03.000 --> 23:08.000
In Python, if I check if 36 is greater than 42 in print, the result we get false.

23:08.000 --> 23:14.000
Go in the other way, we get true and we can check our local file system, no files were created.

23:14.000 --> 23:20.000
Except, we've just proven the case for integers.

23:20.000 --> 23:29.000
What about other objects? In Python, if I declare a dictionary of A1 and a dictionary of B2, what is a pipe B?

23:29.000 --> 23:39.000
It's a union, because we have unions now as of Python's 3.9 if you're using a version older than Python 3.9, please upgrade it.

23:39.000 --> 23:43.000
You have no more security updates, 3.9 is great.

23:43.000 --> 23:48.000
But this is a new in-fix operator as per a newer version of Python.

23:48.000 --> 23:54.000
But there are other in-fix operators that do strange things, such as ParkLib.

23:54.000 --> 24:06.000
If I input ParkLib and I define P as a path and I put this path between two normal strings, I get a possex path.

24:06.000 --> 24:16.000
And if I take a string or stringy type object and redirect that into that path, I get a type error for now.

24:16.000 --> 24:21.000
There's nothing stopping us from implementing this in later versions.

24:22.000 --> 24:25.000
We've gone through a number of things, but hopefully you've learnt something new.

24:25.000 --> 24:29.000
And, be curious, with other programming languages, if you're a Python purest, great.

24:29.000 --> 24:33.000
But I know a bunch of different languages, it's helped me understand more about Python along the way.

24:33.000 --> 24:38.000
Resources are up there, I'm out of time, questions outside, cheers.

