Съществуват и активно се използват много езици за програмиране (ЕП). Те се различават по предназначение и област на употреба, по преобладаващия стил на изразяване – например команден или декларативен, обектноориентиран и пр., по обема и вида (компилатор, интерпретатор или друго) на реализацията си и по още редица други свойства. Тези разлики често са достатъчни, за да изберем за дадена работа даден език сред останалите.

   

Понякога обаче искаме да добием бърза и нагледна представа за външния вид и пригодността на един или друг ЕП. Тогава споменатите формални разлики остават на заден план, а вместо тях за оценка на език или сравнение между няколко си служим с конкретни програми – решения на дадена задача. По-долу съм привел решения на трийсет и един ЕП на много проста, но не съвсем тривиална задача, която е в основата на много други, често и естествено възникващи в практиката. В първата група са „системни“ езици, в следващата – т.нар. динамични и командният bash, а в последната – функционални езици. Всички решения са цялостни, завършени програми, а не просто откъси.

   

Задачата се състои в това да се прочете от т.нар. стандартен вход (терминал, конзола) и отпечата на стандартния изход един ред. Не е важно дали прочетеният ред изрично се запомня в някакъв вид или направо се отпечатва, но програмата не бива да налага ограничение за дължината му. Това прави задачата нетривиална, защото някои ЕП нямат средство за образуване или четене на неопределено дълъг низ, а в други такова средство съществува, но е неочевидно или използването му не е много просто.

Размерът и съдържанието на програмите могат да служат за ориентир доколко езиците са подходящи например за обучение по програмиране, за решаване на ежедневни несложни задачи, за използване от непрограмисти и пр. Разбира се, само един и то прост пример не дава подробна представа за даден ЕП и не позволява пълноценно сравняване между различни езици. И все пак удивително е, че дори и толкова прост пример позволява да изпъкнат съществени черти на езиците.

   

Някои от езиците са на значителна възраст, но в решението на задачата се представят не по-зле или дори значително по-добре от други, по-нови. Да обърна внимание, че BASIC, Algol 68, Рефал и Snobol са от 60-те г. на миналия век, Scheme, Icon и REXX – от 70-те, а Common Lisp, макар формално от 80-те, е всъщност обобщение на значително по-стари диалекти на езика Lisp. Решението на Snobol е от най-икономичните – само четири съвсем ясни лексеми!

   

C е създаден през 1972 г. и е единственият сред показаните езици, в който е невъзможно непосредствено четене на неограничено дълъг ред. Затова в програмата образуваме динамичен масив, разширяването на който става с изрично (пре)заделяне на памет, когато е необходимо. При все това решението е с доста скромен размер. На този фон бюрократичната многословност на Java и Node.js и в по-малка степен на Go и Rust е отблъскваща.

 
C
#include <stdio.h>
#include <stdlib.h>
int main() {
  int sz,c,n;
  char *pb, *p;
  pb = malloc(sz=2);
  p = pb;
  while ((c=getchar()) != '\n') {
    n = p-pb;
    if (n+2 > sz)
      pb = realloc(pb,sz*=2);
    p = pb+n;
    *p++ = c;
  }
  *p = 0;
  puts(pb);
}
 
C++
#include <iostream>
#include <string>
using namespace std;
int main() {
  string s;
  getline(cin,s);
  cout << s << '\n';
}
 
D
import std.stdio;
void main() {
  write(readln());
}
 
Java
import java.io.*;
public class ReadString {
  public static void main(String []args) throws IOException {
    BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    String s = in.readLine();
    System.out.println(s);
  }
}
 
C#
using System;
class ReadString {
  public static void Main() {
    string s = Console.ReadLine();
    Console.WriteLine(s);
  }
}
Algol 68
STRING s;
read((s,newline));
print((s,newline))
 
Ada
with text_io;
use text_io;
procedure readstring is
begin
  put_line(get_line);
end;
 
Go
package main
import ("os"; "bufio"; "fmt")
func main() {
  s,_ := bufio.NewReader(os.Stdin).ReadString('\n')
  fmt.Println(s)
}
 
Rust
use std::io;
fn main() {
  let mut s = String::new();
  io::stdin().read_line(&mut s);
  println!("{}",s);
}
 
Scala
println(readLine)
 
Snobol
    output = input
end
 
Python (v3)
print(input())
 
Ruby
puts gets
 
Tcl
puts [gets stdin]
 
Perl
$s = <>;
print($s);
 
PHP
<?php $s = fgets(STDIN); echo $s; ?>
 
Falcon
>input()
Icon
procedure main()
  write(read())
end
 
Lua
print(io.read())
 
REBOL
print input
 
Julia
println(readline(stdin))
 
BASIC
LINE INPUT S$
PRINT S$
END
 
Euphoria
puts(1,gets(0))
 
REXX
say linein()
Node.js
const readline = require('readline')
const rl = readline.createInterface
             ({input: process.stdin,
               output: process.stdout})
rl.on('line', (s) => {console.log(s); rl.close()})
bash
read -r s && echo ${s}
 
Scheme
(display (get-line (current-input-port)))
(newline)
 
Common Lisp
(write-line (read-line))
 
Рефал
$ENTRY Go {= <Prout <Card>>}
 
Standard ML
(print o valOf) (TextIO.inputLine TextIO.stdIn);
val _ = OS.Process.exit OS.Process.success;
 
Haskell
main = do s <- getLine
          putStrLn s
 

Бойко Банчев  ⋄  ноември 2020