Banning Immigrants

Quite a headline, I know. My wife is an immigrant, here on green card. Many of my freinds are also immigrants, here on H1 or F1 visas, either as students or as employees of companies you’ve heard of. Many of them I met in grad school, or at Google, or at summer schools. These immigrants are a massive boon to the US, and Trumps goal of removing them will dramatically hurt our country and remove our influence in the world.

There’s two major peices of news that have popped up in relation to this. The first can be found:


Trump Suspends Visas Allowing Hundreds of Thousands of Foreigners to Work in the U.S. https://www.nytimes.com/2020/06/22/us/politics/trump-h1b-work-visas.html

In the simplest terms, we are shutting down H1-b visas for the remainder of the year to combat job losses from the Coronavirus. There are many sides to this issue.

First there are large tech companies who only hire international employees to undercut the pay Americans would require to work in low to medium skilled tech jobs. This should be illegal. These companies are obviously working in bad faith. By companies I also mean several large municipal governments…

But for other companies this is not the case. I work at Google, if you can pass the interview, no matter what country you live in and abiding by certain laws we will hire you. You get the same pay no matter where you’re from, Google pays in the top 95% tech pay bracket by employed region. We can’t find enough employees in the US, most people just aren’t good enough, and Americans don’t have the best tech skills.


ICE: Foreign Students Must Leave The U.S. If Their Colleges Go Online-Only This Fall https://www.npr.org/sections/coronavirus-live-updates/2020/07/06/888026874/ice-foreign-students-must-leave-the-u-s-if-their-colleges-go-online-only-this-fa

I think this one is quite a bit worse in some ways. One of the biggest bits of soft power the US has is our colleges. Their known around the world as the best. Harvard, MIT, Yale, even our flagship state universities get the best students other countries have to offer. They come here and learn about the US, meet US students, learn US culture, and often stay in the US to become our top researchers and professors at these colleges.

A common complaint would be why not take US students, and honestly, it’s because either they suck at the technical skills needed or they could easily make much more money just going into the business realm. Why would I bother with a PhD when (if I’m good at what my professed skills are) I could just make a six figure salary at Google, or Amazon, or Microsoft. For international students this is often a door into the US.

The US imports much of our talent. We need these students. Sending them back does immeasurable harm to our future.


I’m going to close this post with a personal note. In 2016, right after I was hired at Google, I went to China to see my wifes family. She was denied a new F1 visa, and I had to spend the next year away from her.

By removing these people from the US, what kinds of families are you hurting? What are you doing to people lives? Please think about this.

Sincerely,

Jon

Thank You Google, and Working From Home

With Covid still looming large in the US, the major tech companies are continuing or expanding their work from home allowance. More then that, many of the larger tech companies are allowing workers to take 12-14 weeks of paid carers leave so they can take care of their children during the absence of childcare services.

As a Googler, I’m getting a possible maximum of 14 weeks of carers leave as paid time off. First, I’m extremely grateful to Google for giving me this extra time off. I’ve taken every Tuesday/ Thursday off for the last 2 months, and will be taking every Tuesday/ Wednesday for the next 2 months.  That is 40 days (8 weeks) of paid time off that I’ve been allowed to spend with my daughter.

This is not suppose to be vacation time. While I’m playing with Lyra, my wife is doing her job. She teaches online (through UMass Boston), holds office hours, and prepares for her classes. During the week there is very little free time, and a 20 month old will take over any extra free time you may have.

The days when I work, I shut the door to my room (office) and do all of my work at my desk. Again, I am very grateful to Google for giving us 1000$ to upgrade our home office! It’s amazing how before the Covid outbreak Googlers were getting pessimistic about the company, but there is a massive amount of goodwill thanks to how they are handling this.

The saddest thing about shutting the door is hearing Lyra cry for Dada. If I’m in a meeting and she hears my voice, then all I hear at the door is “Dada, dada”. I don’t know what she thinks of me not being able to go and play with her, but it’s the saddest part of any workday.

