tri

Capital of Texas Triathlon Preview

Monday I'm going to be running in the 25th Capital of Texas Triathlon!  It's my first triathlon (Olympic distance) in twenty years and I'm pretty jazzed.

Steely-eyed determination 20 years ago. :-)

One of the great things about triathlons (and running races in general) is that you get to occupy unusual spaces: the last ones I did were Leon's Triathlon in Hammond, Indiana, a couple of Bud Light triathlons and others in Chicago. Leon's had a swim in Wolf Lake (shudder), followed by a cycle leg on an elevated highway that ran past the old U.S. Steel plant, and a run leg through an industrial downtown.  The Chicago ones were on the lakefront, just north of Navy Pier, with a bike on Lake Shore Drive and a run along the lake.

2013 CapTexTri
The CapTexTri also has a great location in downtown Austin, with a 1.5k swim in Lady Bird Lake; a 40k (24.8 mile) bike on a quadruple loop through downtown Austin, including Congress Avenue and Cesar Chavez; and a 10k (6.2 mile) run through Zilker Park.

The only thing I'm not too keen on is the bike route, since it requires you to do the same loop four times with a bunch of corresponding hairpin turns.  I don't like loop routes because I always think of how many more times I have to do the thing...Still, going up and down Congress Avenue without any cars is going to be pretty cool. As long as there are no poles in the middle of the road, I should be okay. :-).

Don't ask.

I feel fairly good about my training.  I've maintained good running mileage after the Austin Marathon and Austin Distance Festival and got some good workouts in even while traveling doing school visits.
On Stone Arch Bridge in Minneapolis
The swim is probably my weakest event -- I could stand to do more work on technique and probably do more open water swimming, but the distance won't be an issue.  Also, Lady Bird Lake isn't going to have waves (I seem to recall a couple of triathlons in Chicago with 3-4 foot waves on Lake Michigan (and this was on the near side of the breakwater).  Also, I won't have to deal with a wet suit.  My biggest concern is to not get kicked in the face. :-).
Lady Bird Lake during 2013 CapTexTri
The bike I'm feeling good about as well.  I'll be using the bike I used for my triathlons back in the day - a Trek 1000 I bought when I was in grad school for $450 (a guy at one bicycle shop here tried to sell me a new one, asking if I had a "nostalgic attachment" to it.). I do, but I also don't think a new bike is going to drastically transform my performance.  At least not $2000 worth :-). (A guy at another bike shop told me the Trek 1000 was his first road bike and he wished he still had it.  It's possible he was being kind :-)).

Tomorrow is packet pick-up, bike drop-off, and a chance to scope out the transition area, which I'll need because I can't see without my glasses...:-)

Oh, well.  Qapla!















tri

Capital of Texas Triathlon/Duathlon/10K/5K

So my plan to do my first triathlon in twenty years on Monday didn't turn out so well.

It rained.

A lot. But not so much in town.

At Camp Mabry, just north of central Austin, we got less than an inch of rain last Thursday. At Bergstrom Airport, just south and east of downtown, they got about nine inches.  And it was much worse farther east, along the Colorado River (which also runs through Austin).

On Friday and Saturday, it rained in the Hill Country.  West of Austin.  Upriver.

On Sunday, there was the CapTexTri expo and packet pickup and bike dropoff.

Swag!  My first cowboy hat since I was around seven.
Bike drop off.  I got there early.
Packet pickup
Coveting my neighbor's bike, Part I.
It was clear and sunny.  But because of all the rain, the LCRA opened at least one floodgate from the Tom Miller Dam, releasing water into Lady Bird Lake.  Which was where the swim portion of the CapTexTri was supposed to take place.

At the course talk at the expo, they announced that there was a flow of about 3 mph and they were considering changing the course so that it ran point to point (downriver).
Course talk.  Could've used a projector.


Later that day, they announced the swim was canceled.  Which was disappointing, but I've weathered a couple of triathlons in Chicago where that had happened and one when it probably should've.

Monday, race day, I awoke at 5 AM, fed the cats, ate breakfast and drank coffee, and then I heard rain.  Lots of rain.

Nevertheless (discovering, to my chagrin, that I am apparently an optimist), I headed out.  When I arrived at the transition area, I was told it was closed, and that we should shelter at Palmer Events Center or its garage.  This was around 6-620.

In the garage and on the deck of the Palmer Events Center, folks seemed to take things in stride and with humor.  Some people were concerned about hairpin turns on a wet course, but were generally willing to take it slow.
Sheltering in the garage

We heard a tentative plan to cut short the bike portion to 20k, but the rain and lightning continued. Finally, at around 830, race officials called off the bike portion entirely because of flooding on the course. 
Still a bit lightning-y
They announced that Olympic distance participants could do a 10k, while sprint participants could do a 5k and that start time would be at 10 am. Most folks removed their bikes and went home or back to their hotels. There was some grumbling -- last year the event had been cut short due to flooding, as well, and I gather there had been similar problems in 2014, too.
Athletes clearing out the transition area
 
I took my bike back to my car, but decided that I'd gotten up at five that morning to run a race and so, I was going to do one.  Besides, I didn't want to waste all those carbs I'd eaten in the past few days. :-).

At ten o'clock, the rain pretty much stopped.  And then we were off!  By 10:15, the sun came out.  No, really. 
Everyone who's still there seems in good humor :-)
And we're off!


