🔗 Generalized nullable operators
Today I was writing some Lua code and had to use something like this for the millionth time:
logger:fine("my message " .. (extra_data or ""))
Since operators in Lua fail when applied to null (and thankfully don’t do wat-eseque coercions), whenever I want to perform an operation on a value that may be null, I have to add the neutral element of the operation as a fall back:
print(a + (b or 0)) print(x * (y or 1))
This got me thinking of null-conditional operators such as ?.
that some other languages such as C# have.
Then I wondered: wouldn’t it be nice if “?
” could be a modifier to any operator?
Creating null-checking operators
Here’s the initial sketch of the idea: in case of a “nullable operator”, just cancel the operation when given a null operand: i.e., return the left-hand value in case the right-hand value is null.
Or, expressed in Haskell, here’s a function “rightCheckNullable” that takes a normal operator and converts it to a nullable version checking the right-hand value (”nullable types” are represented as “Maybe” types in Haskell):
rightCheckNullable :: (a -> b -> a) -> (a -> Maybe b -> a) rightCheckNullable fn = a b -> case b of Just x -> fn a x Nothing -> a
Let’s create some nullable operators:
(+?) = rightCheckNullable (+) -- nullable addition (*?) = rightCheckNullable (*) -- nullable multiplication (++?) = rightCheckNullable (++) -- nullable concatenation
And give them a spin:
main = let v1 :: Float v1 = 123 v2 = Nothing v3 :: Maybe Float v3 = Just 456 in do print $ show (v1 +? v2) -- prints 123.0 print $ show (v1 +? v3) -- prints 579.0 print $ show (v1 *? v2) -- prints 123.0 print $ "hello" ++? Just "world" -- prints helloworld print $ "hello" ++? v2 -- prints hello
With something like the above, instead of a + (b or 0) and x * (y or 1), one could write simply:
print(a +? b) print(x *? y)
This could give back some of the terseness we have when null auto-coerces to other types, without surprises with various operations. In JavaScript, null coerces to 0 when it is an integer, which gives us a proper neutral element for addition but not for multiplication.
Null-checking in C#
Note, however, that my choice of picking the right-hand value and checking the left-hand value only was arbitrary (though it works well for the examples above).
In C#, operations on nullable types are always lifted: the operators of the original types are extended with a check where, if either of the arguments is null, the result of the operation is null.
In Haskell, this transformation would be the following, taking a function that goes from a’s to b’s producing c’s, and producing an equivalent function that goes from Maybe a’s to Maybe b’s producing Maybe c’s:
bothCheckNullable :: (a -> b -> c) -> (Maybe a -> Maybe b -> Maybe c) bothCheckNullable fn = ma mb -> case ma of Nothing -> Nothing Just a -> case mb of Nothing -> Nothing Just b -> fn a b
(In Haskell, you don’t have to actually write this function, since can use Control.Applicative.liftA2, a generalization of the above, to get the same result)
Checking the left-hand value
This makes me think that my “nullable operator modifier” could be aplied to either side (or both). Note that the syntax for null-conditional in C# is already ?.
, with the question-mark on the left-hand side, since the value being checked for nullity is the left-hand one. We don’t want x?.y
to return y
when x
is null, though. A more sensible semantics for left-hand ? would be a “short-circuiting” one:
leftCheckNullable :: (a -> b -> c) -> (Maybe a -> b -> Maybe c) leftCheckNullable fn = a b -> case a of Just x -> fn x b Nothing -> Nothing
The flood gates are open!
There is still an asymmetry here, as rightCheckNullable is the only one that returns the “other value” when one of them is null.
In fact, we could have six versions of the conversion function: right-check, both-check, left-check, each of them returning the “other value” (as I did with +?) or null. If we called the C#-like version +??, this means addition could be modified into: +?, ?+, ?+?, +??, ??+, ??+??.
(And there could be two more variants of course, ?+?? and ??+?, but coming up with a realistic example using them would be a nice exercise in creative coding.)
But would it make sense to have so many modifiers?
Well, for one, instead of writing this
logger:severe("Error: connection failed" .. (details and (" - details: "..details) or ""))
we could write something like:
logger:severe("Error: connection failed" ..? (" - details: " ..?? details))
I know this is a step into the world of APL, and I’m not arguing this is a great or even good idea, but it was fun to think about, so I thought I’d share.
🔗 A small practical example where Lua’s % behavior is better than C’s
These days I saw on Twitter a comment on how the behavior of the % (remainder) operator for negative numbers is weird in C.
Under what circumstances does someone actually *want* the C behavior, anyway (-5 % 3 == -2; 5 % -3 == 2) ?
— mcc (@mcclure111) April 6, 2015
I’ve seen this discussion come up numerous times in the Lua mailing list over the years. The reason being because Lua does it different, and most languages simply copy the behavior of C.
Today I saw Etiene’s cool demo of a mini JavaScript Duck Hunt clone that she presented at a “intro to programming” workshop for the Women in Leadership event in Bremen, Germany.
It’s a really nice demo of game behavior in a short span of code, and with the environment of Mozilla Thimble, it instantly enticed me to play around with the code and see what happened.
The first thing that came to my attention was that the ducks spawn at position x=0, and this made them “pop” into the screen. I thought that changing the initial value to something like x=-50 would be a small change to try and would produce a smoother effect (just change 0 to -50 in lines 56 and 116).
When I first tried that, the result was that they would show up, but wouldn’t start flapping their wings until they were at x=0. The reason is because the logic to switch sprites is made testing x % 30 for values 0, 10 and 20… and JavaScript’s % operator, like C’s, returns negative remainders for negative divisors.
My quick hack solution was to calculate
var absx = Math.abs(this.x);
(which required me a visit to DuckDuckGo to figure out how to properly say “abs(x)” in JavaScript). This made the birds enter the screen flapping their wings. Yay!
Of course, this is not something you’d want to have to explain in an “intro to programming” workshop. It would be better if the animation “just worked” with that change…
But wait! If you have really sharp eyes, you’ll notice that from -50 to 0, the birds are flapping their wings upwards and from 0 on, they do it downwards. The animation is inverted!
The reason is because operating on abs(x) causes this:
Lua 5.3.0 Copyright (C) 1994-2015 Lua.org, PUC-Rio > for i = -50, 100 do io.write(math.abs(i)%30, " ") end 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 0 1 2 3 4 5 6 7 8 9 10
If I write a one-liner to simulate the sprite logic in Duck Hunt, I get this:
> for i = -50, 100 do r=math.abs(i)%30; io.write(r==0 and "1" or (r==10 and "2" or (r==20 and "3" or ".") ) ) end 3.........2.........1.........3.........2.........1.........2.........3.........1.........2.........3.........1.........2.........3.........1.........2
Indeed, it’s going 3,2,1, 3,2,1 at the negative numbers and then 1,2,3, 1,2,3 at the positive ones. But let’s just drop the math.abs in Lua and see what happens:
> for i = -50, 100 do r=i%30; io.write(r==0 and "1" or (r==10 and "2" or (r==20 and "3" or ".") ) ) end 2.........3.........1.........2.........3.........1.........2.........3.........1.........2.........3.........1.........2.........3.........1.........2
We get 1,2,3,1,2,3 all the way!
In my experience, the vast majority of times I used %, it was to tell something to “do this every X steps”, like Etiene does in her Duck Hunt. For this kind of purposes, I’m pretty convinced that Lua’s behavior for % is a lot better. It’s unfortunate that most other languages just decided to follow the example of C.
Of course, there are a million other ways to make the ducks flap their wings, with and without %, that’s not the point. But it intrigued me that, if JavaScript had Lua’s behavior for %, my initial tiny change would have “just worked”!
🔗 A comparison between Linux and FreeBSD ps columns
Here’s a diff between which columns are supported in Linux and FreeBSD ps commands, with aliases cleaned up by hand. The lists were gathered from their respective manpages. This is based on ps from FreeBSD 11.0 and from Linux procps-ng 3.3.9.
--- freebsd-ps-columns.txt 2015-03-15 23:44:58.710635450 -0300 +++ linux-ps-columns.txt 2015-03-15 23:42:43.894637864 -0300 @@ -1,81 +1,84 @@ %cpu %mem -acflag args -class +c +cgroup comm command -cow -cpu -dsiz -emul +eip +esp etime etimes -fib +euser +fgid +fgroup flags +fname +fuid +fuser gid group -inblk -jid -jobc -ktrace +ipcns label -lim -lockname -logname lstart +lsession lwp +machine majflt minflt -msgrcv -msgsnd -mwchan +mntns +netns nice -nivcsw nlwp -nsigs -nswap -nvcsw nwchan -oublk -paddr +ouid pgid pid +pidns +policy ppid pri -re +psr rgid rgroup rss rtprio ruid ruser +sched +seat +sgi_p +sgroup sid sig sigcatch sigignore sigmask -sl -ssiz +size +slice +stackp start +stat state +supgid +supgrp +suser svgid svuid -systime -tdaddr -tdev +sz +thcount +tid time +tname tpgid -tsid -tsiz tt tty ucomm uid -upr -uprocp +unit user -usertime +userns +utsns +uunit vsz wchan -xstat
🔗 Speaking of aging
“How sad it is! I shall grow old, and horrible, and dreadful. But this picture will remain always young. It will never be older than this particular day of June… If it were only the other way!” — Oscar Wilde, The Picture of Dorian Gray
A while ago I realized that, as we live more and more of our lives online, many of us have turned into a sort of reverse Dorian Gray.
We create accounts in service after service, uploading our avatar images. Some of them are periodically updated for various reasons (Facebook in particular), but many of them stay unchanged for years. When was the last time you changed your GMail avatar?
As it happens, our online self keeps that perennial smile, that youthful face that’s sometimes years old by now, while our physical self, the one that’s locked in a room, sitting on a computer as the online self strolls around in cyberspace, ages day by day.
I have friends here on Facebook whose avatars I’ve known for years. Professors are known for having outdated pictures in their websites, with black hair that has long turned gray.
I met a guy at a conference who I expected to be a youthful long-haired dude in his 20s, and was a short-haired man in his late 30s. When I said “oh, you have short hair now!” he smiled, a bit confused, and then remembered his own picture. What is striking is that I should have known, since I knew that picture for over ten years myself, back when I was a dude in my 20s.
As for me, I have one nice pic of myself that I uploaded as an avatar in many services (Twitter, Github, etc) that I’m just too lazy to switch. I like the picture and I actually used it once as a reference at the barbershop when getting a haircut (was I trying to chase my “Dorian’s picture”?). Still, when switching back from my child picture here on Facebook back to my “current” picture, the thought that my usual profile picture is actually from 2011 came to mind. Hence, this picture.