I’m very proud to work for a company that takes such good care of it’s employees. When other people were losing their jobs, Google expanded benefits. When other companies canceled internships, Google worked with our internal resources to make our interns able to keep working.

I hope this goodwill keeps on after we all return to the office. I believe Sundar tries to do the right thing. Thank you!

img_20200527_211144

Over-Engineering FizzBuzz

The main language I use in my day-to-day programming life is Common Lisp. It’s a wonderful language with some very powerful tools that most other languages don’t have. How many other languages have the powerful macro system of Lisp? How about generic functions? Not many.


Side note: A generic function is a function you can have many different version of which use a type system to determine which version should be called. This isn’t completely true, but good enough for what I’m writing here.


With this much power we can write code more complex than it ever should be. Let’s use FizzBuzz for an example. The goal of FizzBuzz is to print the numbers from 1 to 100 where if the number is divisible by 3 we print “Fizz”, if it’s divisible by 5 we print “Buzz
and if it’s divisible by 3 and 5 we print “FizzBuzz”. It’s a classical interview problem and now an interview trope.

First, let’s do a simple macro example. I don’t want recursion or multiple function calls or loop iteration in my code, in this example. So I can make a macro that will unroll into a sequence of print statements.

(defmacro stupid-fizz-buzz (c)
  (cond ((> c 100) ())
        ((zerop (mod c 15))
          `(progn
             (print "FizzBuzz")
             (stupid-fizz-buzz ,(1+ c))))
        ((zerop (mod c 3))
          `(progn
             (print "Fizz")
             (stupid-fizz-buzz ,(1+ c))))
        ((zerop (mod c 5))
          `(progn
             (print "Buzz")
             (stupid-fizz-buzz ,(1+ c))))
        (t
          `(progn
             (print ,c)
             (stupid-fizz-buzz ,(1+ c))))))

Changing 100 to 3 and calling macroexpand-all on (stupid-fizz-buzz 1) we get:

(PROGN (PRINT 1) (PROGN (PRINT 2)
  (PROGN (PRINT "Fizz") NIL)))

There are nicer ways to write stupid-fizz-buzz as a macro, but this is a dead simple way.

Also calling (let ((n 1)) (stupid-fizz-buzz n)) won’t work because n isn’t an integer at the time of macro expansion, so some care must be taken. In order for the macro to work the input must be an integer at time of macro-expansion. To fulfill the problem we could give the below inlined function and we should see the unrolled code wherever we call fizz-buzz in our code after compilation.

(declaim (inline fizz-buzz))
(defun fizz-buzz ()
(stupid-fizz-buzz 1))

Perhaps you believe one function should print “Fizz” and another function should print “Buzz”. Also, you love generic functions.

(defparameter *fizz* 3)
(defparameter *buzz* 5)
(defparameter *up-to* 100)

(defgeneric %stupid-fizz-buzz (count))

(defmethod %stupid-fizz-buzz :before ((count integer))
  (when (zerop (mod count *fizz*))
    (format t "Fizz")))

(defmethod %stupid-fizz-buzz :before ((count rational))
  (when (zerop (mod count *buzz*))
    (format t "Buzz")))

(defmethod %stupid-fizz-buzz (count)
  (if (or (zerop (mod count *fizz*))
          (zerop (mod count *buzz*)))
      (format t "~%")
      (format t "~a~%" count))
  (when (< count *up-to*)
    (%stupid-fizz-buzz (1+ count))))

(defun stupid-fizz-buzz ()
  (%stupid-fizz-buzz 1))

 

Here, integer is more exact than rational so the "Fizz" will occur before the "Buzz". Either way, entirely over-engineered… At least the macro version has the benefit of complete loop unrolling.


How should fizz buzz be done.

