I like the idea of a single macro that can do both lags and leads, especially because it allows dynamic control of the lead and lag length. And if fail_flag=1 is a rare event I suspect "point=" is the right underlying strategy.

But the problem for me, when using a sorted data set, is that the underlying POINT= approach doesn't actually take advantage of the fact that the data are ordered. For large sorted data sets, I suspect that using lag functions, and emulating leads via "auto-merge with firstobs", is likely to be much faster, as it involves no direct-addressing of observations. Instead it uses SAS's very fast sequential read engine.

Consider the problem posted: get the number of days elapsed between the 2nd record prior to a failure and the 1st record after the failure. And that result should be assigned to the record having fail_flag=1:

data want;
merge have
have (firstobs=2 keep=date_out rename=(date_out=nxt_date));
delta = ifn(fail_flag=1,nxt_date - lag2(date,.);
drop nxt_date;
run;

I suspect that for relatively large data sets, or relatively frequent precipitating events, that there would be a substantial time savings vs point=. For example I deal with datasets containing a day of stock trades (billions of observations time-stamped to the nano-second, sorted by trade symbol and time), looking for price changes and then retrieving some type of lagged or lead information surrounding the newly price record.

The other restriction that may limit use of %hop is when there needs to be a "where=" expression, which doesn't work in the "set ... point=" statement. For example, if instead of 2 records prior and 1 record later, you have a class variable, with values 1 and 2, and you only want to count records with the same class as the fail_flag=1 record. Unfortunately SAS won't let you use "set &d (where=(class=1)) point=&I". (One could program around that for lags, but subsetted leads are a good deal more challenging).