🔗 A story of violence and gender
[Even though the title foretells its content, I’ve been advised to add a trigger warning at the top of this post. It doesn’t hurt to be careful.]
It’s been a few days that I’ve been meaning to write this. I even discussed with a friend two days ago about when would be a good time. Emma Watson’s speech on gender equality yesterday (transcript and video) inspired me to go for it: “if not now, when?”.
I want to touch a delicate subject, which she brought up masterfully: how gender inequality works on men.
The story of any oppression is that of three roles: a mass of oppresed ones; a few who oppress them; and a mass who turns a blind eye, who are oppressors by proxy. This is the story of racism, of religious discrimination, and so on. Ms. Watson’s speech shines a light that the issue of gender equality is even more complex than that. Men are hurting women, and also hurting themselves in the process.
What made me want to write this was something that happened last week. I was with two friends, a guy and a girl, at a bar in a foreign country. (It was in Russia, but it could have been anywhere.) A disgusting scene happened. I didn’t see it firsthand, but the girl who was with us was looking straight at it, so I’ll reproduce her report:
At one point the guy who seemed to be the manager started to harass the waitress, just like that, in front of anyone. She froze. And so did I. She stood still in front of the counter while the man held her from behind rubbing his penis violently against her ass. I watched, petrified. I zoned out of my friends’ conversation. The pleasant look in the girl’s face was gone. After he let her go, I tried to approach her in another corner of the bar. The manager went to annoy two other women who were customers. One of them pulled her arm so he’d let her go. And they stayed in the bar! In the corner of the bar I asked the waitress [using Google Translator] if he was her boyfriend and if she was okay. She didn’t speak English, didn’t answer and just said “it’s okay, it’s okay.”
Of course it was not okay. My friend shared her concern with us. Dismayed as we were with it, our only reaction was to express our impotence with the situation. The reflex instinct of being part of “the mass who turns a blind eye”. We think ourselves better because we don’t do such things (and we probably are). Still, being “oppressors by proxy” is not a place we’re proud to be. Our sense of impotence, however, was very much real.
We said “What can we do?”. She said, “I don’t know, if he does it again I’ll make a scene in this place! A scandal!” Then I said “Women have that option.” I didn’t mean to sound rude, but that’s true. The way things work with men is that if we were to confront the (shirtless, tattooed, long-haired) guy, things would soon go violent. We told our friend: “What can we do? Get into a fist fight in a foreign country?” Her reaction was “Oh, men.”
This story highlights a less-discussed aspect in gender inequality. The prevailing rule of male violence serves not only to harm women, but also to stop other men from taking action. My male friend and I, we both knew we were under an unspoken law that if we were to do something, things would get violent.
(A flashback: The only time in my adult life that I got in a fist fight was years ago, also in Eastern Europe. I was walking down a street with a group of friends. Some guys across the street started yelling at the only woman in our group. She yelled back. They crossed the street and went for her. We stood in the way and it quickly got ugly. I think eventually someone shouted “police” and they ran away. One thing that strikes me from that story is that I’ve rarely retold it, and I’ve never seen any of my friends telling it. Men get ashamed of getting in a fight like that, even if it was for standing up for a woman. The other guys probably just made jokes about beating up some foreigners the next day.)
Back to last week’s story, we all felt the waitress really just meant “please don’t get into this”. Still, I wanted to think of something to do. If were we in our home country, we’d know how to report the manager in a safe way. We didn’t know if he owned the place, if anything we did would just get her fired, or worse. All these things crossed my mind.
We evidently didn’t want to stay in that place and give them any more money, so we spoke of leaving. We were waiting for a local friend, and I could just message him saying we had to leave. Then I told my friend “No, let’s wait for my friend and then we’ll explain him what happened and ask him to talk to her in Russian.” She replied, “Good idea.”
As soon as he arrived I told him the story, and that we wanted him to talk to the waitress about what happened before leaving. He seemed surprised; both with what happened and with our seriousness about it. We called her to our table. My Russian friend talked to her, and she told him that he was her boss, not a boyfriend, that he was “like that” but that it was “okay”. Before leaving the waitress went to my friend and repeated to her “it’s okay, it’s okay”, but her sad look said otherwise.
Even if she did think that enduring that guy was “just part of the job”, I hope that our concern reminded her that no, it’s not okay. And if she already felt it’s not okay (as I think she did), now she knows she’s not alone in thinking that, and that she’s not invisible. I’m very proud of my friend for reaching out for her, and shaking us up to do the same. The next day I had a long conversation about it in the airplane with my male friend who was there. These things matter.
We can’t fight gender inequality only by having women to stand up to men. Men have to stand up against inequality as well. And by “standing up” I don’t mean picking up fights. That is only reinforcing the gender stereotype. It’s a matter of redefining gender roles. I feel that society is slowly making progress (though clearly not at the same pace everywhere), but it’s a struggle into which both women and men need to take part. We men have to learn how.
Follow
🐘 Mastodon ▪ RSS (English), RSS (português), RSS (todos / all)
Last 10 entries
- Western civilization
- Why I no longer say "conservative" when I mean "cautious"
- Sorting "git branch" with most recent branches last
- Frustrating Software
- What every programmer should know about what every programmer should know
- A degradação da web em tempos de IA não é acidental
- There are two very different things called "package managers"
- Last day at Kong
- A Special Hand
- How to change the nmtui background color