(defun fizz-buzz ()
  (loop for i from 1 to 100 do
    (when (zerop (mod i 3))
      (format t "Fizz"))
    (when (zerop (mod i 5))
      (format t "Buzz"))
    (if (or (zerop (mod i 3))
            (zerop (mod i 5))))
        (format t "~%")
        (format t "a~%" i))))

Is probably what it should be, you can do a bit nicer if you understand the format directive better.


I hope you had fun in this silly post.

Shout out to @cgay for some spelling errors and the note about the macro not working for (let ((n 1)) (stupid-fizz-buzz n)) .

There’s more examples: https://www.reddit.com/r/lisp/comments/59ikqm/the_most_elegant_implementation_of_fizzbuzz/

Finally, Little one:

img_20200514_130303

Working From Home, 2020

Welcome to an update of working from home, 2020 Covid edition. For those who are new to this blog, or who forgot, I did a post about working from not at work a long while ago: Working From Away. With Covid-19, most programmers are working from home, including me, so I thought it was a good time to discuss working from home again.

img_20200326_120154
And teaching from home!

The major difference this time, is you shouldn’t travel. In my previous post I said I liked working outside the house, usually in a coffee shop. During a pandemic, that’s probably a really bad idea. I would suggest supporting your favorite coffee shop. You probably want to drink there again after the pandemic ends, but you should really choose to stay home.

I’m going to assume you work for a company, and your not a self-employed contractor. If you are a self-employed contractor, you probably already work from home. Good for you!

As a programmer, you probably have a laptop that was issued by your company. This is probably the machine you will be working with. Depending on the company, you may ssh into a physical machine located inside of your company or you may do your work directly on that machine. I don’t find the difference to matter, though I do all of my programming on Emacs in terminal mode.


1. You may choose to work solely with your laptop.

I personally don’t like this scenario. The screen is to small, not enough screen real estate to view all of my code.

2. You may have a monitor.

I have a 27′ monitor. I find it’s a good size, I can easily have two or three side-by-side Emacs buffers up. I also use my laptop screen for web-browsing.

3. You may have more then one extra monitor.

I find two screens to be optimal, one for code and one for non-code. You may like three. I hear Bill Gates prefers his three monitor setup.


Now, where to work. Some people like to sit on a couch. This is terrible for your back, please don’t do this to much.

My wife likes to sit at our dining table. This is fine for small bouts of work, but I don’t want to work at my dining table, I prefer to eat there.

I recently purchased a desk from IKEA: https://www.ikea.com/us/en/p/micke-desk-black-brown-10244743/ . If I had more space I would have ordered a larger desk, but it barely fits!

img_20200311_203327
My daughter trying to build my desk.

img_20200312_163417
Really is the perfext size.

Make sure you have a decent chair.

With a little one, you should also be able to wall yourself away. If I wasn’t in a separate room, little one would never let me get work done! If you don’t have a little one, I would still suggest having a separate room. It gives your life distance from your work.


One last note: Please stay at home. Don’t go to your favorite coffee shop! Feel free to support them though. Help support your local hospitals.

Please read:

https://medium.com/@tomaspueyo/coronavirus-act-today-or-people-will-die-f4d3d9cd99ca

View at Medium.com

Don’t forget to have fun.

img_20200323_183227
And eat bacon, lots of bacon.

Post Thanksgiving

Apologies for the lack of posts, I’ll add them when I can but the mix of a 1 year old, full time job, and research makes making them nearly impossible. A lot has been going on, and I wanted to make a post-thanksgiving post. Namely I want to talk about work.

Currently I’m a level 4 software engineer at Google. It’s not bad work, it can be entertaining and I even get to program in Lisp. If I had to write Java that would be one thing, but Lisp is truly an enjoyable language that deserves much more attention then it’s getting. That, and the pay, make it basically impossible to leave and just work on math. Adding to that the near impossibility of finding a decent academic job makes it the proposition even crazier.

In my spare time, besides spending time with my little one, I’m a PhD student in Operator Algebra’s/ Quantum Information Theory. I’ve been doing way to much reading of C*-Algebras by Example, time that would probably be mostly better spent doing research. That being said, I need a better background in C*-Algebras and this book is wonderful. I feel like I have a decent understanding of AF Algebras!

