I don't think there is a significant difference in memory usage between functions and internal procedures. If you have to use either instead of methods and they are used in multiple programs you should just put them in a super procedure or session session service so they will only be loaded once in your session.
There are more important differences to think about. Function calls are checked at compile time (existence and matching parameters), run statements are not checked. A run ... no-error will suppress an error even if the procedure doesn't exist or the parameters don't match.
Functions can't return errors, procedures can.
With functions you can get the error "Input blocking statement is invalid while executing a user-defined function (2780)" in older Progress versions. Essentially that means that you can't use PROMPT-FOR, SET, UPDATE, WAIT-FOR, READKEY and PROCESS EVENTS while inside a function, including all procedures called from that function. The easiest way to avoid this is not to call procedures from a function. With newer versions this doesn't seem to be an issue anymore, see documentation on the -IOEverywhere parameter.
Methods kind of merge the advantages while avoiding the disadvantages. Method calls are checked at compile time and can return errors / exceptions.