When TeX performs a \def, it just stores tokens with their current category code. In your case you are storing
\catcode • `12 • \^^M • \active • \let ^^M5 • \par
(bullets separate tokens). So when your \obeylines macro is called, ^^M becomes active, but \let^^M will throw an error of “Missing control sequence”.
Actually, this analysis is not the full truth, because the ^^M with category code 5 in the body of the definition will cause the line to be finished and \par} ignored. So the error you get is different. Doing similar things with other characters would have the same problem described above.
If you look in plain.tex you see
% In \obeylines, we say `\let^^M=\par' instead of `\def^^M{\par}'
% since this allows, for example, `\let\par=\cr \obeylines \halign{...'
{\catcode`\^^M=\active % these lines must end with %
\gdef\obeylines{\catcode`\^^M\active \let^^M\par}%
\global\let^^M\par} % this is in case ^^M appears in a \write
so what's actually stored is
\catcode • `12 • \^^M • \active • \let ^^M13 • \par
which does the job. The \global\let^^M\par can be without the \global, but you could incur into problems if page breaks come along.
\obeylines, do you? – egreg Apr 05 '18 at 16:31