This seems great, the issue is it’s really hard to do both research and work at the same time. I spend 10-6:30 at work, 6:45-9 with Lyra, and the rest of the time trying to learn math (and cleaning, and a little bit of relaxing). It leaves little time to focus on what I’m passionate about.

I hope this explains the lack of blog posts, there will be some in the future, just sparser then in the past.

Until then, I leave you with:

img_20191118_092533

P.S. I hope to have a video detailing the GNS Construction and the extra part of the proof that every C* algebra is *-isomorphic to a Concrete C* Algebra. It’s a really nice theorem that everyone should see.

P.P.S. You should check out my wife’s thesis here.

Class VS Struct in Lisp Revisited

Last time we tried to test Class VS Struct, and I got several comments on ways I could improve the tests. We will be looking at performance improvements that can be made for defstruct. We will be running on an Intel Core i5 Pixelbook using SBCL (except where CCL is specified).

You can find the code:

https://github.com/Slids/lisp-perf-test/blob/master/class-v-struct-boa.lisp


Random Takes Time

Starting, random adds quite a bit of time. It used enough time to massively obfuscate the time things were taking. We can see how much time random is taking

(time (dotimes (i 1000000000) (random 100)))

Evaluation took:
31.172 seconds of real time
31.168020 seconds of total run time (31.168000 user, 0.000020 system)
99.99% CPU
50,123,948,880 processor cycles
0 bytes consed


Argument Constructors are Bad

The next problem is using the default struct constructor instead of using a a constructor with positional arguments. I say, why should this by slower? They say, it’s a bug. We see:

(defstruct (simple-struct
             (:constructor make-simple-struct
               (slot-1 slot-2 slot-3)))
             (slot-1)
             (slot-2)
             (slot-3))
(time (dotimes (i 1000000000)
        (make-simple-struct 1 2 3)))

Evaluation took:
9.602 seconds of real time
9.714198 seconds of total run time (9.268526 user, 0.445672 system)
[ Run times consist of 2.013 seconds GC time, and 7.702 seconds non-GC time. ]
101.17% CPU
15,438,933,331 processor cycles
32,000,006,848 bytes consed

(defstruct simple-struct-2
  (slot-1)
  (slot-2)
  (slot-3))
(time (dotimes (i 1000000000)
        (make-simple-struct-2 :slot-1 1
                              :slot-2 2
                              :slot-3 3)))

Evaluation took:
20.735 seconds of real time
20.927129 seconds of total run time (20.470935 user, 0.456194 system)
[ Run times consist of 2.453 seconds GC time, and 18.475 seconds non-GC time. ]
100.93% CPU
33,340,558,882 processor cycles
32,000,007,568 bytes consed

So we get pretty large savings making a boa-constructor!

We can do more and declaim the constructor inline:

(declaim (inline make-simple-struct-3))
(defstruct (simple-struct-3
             (:constructor make-simple-struct-3
               (slot-1 slot-2 slot-3)))
             (slot-1)
             (slot-2)
             (slot-3))
(time (dotimes (i 1000000000)
        (make-simple-struct-3 1 2 3)))

Evaluation took:
0.363 seconds of real time
0.362868 seconds of total run time (0.362868 user, 0.000000 system)
100.00% CPU
583,539,405 processor cycles
0 bytes consed

We were able to stack-allocate the struct leading to quite the savings and no garbage collection. I wouldn’t suggest this very often but it’s an impressive change.


Rerunning Instantiation Tests

I will re-run the instantiation test with our defstruct having the boa-constructor and not using random.

SBCL

CCL.png

Note: For CCL the struct instantiation test took: 0.238095 seconds. Why was class so terrible? CCL folks?

For there information the output was:

