First off, please format code when posting, for blocks use three back-ticks (```) to bracket the block (on their own line); for a inline, use single backticks to bracket the item.
Secondly, the difference is obvious once you understand unconstrained arrays, the simple way to explain it being “X :String;” is rejected by the compiler because it doesn’t know the length, while “X : String := "Hello";” takes the length from the initialization to specify the length, and similarly “X : String:= Get_Line;” uses the function’s result to perfectly size the buffer (String) to the value it receives. (See Memory Management with Ada 2012. linked below.)
You can even combine having a buffer with returning long strings via recursively calling a buffered function; as shown in this Adapower.com example:
function Next_Line(File : in Ada.Text_IO.File_Type :=
Ada.Text_Io.Standard_Input) return String is
Answer : String(1..256);
Last : Natural;
begin
Ada.Text_IO.Get_Line(File => File,
Item => Answer,
Last => Last);
if Last = Answer'Last then
return Answer & Next_Line(File);
else
return Answer(1..Last);
end if;
end Next_Line;
PS — J.P. Rosen’s excellent presentation: Memory Management with Ada 2012.