Turned out, there were only about 200 of us who stuck around for the 10k, with another 150 for the 5k (out of around 3000 original participants), but everyone seemed to be having a good time.  I was pretty happy with my race -- I'm not sure it was exactly 10k, but I still did one of my better overall times and paces. At least this century :-).
The view from the Biergarten.  Note the utter absence of rain.
Sunny skies.
On the whole, it was a bit surreal but fun, although in the moment sometimes frustrating.  And, in retrospect, kind of funny.  I think the organizers did a good job under trying conditions and kept us pretty well informed via social media.  So, thanks (And I am really glad I wasn't in charge :-)).  Thanks also to all the volunteers who stuck around to the bitter end.

 Oh, and I actually ended up getting a bit of a tan.

Coveting my neighbor's bike, Part II
Epilogue: Late Monday, the Austin Fire Department closed Lady Bird Lake and Lake Austin to all boat traffic.

And they're giving us a discount for the 2017 race. :-).

Here's what the lake looked like Tuesday morning (Normally, there is no current at all):

















 




tri

Tri and Tri Again

This summer I was finally able to complete my first triathlon of the century! I've actually managed two: The Capital of Texas Triathlon, which takes place in downtown Austin over Memorial Day, and Jack's Generic Triathlon, which is in Pflugerville in August.

Unlike last year, the CapTexTri went off without a hitch and with nearly perfect weather. I was fairly happy with my swim -- my time was actually comprable if not better than my times from back in the day. My only problem was that I kept drifting off course since I couldn't see -- my glasses kept fogging up and I couldn't see the marker buoys...

The bike went well, too: again, my time was comparable to the last time I did an Olympic distance event, undoubtedly due to my brilliant training regimen. (Either that, or the new bike that's half the weight of my old one).

My only problem was that I didn't hydrate enough on the bike, which affected my run. I got really hot and crashed a bit on mile 4, so my run time was less than optimal. Also, I probably should've indulged in some on-course solid or semi-solid nutrition. Oh, well, live and learn... 

Here are a few pics:

Packet pickup at the back of the exhibit hall

The Cutco cutlery booth. I think this is for the "Game of Thrones" division
Everything you always wanted to know about how to mark your body for a triathlon
Alas, fixed-gear bikes are not legal in USAT sanctioned events
Setting up the swim venue
Shiny bikes all in a row (race morning)

On the bike!
And the run!
At the finish line!
I'd originally planned to run the TriRock triathlon over Labor Day, but that one was canceled this year, so I decided to run Jack's Generic Triathlon, in early August.

Again, I was fairly pleased with my swim, although I may have cut the course a bit. My goggles were fogged and I have no memory of rounding one of the triangular marker buoys. But my time was in the right ballpark, so it's enitrely possible I did it correctly :-).

The bike portion was two loops through rolling corn fields, which reminded me a lot of central Illinois where I would ride back when I was an undergrad at U. of I. It was rather windy, and I was very happy to have my new aero handlebars...It felt pretty good, too, and I made an effort to hydrate more than during the CapTexTri.  Apparently not enough, though, because I again crashed and overheated during the run.  But there were ice sponges on course and plenty of water and Nuun and there was an ice bath at the end...Also, I now understand why some teams provide their riders with Coca-Cola during the Tour de France...

All in all, a fun race that I will probably do again next year.

Because it's out in Pflugerville, I decided to check out the course beforehand:

Lake Pflugerville!
The Hydrilla-eating Monster
Panorama of the bike route. Lots of corn
Yes, I had my Bat Shark Repellent. Because you never know what the hydrilla monster is going to dredge up.
As usual, the race started way too early in the morning, but I managed to get a few pics:

Bicycles at dawn


Prepping for the afterparty
The swim exit is prepared
Posing before the swim just before warmups
The squint of the near-sighted swimmer racing to the transition area
Made it to the bike. I'm now a fan of aero handlebars
The transition area post-race
  
Post-race ice bath, yay!
Coca-Cola is our friend







tri

Extraterrestrial artifacts

Could the Solar System host traces of other intelligent life?




tri

2026 Cadillac Vistiq Electric SUV



  • SUVs & Trucks

tri

Manscaped The Chairman Pro Electric Shaver




tri

Patrick Stein: Ray Tracing In One Weekend (in Lisp, and n-dimenions)

Earlier this year, I started working through the online book Ray Tracing In One Weekend (Book 1). I have been following along with it in Common Lisp, and I have been extending it all from 3-dimensional to n-dimensional.

I reproduced 4-dimensional versions of all of the book images which you can see on my weekend-raytracer github page.

Here is the final image. This is a 250-samples-per-pixel, 640x360x10 image plane of three large hyperspheres (one mirrored, one diffuse, one glass) atop a very large, diffuse hypersphere. Also atop this very large hypersphere are a bunch of smaller hyperspheres of varying colors and materials. The image is rendered with some defocus-blur.

Final image of 4-dimensional scene

Caveat: This depends on a patched version of the policy-cond library that is not in the current Quicklisp distribution but should be in the next.




tri

TurtleWare: Dynamic Vars - The Empire Strikes Back

Table of Contents

  1. Thread Local storage exhausted
  2. The layer of indirection
  3. I can fix her
  4. Let's write some tests!
  5. Summary

Thread Local storage exhausted

In the last post I've described a technique to use dynamic variables by value instead of the name by utilizing the operator PROGV. Apparently it works fine on all Common Lisp implementations I've tried except from SBCL, where the number of thread local variables is by default limited to something below 4000. To add salt to the injury, these variables are not garbage collected.

Try the following code to crash into LDB:

(defun foo ()
  (loop for i from 0 below 4096 do
    (when (zerop (mod i 100))
      (print i))
    (progv (list (gensym)) (list 42)
      (values))))
(foo)

This renders our new technique not very practical given SBCL popularity. We need to either abandon the idea or come up with a workaround.

The layer of indirection

Luckily for us we've already introduced a layer of indirection. Operators to access dynamic variables are called DLET, DSET and DREF. This means, that it is enough to provide a kludge implementation for SBCL with minimal changes to the remaining code.

The old code works the same as previously except that instead of SYMBOL-VALUE we use the accessor DYNAMIC-VARIABLE-VALUE, and the old call to PROGV is now DYNAMIC-VARIABLE-PROGV. Moreover DYNAMIC-EFFECTIVE-SLOT used functions BOUNDP and MAKUNBOUND, so we replace these with DYNAMIC-VARIABLE-BOUND-P and DYNAMIC-VARIABLE-MAKUNBOUND. To abstract away things further we also introduce the constructor MAKE-DYNAMIC-VARIABLE

(defpackage "EU.TURTLEWARE.BLOG/DLET"
  (:local-nicknames ("MOP" #+closer-mop "C2MOP"
                           #+(and (not closer-mop) ecl) "MOP"
                           #+(and (not closer-mop) ccl) "CCL"
                           #+(and (not closer-mop) sbcl) "SB-MOP"))
  (:use "CL"))
(in-package "EU.TURTLEWARE.BLOG/DLET")

(eval-when (:compile-toplevel :execute :load-toplevel)
  (unless (member :bordeaux-threads *features*)
    (error "Please load BORDEAUX-THREADS."))
  (when (member :sbcl *features*)
    (unless (member :fake-progv-kludge *features*)
      (format t "~&;; Using FAKE-PROGV-KLUDGE for SBCL.~%")
      (push :fake-progv-kludge *features*))))

(defmacro dlet (bindings &body body)
  (flet ((pred (binding)
           (and (listp binding) (= 2 (length binding)))))
    (unless (every #'pred bindings)
      (error "DLET: bindings must be lists of two values.~%~
                Invalid bindings:~%~{ ~s~%~}" (remove-if #'pred bindings))))
  (loop for (var val) in bindings
        collect var into vars
        collect val into vals
        finally (return `(dynamic-variable-progv (list ,@vars) (list ,@vals)
                           ,@body))))

(defmacro dset (&rest pairs)
  `(setf ,@(loop for (var val) on pairs by #'cddr
                 collect `(dref ,var)
                 collect val)))

(defmacro dref (variable)
  `(dynamic-variable-value ,variable))

;;; ...

(defmethod mop:slot-boundp-using-class
    ((class standard-class)
     object
     (slotd dynamic-effective-slot))
  (dynamic-variable-bound-p (slot-dvar object slotd)))

(defmethod mop:slot-makunbound-using-class
    ((class standard-class)
     object
     (slotd dynamic-effective-slot))
  (dynamic-variable-makunbound (slot-dvar object slotd)))

With these in place we can change the portable implementation to conform.

#-fake-progv-kludge
(progn
  (defun make-dynamic-variable ()
    (gensym))

  (defun dynamic-variable-value (variable)
    (symbol-value variable))

  (defun (setf dynamic-variable-value) (value variable)
    (setf (symbol-value variable) value))

  (defun dynamic-variable-bound-p (variable)
    (boundp variable))

  (defun dynamic-variable-makunbound (variable)
    (makunbound variable))

  (defmacro dynamic-variable-progv (vars vals &body body)
    `(progv ,vars ,vals ,@body)))

I can fix her

The implementation for SBCL will mediate access to the dynamic variable value with a synchronized hash table with weak keys. The current process is the key of the hash table and the list of bindings is the value of the hash table. For compatibility between implementations the top level value of the symbol will be shared.

The variable +FAKE-UNBOUND+ is the marker that signifies, that the variable has no value. When the list of bindings is EQ to +CELL-UNBOUND+, then it means that we should use the global value. We add new bindings by pushing to it.

#+fake-progv-kludge
(progn
  (defvar +fake-unbound+ 'unbound)
  (defvar +cell-unbound+ '(no-binding))

  (defclass dynamic-variable ()
    ((tls-table
      :initform (make-hash-table :synchronized t :weakness :key)
      :reader dynamic-variable-tls-table)
     (top-value
      :initform +fake-unbound+
      :accessor dynamic-variable-top-value)))

  (defun make-dynamic-variable ()
    (make-instance 'dynamic-variable))

  (defun dynamic-variable-bindings (dvar)
    (let ((process (bt:current-thread))
          (tls-table (dynamic-variable-tls-table dvar)))
      (gethash process tls-table +cell-unbound+)))

  (defun (setf dynamic-variable-bindings) (value dvar)
    (let ((process (bt:current-thread))
          (tls-table (dynamic-variable-tls-table dvar)))
      (setf (gethash process tls-table +cell-unbound+) value))))

We define two readers for the variable value - one that simply reads the value, and the other that signals an error if the variable is unbound. Writer for its value either replaces the current binding, or if the value cell is unbound, then we modify the top-level symbol value. We use the value +FAKE-UNBOUND+ to check whether the variable is bound and to make it unbound.

#+fake-progv-kludge
(progn
  (defun %dynamic-variable-value (dvar)
    (let ((tls-binds (dynamic-variable-bindings dvar)))
      (if (eq tls-binds +cell-unbound+)
          (dynamic-variable-top-value dvar)
          (car tls-binds))))

  (defun dynamic-variable-value (dvar)
    (let ((tls-value (%dynamic-variable-value dvar)))
      (when (eq tls-value +fake-unbound+)
        (error 'unbound-variable :name "(unnamed)"))
      tls-value))

  (defun (setf dynamic-variable-value) (value dvar)
    (let ((tls-binds (dynamic-variable-bindings dvar)))
      (if (eq tls-binds +cell-unbound+)
          (setf (dynamic-variable-top-value dvar) value)
          (setf (car tls-binds) value))))

  (defun dynamic-variable-bound-p (dvar)
    (not (eq +fake-unbound+ (%dynamic-variable-value dvar))))

  (defun dynamic-variable-makunbound (dvar)
    (setf (dynamic-variable-value dvar) +fake-unbound+)))

Finally we define the operator to dynamically bind variables that behaves similar to PROGV. Note that we PUSH and POP from the thread-local hash table DYNAMIC-VARIABLE-BINDINGS, so no synchronization is necessary.

#+fake-progv-kludge
(defmacro dynamic-variable-progv (vars vals &body body)
  (let ((svars (gensym))
        (svals (gensym))
        (var (gensym))
        (val (gensym)))
    `(let ((,svars ,vars))
       (loop for ,svals = ,vals then (rest ,svals)
             for ,var in ,svars
             for ,val = (if ,svals (car ,svals) +fake-unbound+)
             do (push ,val (dynamic-variable-bindings ,var)))
       (unwind-protect (progn ,@body)
         (loop for ,var in ,svars
               do (pop (dynamic-variable-bindings ,var)))))))

Let's write some tests!

But of course, we are going to also write a test framework. It's short, I promise. As a bonus point the API is compatibile with fiveam, so it is possible to drop tests as is in the appropriate test suite.

(defvar *all-tests* '())

(defun run-tests ()
  (dolist (test (reverse *all-tests*))
    (format *debug-io* "Test ~a... " test)
    (handler-case (funcall test)
      (serious-condition (c)
        (format *debug-io* "Failed: ~a~%" c))
      (:no-error (&rest args)
        (declare (ignore args))
        (format *debug-io* "Passed.~%")))))

(defmacro test (name &body body)
  `(progn
     (pushnew ',name *all-tests*)
     (defun ,name () ,@body)))

(defmacro is (form)
  `(assert ,form))

(defmacro pass ())

(defmacro signals (condition form)
  `(is (block nil
         (handler-case ,form
           (,condition () (return t)))
         nil)))

(defmacro finishes (form)
  `(is (handler-case ,form
         (serious-condition (c)
           (declare (ignore c))
           nil)
         (:no-error (&rest args)
           (declare (ignore args))
           t))))

Now let's get to tests. First we'll test our metaclass:

(defclass dynamic-let.test-class ()
  ((slot1 :initarg :slot1 :dynamic nil :accessor slot1)
   (slot2 :initarg :slot2 :dynamic t   :accessor slot2)
   (slot3 :initarg :slot3              :accessor slot3))
  (:metaclass class-with-dynamic-slots))

(defparameter *dynamic-let.test-instance-1*
  (make-instance 'dynamic-let.test-class
                 :slot1 :a :slot2 :b :slot3 :c))

(defparameter *dynamic-let.test-instance-2*
  (make-instance 'dynamic-let.test-class
                 :slot1 :x :slot2 :y :slot3 :z))

(test dynamic-let.1
  (let ((o1 *dynamic-let.test-instance-1*)
        (o2 *dynamic-let.test-instance-2*))
    (with-slots (slot1 slot2 slot3) o1
      (is (eq :a slot1))
      (is (eq :b slot2))
      (is (eq :c slot3)))
    (with-slots (slot1 slot2 slot3) o2
      (is (eq :x slot1))
      (is (eq :y slot2))
      (is (eq :z slot3)))))

(test dynamic-let.2
  (let ((o1 *dynamic-let.test-instance-1*)
        (o2 *dynamic-let.test-instance-2*))
    (signals error (slot-dlet (((o1 'slot1) 1)) nil))
    (slot-dlet (((o1 'slot2) :k))
      (is (eq :k (slot-value o1 'slot2)))
      (is (eq :y (slot-value o2 'slot2))))))

(test dynamic-let.3
  (let ((o1 *dynamic-let.test-instance-1*)
        (exit nil)
        (fail nil))
    (flet ((make-runner (values)
             (lambda ()
               (slot-dlet (((o1 'slot2) :start))
                 (let ((value (slot2 o1)))
                   (unless (eq value :start)
                     (setf fail value)))
                 (loop until (eq exit t) do
                   (setf (slot2 o1) (elt values (random (length values))))
                   (let ((value (slot2 o1)))
                     (unless (member value values)
                       (setf fail value)
                       (setf exit t))))))))
      (let ((r1 (bt:make-thread (make-runner '(:k1 :k2))))
            (r2 (bt:make-thread (make-runner '(:k3 :k4))))
            (r3 (bt:make-thread (make-runner '(:k5 :k6)))))
        (sleep .1)
        (setf exit t)
        (map nil #'bt:join-thread (list r1 r2 r3))
        (is (eq (slot2 o1) :b))
        (is (null fail))))))

Then let's test the dynamic variable itself:

(test dynamic-let.4
  "Test basic dvar operators."
  (let ((dvar (make-dynamic-variable)))
    (is (eql 42 (dset dvar 42)))
    (is (eql 42 (dref dvar)))
    (ignore-errors
     (dlet ((dvar :x))
       (is (eql :x (dref dvar)))
       (error "foo")))
    (is (eql 42 (dref dvar)))))

(test dynamic-let.5
  "Test bound-p operator."
  (let ((dvar (make-dynamic-variable)))
    (is (not (dynamic-variable-bound-p dvar)))
    (dset dvar 15)
    (is (dynamic-variable-bound-p dvar))
    (dynamic-variable-makunbound dvar)
    (is (not (dynamic-variable-bound-p dvar)))))

(test dynamic-let.6
  "Test makunbound operator."
  (let ((dvar (make-dynamic-variable)))
    (dset dvar t)
    (is (dynamic-variable-bound-p dvar))
    (finishes (dynamic-variable-makunbound dvar))
    (is (not (dynamic-variable-bound-p dvar)))))

(test dynamic-let.7
  "Test locally bound-p operator."
  (let ((dvar (make-dynamic-variable)))
    (is (not (dynamic-variable-bound-p dvar)))
    (dlet ((dvar 15))
      (is (dynamic-variable-bound-p dvar)))
    (is (not (dynamic-variable-bound-p dvar)))))

(test dynamic-let.8
  "Test locally unbound-p operator."
  (let ((dvar (make-dynamic-variable)))
    (dset dvar t)
    (is (dynamic-variable-bound-p dvar))
    (dlet ((dvar nil))
      (is (dynamic-variable-bound-p dvar))
      (finishes (dynamic-variable-makunbound dvar))
      (is (not (dynamic-variable-bound-p dvar))))
    (is (dynamic-variable-bound-p dvar))))

(test dynamic-let.9
  "Stress test the implementation (see :FAKE-PROGV-KLUDGE)."
  (finishes                              ; at the same time
    (let ((dvars (loop repeat 4096 collect (make-dynamic-variable))))
      ;; ensure tls variable
      (loop for v in dvars do
        (dlet ((v 1))))
      (loop for i from 0 below 4096
            for r = (random 4096)
            for v1 in dvars
            for v2 = (elt dvars r) do
              (when (zerop (mod i 64))
                (pass))
              (dlet ((v1 42)
                     (v2 43))
                (values))))))

(test dynamic-let.0
  "Stress test the implementation (see :FAKE-PROGV-KLUDGE)."
  (finishes                             ; can be gc-ed
    (loop for i from 0 below 4096 do
      (when (zerop (mod i 64))
        (pass))
      (dlet (((make-dynamic-variable) 42))
        (values)))))

All that is left is to test both dynamic variable implementations:

BLOG/DLET> (lisp-implementation-type)
"ECL"
BLOG/DLET> (run-tests)
Test DYNAMIC-LET.1... Passed.
Test DYNAMIC-LET.2... Passed.
Test DYNAMIC-LET.3... Passed.
Test DYNAMIC-LET.4... Passed.
Test DYNAMIC-LET.5... Passed.
Test DYNAMIC-LET.6... Passed.
Test DYNAMIC-LET.7... Passed.
Test DYNAMIC-LET.8... Passed.
Test DYNAMIC-LET.9... Passed.
Test DYNAMIC-LET.0... Passed.
NIL

And with the kludge:

BLOG/DLET> (lisp-implementation-type)
"SBCL"
BLOG/DLET> (run-tests)
Test DYNAMIC-LET.1... Passed.
Test DYNAMIC-LET.2... Passed.
Test DYNAMIC-LET.3... Passed.
Test DYNAMIC-LET.4... Passed.
Test DYNAMIC-LET.5... Passed.
Test DYNAMIC-LET.6... Passed.
Test DYNAMIC-LET.7... Passed.
Test DYNAMIC-LET.8... Passed.
Test DYNAMIC-LET.9... Passed.
Test DYNAMIC-LET.0... Passed.
NIL

Summary

In this post we've made our implementation to work on SBCL even when there are more than a few thousand dynamic variables. We've also added a simple test suite that checks the basic behavior.

As it often happens, after achieving some goal we get greedy and achieve more. That's the case here as well. In the next (and the last) post in this series I'll explore the idea of adding truly thread-local variables without a shared global value. This will be useful for lazily creating context on threads that are outside of our control. We'll also generalize the implementation so it is possible to subclass and implement ones own flavor of a dynamic variable.




tri

tried to deliver

Today on Married To The Sea: tried to deliver


This RSS feed is brought to you by Drew and Natalie's podcast Garbage Brain University. Our new series Everything Is Real explores the world of cryptids, aliens, quantum physics, the occult, and more. If you use this RSS feed, please consider supporting us by becoming a patron. Patronage includes membership to our private Discord server and other bonus material non-patrons never see!




tri

Troll Dad Strikes When You Least Expect Him





tri

They Tried Digging Up, Decided Building a Ladder Was Better




tri

Joey Logano 1-on-1: Winning Cup Series championship is 'electric'

Joey Logano sat down with FOX Sports to discuss the wild pace-car wreck, the playoff format and the feeling of winning the title at Phoenix.




tri

Deion Sanders says he’ll intervene if ‘wrong' NFL team tries to draft son Shedeur

Coach Prime tells the "Speak" crew how he plans to handle the NFL draft process with quarterback son, Shedeur, and two-way star Travis Hunter.




tri

in (one's) stride, at (a) pace

This post is inspired by a poll that Ellen Jovin, aka the Grammar Table, ran in September. Before I get into that, let me point out that there is a Kickstarter to support the documentary about her spreading grammatical joy across all 50 US states. It'd be lovely to be able to see that film in a (BrE) cinema/(AmE) theater or event near you, near me and near everybody. So if you have the wherewithal to support it, click!
https://www.kickstarter.com/projects/rebelwithaclause/rebel-with-a-clause
 
Now back to our (somewhat) regularly scheduled grammar-gazing. 

to take (something) in (one's) stride

Ellen asked on social media whether people say take it in stride or take it in one's stride



When I see a split like that, I think dialects.

The version with a possessive pronoun, to take in one's stride, is the more British (and non-North American) version:


And the shorter version, to take in stride, is the North American: 


The phrase is a metaphor from horse racing. As the OED defines it:

to take in one's stride: of a horse or its rider, to clear (an obstacle) without checking one's gallop; figurative to deal with (a matter) incidentally, without interrupting one's course of action, argument, etc. Also (chiefly U.S.) without possessive adjective.

It seems to come from the UK in the early-mid 1800s, and then takes off in its possessiveless form in 1930s US. (The possessive-ful lines are low in the following graph because I had to choose just one possessive form to search—I chose his for the illustration because it's the most frequent in this phrase in Google Books.)



It's not clear to me whether AmE speakers back then were familiar with the racing expression. If not, then the expression might not have been recogni{s/z}ed as metaphorical, and therefore might be more likely to change.

But then again, I'm not sure the possessive is absolutely needed—you wouldn't take something in someone else's stride. So maybe Americans dropped the possessive in both literal and metaphorical usage. A horsey person might have to tell us.

at (a) pace

At pace (meaning 'moving fast') is a similar expression—a prepositional phrase involving a noun that alludes to walking—and it has no possessive or other word introducing it. But that doesn't help us explain the American loss of the possessive in in stride, since at pace is a more British and much more recent expression. 


An older version has the indefinite determiner: at a pace. That's found in similar numbers in AmE and BrE. And then there's the very old (Middle English) expression apace, which means much the same thing and sounds much like at pace. It's possible that at pace is an eggcorn for apace, or that it's at a pace without the a, or maybe it's a bit of both—i.e. different people have come to the same form from different angles.

why?

So we have two phrases that originally had a determiner* (a possessive pronoun or an article) between a preposition and a noun for a stepping action, and in just one place (but not the same place) the expression has been getting shorter. Why? Well, the basic answer is: language changes and it doesn't ask anyone's permission. If it changes in one place it doesn't need to change in the other. And for set phrases like this, change is likely to be piecemeal. Just because one phrase loses its determiner, doesn't mean all such phrases will. 

Since these expressions have got(ten) more and more figurative over the ages (referring to properties like ease and speed, rather than literal steps or paths), the determiners have had less and less work to do. Since they are unstressed syllables, they're easy to swallow up. So, if they go, we might not miss them, and if they stay they probably won't bother us. C'est la parole


*You'll see above that OED calls these things possessive adjectives. I don't. They act more like determiners (e.g., a(n)the and this) than like adjectives like good or corporate.




tri

NFPA and ESFI work to reduce fatalities caused by electric shock drowning in pools and at marinas

With summer in full swing, the National Fire Protection Association (NFPA) and Electrical Safety Foundation International (ESFI) are joining forces to remind people about the potential electrical hazards in swimming pools, hot tubs and spas, on board boats and in the waters surrounding boats, marinas and launch ramps.




tri

Saudi Arabia’s Sovereign Wealth Fund Trims Nintendo Stake Again




tri

Kansai Electric to Raise Up to $3.3 Billion From Share Sale




tri

Israeli forces strike Oct. 7 attacker's cell in Gaza

The Israeli Defense Forces (IDF) said on Wednesday that it eliminated a militant cell member, Yasser Ghandi, in Gaza's Shejaiya area who allegedly participated in the October 7 attack in Israel that l...




tri

8 killed in Israeli airstrike in Lebanon

An airstrike by Israeli forces in southern Lebanon has led to the death of eight individuals, according to reports from the Lebanese state news agency NNA. "The National News Agency corresponden...





tri

Antec Introduces the CX600M Trio PC Case

Antec Inc., a global leader in high-performance computer components and accessories, is proud to announce the launch of the Antec CX600M Trio Mid-Tower Gaming Case. This latest addition to Antec's chassis lineup combines compact design with cutting-edge modern style, delivering a jaw dropping microATX case that's perfect for modern, high-performance PCs.

The post Antec Introduces the CX600M Trio PC Case appeared first on ThinkComputers.org.




tri

Computing orientation with complex multiplication but without trigonometric function

Today’s methods for computing orientation are quaternion and rotation matrix. However, their efficiencies are tarnished by the complexity of the rotation matrix and the counterintuitivity of quaternion. A better method is presented here. It uses complex multiplication for rotating vectors in 3D space and can compute orientation without angle and trigonometric functions, which is simple,...




tri

ININ & Strictly Limited Games Sale Thread

 I just noticed ININ Games is having a Gaming Season Sale on Amazon starting today. 
 
Here are the deals:
 
 
 
 
 
Note:  I would jump on this since who knows how many Egret II mini's are left in-stock and this year is TAITO's anniversary, this is an insanely good price on the arcade unit and controllers.
 
 
 
  • -->





    tri

    I Tried the Viral DIY Pool Noodle Decor Hack, and It Couldn't Be Easier

    I’m definitely going to do this again! READ MORE...




    tri

    How do we ensure that training and information support contributes to positive outcomes for carers?

    This is a paper produced as part of the PROP2 (Practitioner Research: Outcomes and Partnership) programme, a partnership between the Centre for Research on Families and Relationships (CRFR) at the University of Edinburgh and Iriss that was about health and social care in Scotland. This paper was written by Alan Gilmour from Glasgow City Community Health Partnership who participated in the PROP2 programme. This research aimed to gain an understanding of how training and information support contributes to positive outcomes for carers. It provided a range of information to answer specific questions such as: • Do carers feel that their needs are identified appropriately at different stages of their journey? • Does training contribute to the carer’s outcomes? • What are the barriers to carers engaging in training?




    tri

    Fox Business Tries In Vain To Defend Trump's Crazy Tariff Plans

    Fox Business host Charles Payne and contributor Steve Moore did their best to soft-peddle the damage Trump's cringeworthy plan of tariffs would have to the US economy but still came up short.

    Payne, subbing for Neil Cavuto, went back to a US history that is no longer relevant to us to prop up the idea of tariffs.

    PAYNE: How does President Trump plan to convince his fellow Republicans that this is the right way to go?

    MOORE: Well, there's two issues here, Charles.

    One is how do we make his landmark 2017 tax bill permanent, because as you know, if no action is taken this year, a lot of that tax bill expires and the average family would pay about $2,500 more in taxes and it would hurt our businesses.

    This is what the 2%ers and corporations want more than life itself. Letting these tax cuts expire won't hurt anybody. It makes it harder for the rich to fiddle with their tax returns.

    Now comes the rub. This is where their clucking begins.

    MOORE: And then, of course, there's the secondary issue about the tariffs that Trump has been talking about. Now, maybe, I'm just thinking out loud here, Charles, and I've talked to some of the top economic advisors that have worked with me in the Trump campaign, we could maybe mix these two and use tariffs as a way to pay for some of these tax cuts.

    read more




    tri

    Trey Parker and Matt Stone Supposedly Bought Cars for a Whole Club of Strippers

    By Keegan Kelly Published: November 11th, 2024




    tri

    The IKEA Hack That Turned the Ugliest Wall into a Striking Focal Point

    We’ve all seen the IKEA LACK shelf. Many of us have probably installed one or two in our homes. It’s practical, unassuming and one of the most popular IKEA pieces for budget-friendly decor. But just when we thought we’d seen it all, design producer Justin Miller who goes by the handle @miztermiller on Instagram, gives this humble shelf a fresh twist and got us looking at the simple, chunky shelf with renewed fondness. Miller’s latest hack transforms five 74-inch LACK […]

    The post The IKEA Hack That Turned the Ugliest Wall into a Striking Focal Point appeared first on IKEA Hackers.




    tri

    These countries are facing the biggest health impacts

    Medical Aid, a South African insurance comparison website, investigated the effects of environmental issues like poor water quality, pollution, sanitation and chemical exposure on the health of citizens in 103 countries around the world. The information is summarized in a report titled, "Climate Health: Where in the World is Climate Change Impacting Health the Most?"[...]




    tri

    These are 5 industries being propelled by 3D printing

    When 3D printing first took off, it was difficult to imagine how diverse the field would grow. Nowadays, the realm of additive manufacturing is growing daily. In particular, five sectors are advancing rapidly as a result of developments in additive manufacturing. These are healthcare, food, fashion, motorsports and aerospace. Based on estimates, it is believed that soon these industries will incorporate 3D printing as a key component of their operations.[...]





    tri

    VEILDrive Attack Exploits Microsoft Services to Evade Detection and Distribute Malware

    An ongoing threat campaign dubbed VEILDrive has been observed taking advantage of legitimate services from Microsoft, including Teams, SharePoint, Quick Assist, and OneDrive, as part of its modus operandi. "Leveraging Microsoft SaaS services — including Teams, SharePoint, Quick Assist, and OneDrive — the attacker exploited the trusted infrastructures of previously compromised organizations to




    tri

    Cisco Releases Patch for Critical URWB Vulnerability in Industrial Wireless Systems

    Cisco has released security updates to address a maximum severity security flaw impacting Ultra-Reliable Wireless Backhaul (URWB) Access Points that could permit unauthenticated, remote attackers to run commands with elevated privileges. Tracked as CVE-2024-20418 (CVS score: 10.0), the vulnerability has been described as stemming from a lack of input validation to the web-based management




    tri

    IcePeony and Transparent Tribe Target Indian Entities with Cloud-Based Tools

    High-profile entities in India have become the target of malicious campaigns orchestrated by the Pakistan-based Transparent Tribe threat actor and a previously unknown China-nexus cyber espionage group dubbed IcePeony. The intrusions linked to Transparent Tribe involve the use of a malware called ElizaRAT and a new stealer payload dubbed ApoloStealer on specific victims of interest, Check Point




    tri

    New Flaws in Citrix Virtual Apps Enable RCE Attacks via MSMQ Misconfiguration

    Cybersecurity researchers have disclosed new security flaws impacting Citrix Virtual Apps and Desktop that could be exploited to achieve unauthenticated remote code execution (RCE) The issue, per findings from watchTowr, is rooted in the Session Recording component that allows system administrators to capture user activity, and record keyboard and mouse input, along with a video stream of the




    tri

    LA man wearing GPS ankle monitor is accused of a robbery string. Officials can't track him




    tri

    Tribal digital sovereignty in today's dystopia







    tri

    How to see the invisible: Using the dark matter distribution to test our cosmological model

    A Princeton-led team of astrophysicists has measured a surprising value for the “clumpiness” of the universe’s dark matter.




    tri

    Crystal Place Tri 2022

    So this was my first triathlon, so I was a bit worried about how it would go. The swim was always going to be the challenging part, I had been doing swim lessons for the 6 weeks previously and only the week before I managed to swim 100m of front crawl without stopping. So the … Continue reading Crystal Place Tri 2022




    tri

    ‘Many Minds, Many Stripes’ conference sets 2025 date to celebrate Graduate School alumni

    The conference has been scheduled for Oct. 9-11, 2025. All Princeton alumni are invited back to campus for the gathering. 




    tri

    Chemist Victor Laurie, who contributed to the field of microwave spectroscopy, dies at 88

    Laurie joined the Princeton faculty in 1966 and transferred to emeritus status in 2000.




    tri

    Do-Re-Meet: Pre-Concert Speed Dating + Isidore String Quartet Concert

    Wednesday, November 20, 2024 7-8:30PM: Speed Dating 9PM: Concert featuring the Isidore String Quartet Find your perfect harmony among music-loving singles* in your age group by participating in 8-minute speed dates while enjoying catered appetizers on the historic Princeton University campus! Everyone will then head over to the concert hall to experience the trailblazing Isidore String Quartet. May you enjoy Isidore with a fellow music-lover you adore! Age Groups: Group Do: 24-39 Group Re: 40-59 Group Mi: 60+ Tickets for the full evening—admission to both the Do-Re-Meet event and the ensuing concert—are $50 General/$25 Student (an $80 value). If you already have a ticket to the concert and want to add on this experience, please contact us. *This event is designated for individuals seeking heterosexual connections. There will be an LGBTQIA+ and Allies Mingle on Saturday, December 7, 2024. To learn more about the Do-Re-Meet program and see more of Princeton University Concerts' social events for music lovers, click here. This event is presented by Princeton University Concerts. For a full event listing and tickets, please visit this link. Presented in partnership with TheSinglesGroup.com and Olsson's Fine Foods.




    tri

    Princeton University Concerts presents Isidore String Quartet

    About the Event Part of the Princeton University Concerts (PUC) Performances Up Close series, audience is seated onstage alongside the musicians in an hour-long program. Winners of a 2023 Avery Fisher Career Grant and the 14th Banff International String Quartet Competition in 2022, the New York City-based Isidore String Quartet was formed in 2019 with a vision to revisit, rediscover, and reinvigorate the repertory. The young ensemble will do just that when they make their Princeton debuts in a program featuring a recent string quartet by multiple GRAMMY-winner Billy Childs; Henri Dutilleux’s fascinating Ainsi la nuit (“Thus the Night”); and W.A. Mozart’s forward-thinking “Dissonance” quartet. This event is presented by Princeton University Concerts. For a full event listing and tickets, please visit this link.




    tri

    Princeton University Concerts Live Music Meditation: Isidore String Quartet

    "When the first notes of [the music] threaded their way into my consciousness, they seemed to come from inside me…music wound its way through me as sound turned pure sensation." —The New York Times on PUC's Live Music Meditation About the Event Breathe in sound and silence through guided meditation as you listen to music more viscerally than ever before, meditating to the playing of the Isidore String Quartet, guided by Matthew Weiner, Associate Dean in the Princeton University Office of Religious Life. This is a FREE, unticketed opportunity to indulge in attentive, focused, and mindful listening. No prior experience with meditation necessary. Capacity is limited, and we advise participants to arrive early—although the event officially begins at 12:30PM, doors to the hall will open and meditation instruction will begin at 12:00PM (noon). The event will conclude by 1:30PM. If desired, attendees may bring floor seating (mat/cushion/etc); seating will be on stage, with chairs provided. For more information about the Live Music Meditation experience, check out this New York Times feature and Performance Today segment. About the Musicians: Winners of a 2023 Avery Fisher Career Grant, and the 14th Banff International String Quartet Competition in 2022, the New York City-based Isidore String Quartet was formed in 2019 with a vision to revisit, rediscover, and reinvigorate the repertory. The quartet is heavily influenced by the Juilliard String Quartet and the idea of ‘approaching the established as if it were brand new, and the new as if it were firmly established.’ The quartet began as an ensemble at the Juilliard School. They are currently completing their final year as Peak Fellowship Ensemble-in-Residence at Southern Methodist University in Dallas. Additional Evening Concerts: The Isidore Quartet will also perform in the evening as part of the Performances Up Close series at 6PM & 9PM, with audience seated onstage. Concert info & tickets This event is presented by Princeton University Concerts. For a full event listing and tickets, please visit this link.




    tri

    Princeton Triangle Club Presents: Pageant Pending

    Back for its 134th year, the Princeton Triangle Club premieres a brand-new Triangle Show: Pageant Pending! Welcome to America’s Most Wanted, the biggest pageant event in all 50 states! The lights are blinding, the competition is cutthroat, and the interview questions must be answered in twenty seconds or less. Dreams, schemes, and ripped seams are all exposed under a merciless spotlight in this new musical comedy about a series of sash decisions! Join us for Pageant Pending and discover what has made the annual Triangle Show one of Princeton’s favorite town/gown traditions for over 130 years!