(LOOP FOR I FROM 1 TO RUN-TIMES DO (MAKE-INSTANCE ‘SIMPLE-CLASS :SLOT-1 I :SLOT-2 I :SLOT-3 I))
took 33,453,955 microseconds (33.453957 seconds) to run.
68,225 microseconds ( 0.068225 seconds, 0.20%) of which was spent in GC.
During that period, and with 4 available CPU cores,
33,421,986 microseconds (33.421986 seconds) were spent in user mode
66,531 microseconds ( 0.066531 seconds) were spent in system mode
800,000,528 bytes of memory allocated.
303 minor page faults, 0 major page faults, 0 swaps.

Thanks

I would like to thank @dougk (Google) and @stassats (Reddit account) for the comments and suggestions!


As usual I like to end with a picture:

img_20190909_174425

Class VS Struct in Lisp

It is taken as Gospel that classes are less performant then structs in Common Lisp. This is told to me by one of the main maintainers of SBCL, so for the most part I believe it. This being said, I wanted to see for myself, so I made a simple script and did my own tests. The tests were run in both Clozure Common Lisp (CCL) and Steel Bank Common Lisp (SBCL) on my Lenova Carbon laptop.


Note: These test are very simple, probably don’t represent usual use of class and structs in user code, and I know a lot of people will make a lot of comments on this. That being said, I just wanted to run some basic checks.

All of the code can be found:

https://github.com/Slids/lisp-perf-test/blob/master/class-v-struct.lisp

I will happily take pull requests.


Test slot accessing and setting:

I made a class and a struct that contains 3 un-typed slots. Outside of timing I instantiated the class and the struct. Then with the Lisp time function  set a random slot for a class or struct a random int:

(defun set-random-struct (my-struct)
     (ecase (random 3)
        (0 (setf (simple-struct-slot-1 my-struct)
          (random 100)))
        (1 (setf (simple-struct-slot-2 my-struct)
          (random 100)))
        (2 (setf (simple-struct-slot-3 my-struct)
          (random 100)))))

I ran this 1,000,000,000 for both the class and the struct.I ran this 1,000,000,000 for both the class and the struct.

Set Test (1)

We see structs are in fact faster, though in SBCL the difference is (nearly) negligible. There was no consing so no memory usage.


Test instantiation:

Next we want to test the memory and time of instantiating a set vs a class. For this we just instantiated either a class of a struct setting each slot to a random int:

(make-instance 'simple-class
     :slot-1 (random 10)
     :slot-2 (random 10)
     :slot-3 (random 10))

We ran this (and likewise for struct) 10,000,000 times:

Instantiate Time

Class is a little faster then struct.

Instantiate Consing (1).png

Consing for classes was much worse then structs.


Test Both:

Next we try both instantiating once then setting 100000 times, in 1000 loops for both class and struct:

Instantiate and Set 

So time wise in SBCL they perform almost the same, but for CCL classes are quite a bit slower.

Instantiate and Set Consing

Here we see structs outperform classes hands down.


We see that struct generally performs better. For most cases, you’ll probably be okay either way but for performance struct is better.

And finally:

img_20190824_145150-1

Note: After talking to Dougk I found out I was previously testing the print functions in the instantiate test for Struct and Class. The document has been updated

Macros in Lisp

Note: This post had to be update, WordPress seemed to mangle some of my writing making it less then readable (deleted some text and merged a lisp macro and a c++ function).

Whats the special sauce of Lisp? Macros! And Code as Data etc…

What is a macro? It’s a way to write code that generates more code, or it’s a way to improve/increase the syntax of your language. This confused me for quite a while, so lets go with an example.

Recently, I was writing code that contacts a database in C++. First it creates a connection to the database, runs a query on said database, does some processing collected to the database (the database sends back only a row at a time), and then closes the connection. Since my query is slow (the table is HUGE) it frequently times out giving a retry-able error. The code looks like:

void QueryDatabaseWithWork() {
     DatabaseConnection conn;
     RunQuery(&conn);
     DoWork(conn.Result());
     assert(conn.Finish() == 0);
}

