SAS does have expected behavior when dealing with CHARACTER type variable assignments - pretty well documented and mostly consistent.
Suggest if you want to ensure an expected SAS CHARACTER variable length to avoid truncation, use an ATTRIB or LENGTH statement (and not a FORMAT statement, by the way). And you will want to code the statement ahead of the first reference to a given SAS CHARACTER variable, that being either with an assignment stmt, a SET, or a RETAIN, to cover most instances.
We SAS users are just too spoiled by SAS doing so much for us implicit.
So may be SAS R&D decided here to take the safe way and assign a variable length which is always long enough - instead of trying to cater for all the possibilities of how people might create a concatenated string.
I.e: using cat() for concatenation you even end up with the default length for character variables ($200 in my environment).
As others already said: If you want to be sure what you get define it explicit using a length statement.
All make me some sense is 'substr(first,1,7)' is only in PDV ( not write into disk) so SAS will treat it has the same storage length with variable 'First' . and once you write it into dataset (such as ' a=substr(first,1,7) '),it will has 7 length of storage.
I don't know if the details regarding assigning variable length in such a condition are documented but, if you want the calculation to equal 16, just use a function that doesn't include trailing blanks. I.e., use length rather than lengthn.