So we create a database connection, run a query, do some work with the returned rows and then call Finish(). Finish() will return either 0 for success, 1 for retry-able error or -1 for non-retry-able errors. So you tell me just wrap this in a loop. (Note wordpress keeps undoing changes to the below code…)

void QueryDatabaseWithWorkRetry() {
     char status = 1;
     for(int attempts = 0;
         attempts <= 10 && status == 1;
         attempts++) {
         if (attempts > 0) {
           sys.sleep(attempts * Milliseconds(10));
           std::cout << "On retry: " << attempts;
         }
       RunQuery(&conn);
       DoWork(conn.Result());
       status = conn.Finish();
     }
     assert(status == 0);
}

This code is fine… I even submitted a CL that looks suspiciously like this. The issue is you must do this EVERY place you have a a query with a bit of work. Of course you could parameterise the query and put the work in a lambda, a runnable or another construct, but this separates your query from your work, and causes a level of indirection that makes code hard to read.

Instead we can extend our language to create a control flow syntax (like while or for) that will give us retries.

(defmacro retry-query (status &body body)
  `(loop :for attempts from 0 to 10
         :while (= status 1)
         :do
       (when (> attempts 0)
         (sleep (* 10 ,attempts))
         (format nil "On attempt ~a" (+ attempts 1)))
       ,@body))

Note: Before we discuss this macro note this is not “production” grade, the macro has variable capture and there are plenty of arguments that should be modifiable, but that would make our example more complex then it should be.


What this will do is allow the user to specify a “status” variable that, if equals 1, will retry the body. We see in the loop body that it will retry up to 10 time and log after every failure. We have also added a back-off in the form of a sleep as before.

Now lets use this macro:

(defun query-database ()
  (let ((conn nil))
    (retry-query
     status
     (setf status (run-query 'my-query)))))

First, we require the user to update status. This makes this macro more useful, as long as we set status to 1 for retry anything can have a retry-able back off, not just this kind of query. Another option is to require body to return the status (retry-able or not) and put the setf in the macro. I’ll give this in the bottom of the page.

I said macros generate code. We used the retry-query macro to allow us to get retries for our code, but what lisp will do is expand

(retry-query
status
(setf status (run-query 'my-query)))

So after macro-expansion Lisp will compile:

(defun query-database ()
  (let ((conn nil))
    (LOOP :FOR ATTEMPTS FROM 0 TO 10
          :WHILE (= STATUS 1)
          :DO
        (WHEN (> ATTEMPTS 0)
          (SLEEP (* 10 ATTEMPTS))
          (FORMAT NIL "On attempt ~a" (+ ATTEMPTS 1)))
        (SETF STATUS (RUN-QUERY 'MY-QUERY)))))

Which is much like the C++ code from above. Instead of having to deal with worrying about abstract classes or interfaces to pass through functionality, or lambda function for dealing with work, we just use our retry-query macro.


I know it’s hard to understand the use of macros for new Lispers, or non-Lispers. I hope I’ve made you a little interested!

I leave you with Lyra and Stitch.

img_20190809_205742


P.S.

Here’s a macro that at least removes variable capture and adds at least minimal flexibility:

(defmacro retry-query ((status &key
                               (log-stream nil)
                               (num-retries 10))
                       &body body)
  (let ((attempts (gensym "attempts")))
    `(loop :for ,attempts from 0 to ,num-retries
           :while  (= ,status 1)
           :do
        (when (> ,attempts 0)
          (sleep (* 10 ,attempts))
          (format ,log-stream "On attempt ~a"
                  (+ ,attempts 1)))
           ,@body)))

or if you know that your body will return 1 for retriable:

(defmacro retry-query ((&key (log-stream nil) (num-retries 10))
                       &body body)
  (let ((attempts (gensym "attempts"))
        (status (gensym "status")))
    `(loop :for ,attempts from 0 to ,num-retries
           :while (= ,status 1)
           :do
         (when (> ,attempts 0)
           (sleep (* 10 ,attempts))
           (format ,log-stream "On attempt ~a"
                   (+ ,attempts 1)))
         (setf ,status ,@body))))

UPDATE: You can also write macros in a language with C-Style syntax in Dylan (example given by @cgay):

define macro with-retry
  { with-retry (#key ?log-stream:expression,
                      ?num-retries:expression = 10)
               ?:body
    end
  }
  => { block (exit)
       for (attempt from 0 to ?num-retries)
         if (attempt > 0)
           sleep(attempt * 10);
           format(?log-stream | *standard-output*, "Attempt %d",
                attempt);
         end;
         if (?body ~= -1)
           exit()
         end
       end
       end block
     }
end macro with-retry;

Here’s Some Pointers

Here’s a pointer: pointers suck!

pointers
XKCD: https://xkcd.com/138/

First, no they don’t, but whats a pointer? For those who are still reading this and are not programmers, pointers are variables that contain a memory address. Say you have

void foo() {
int x = 5;
int* y = &amp;x; // *y == x
cout << y; // print address of x
cout << *y; // print 5 (ie x)
cout << x; // print 5 (ie x)
}

 

Now x is a variable that stores the value 5, and &x says “heres where x is stored”. So saying y = &x tells us that y contains the address of x. In fact, you could read int* as the memory address of an int.

Then *y says, go to the address y is pointing to. What if we did *x? We’d get an error. This being said, &y is still valid, it’s the memory address of the memory address of an int, or int**.  Finally, “cout << x” just says display the value of x to the screen.

If your not a programmer and you don’t understand that’s okay. If you’re a programmer complaining about me eliding certain facts, my apologies.

Now, we if I had a function

void foo(int* y) {
cout << *y;
}
void bar() {
int* z;
foo(z);
}

We would expect all to be okay, we print the int that y is pointer to. But what would that value be? Well,  int* z is saying z will be a pointer to an int, we don’t know where that pointer is, but we will set it soon.

A memory address is an integer from 0 to 2^32 -1 or 2^64 – 1 depending on your processor, and a memory address is stored as an integer. Lets say your processor is 64 bit so 0 to (2^64)-1. So y will be a value from 0 to 2^64 – 1, but its unlikely that this place in memory will contain an integer. Most likely, int* z will set the value z to 0, so “cout << z” should just return zero, but we can’t be sure. Then what will cout << *y; return? It will probably crash whatever program your running.

img_20190707_203609

So why do we use them? They make our code faster. If z was a pointer to 5000 integers:

void foo1(set y) { cout << *y; }
void foo2(set* y) { cout << *y; }
void bar() {
set z = {...}; // z sets 5000 ints
foo1(z);
foo2(&z);
}

Then foo1 has to copy 5000 integers where foo2 just uses those integers!

That being said, this difference has caused a lot of the bugs you’ve heard of, and wasted hours of my life!

Hope you learned something!

img_20190706_131409

For My Daughters First Independence Day

To Lyra,

Today was your first fourth of July, there were some fireworks, though we went home before the big event. There was some junk food, though all you had was sweet potato. You seem to enjoy walking around but the fireworks just confused you, and the national anthem seemed the same as every other song.

You were born into a divided nation. It’s something we can see in every family, especially ours. My parents are Trump supporters, and my co-workers are anti-Trump. It’s hard to understand the divide, why the sides are so against each-other, hopefully this will sort itself out before your old enough to care.

The last fourth of July you were smaller, still in mama. We told you stories like The Little Taxi That Hurried, which made you move a lot. We watched the fireworks together, though you never knew.

What really made me think, was what will you think of this holiday. As you grow up will you care about the US National Anthem? The Chinese National Anthem? Will you believe in Independence Day, or 国庆节? I hope for both.

I don’t know what the future holds my little one, but 我爱你.

Dada

download_20190704_221906