5种你可能从未听说过的编程语言

jopen 7年前

一起来看一看你可能最闻所未闻的5种编程语言吧。

1.Nim

我喜欢用Nim编码,是因为它很有意思。Nim模糊了编译和脚本语言之间的界线。下面是源代码:

proc update(options: Options) =    ## Downloads the package list from the specified URL.    ##    ## If the download is successful, the global didUpdatePackages is set to    ## true. Otherwise an exception is raised on error.    let url =      if options.action.typ == actionUpdate and options.action.optionalURL != "":        options.action.optionalURL      else:        defaultPackageURL    echo("Downloading package list from " & url)    downloadFile(url, options.getNimbleDir() / "packages.json")    echo("Done.")

还有长一点的:

proc parseConfig*(): Config =    result = initConfig()    var confFile = getConfigDir() / "nimble" / "nimble.ini"      var f = newFileStream(confFile, fmRead)    if f == nil:      # Try the old deprecated babel.ini      confFile = getConfigDir() / "babel" / "babel.ini"      f = newFileStream(confFile, fmRead)      if f != nil:        echo("[Warning] Using deprecated config file at ", confFile)      if f != nil:      echo("Reading from config file at ", confFile)      var p: CfgParser      open(p, f, confFile)      while true:        var e = next(p)        case e.kind        of cfgEof:          break        of cfgSectionStart: discard        of cfgKeyValuePair, cfgOption:          case e.key.normalize          of "nimbledir":            # Ensure we don't restore the deprecated nimble dir.            if e.value != getHomeDir() / ".babel":              result.nimbleDir = e.value          of "chcp":            result.chcp = parseBool(e.value)          else:            raise newException(NimbleError, "Unable to parse config file:" &                                    " Unknown key: " & e.key)        of cfgError:          raise newException(NimbleError, "Unable to parse config file: " & e.msg)      close(p)

2.Felix

Felix是独一无二的。它是C ++、ML以及许多独特构想的结合。下面摘自我写的一个小型JSON解析器:

class JSON {      typedef LineType = int;        union Value =          | Object of strdict[Value]          | Array  of list[Value]          | String of string          | Number of double          | True          | False          | Null          | Error of string * LineType      ;        union Token =          | TString of string          | TNumber of double          | TLBrace // {          | TRBrace // }          | TLBrak  // [          | TRBrak  // ]          | TColon  // :          | TTrue   // true          | TFalse  // false          | TNull   // null          | TEOF          | TError of string * LineType      ;        instance Str[Token] {          fun str(t: Token) => match t with              | TString ?s => "TString \"" + s + "\""              | TNumber ?n => "TNumber " + n.str              | TLBrace    => "TLBrace"              | TRBrace    => "TRBrace"              | TLBrak     => "TLBrak"              | TRBrak     => "TRBrak"              | TColon     => "TColon"              | TTrue      => "TTrue"              | TFalse     => "TFalse"              | TNull      => "TNull"              | TEOF       => "TEOF"              | TError (?s, ?i) => "error at line " + i.str + ": " + s          endmatch;      }        proc lex(s: string, line: &LineType, outs: oschannel[Token]) = {          line <- 1;            proc tok(t: Token) => write $ outs, t;            proc err(s: string) = {              tok $ TError(s, *line);              return from lex;          };            var i = 0.size;            while i < s.len do              while s.[i].isspace do                  if s.[i] == "\n" do *line++; done;                  i++;                  if i >= s.len goto eof;              done;                // number              if s.[i].isnumeric or (i+1 < s.len and s.[i] == "-" and                                       s.[i+1].isnumeric) do                  d := s.[i to].double;                  i += d.str.len;                  tok $ TNumber d;              // string              elif s.[i] == "\"" do                  i++;                  var st = "";                  while i < s.len and s.[i] != "\n" and s.[i] != "\"" do                      st += s.[i];                      i++;                  done;                  if s.[i] != "\"" call err "unterminated string literal";                  i++;                  tok $ TString st;              // literals              elif s.[i to i+4] == "true" do                  tok $ TTrue;                  i += 4.size;              elif s.[i to i+5] == "false" do                  tok $ TFalse;                  i += 5.size;              elif s.[i to i+4] == "null" do                  tok $ TNull;                  i += 4.size;              // others              else                  match s.[i].str with                      | "{" => tok TLBrace;                      | "}" => tok TRBrace;                      | "[" => tok TLBrak;                      | "]" => tok TRBrak;                      | ":" => tok TColon;                      | _   => err "unknown token";                  endmatch;                    i++;              done;          done;            eof:>          tok TEOF;      }  }

你也可以鉴赏一下我写的这个JSON解析器,这是链接

它有一些很不错的功能,如schannels(一种协同程序)。 schannels就像Go的channels,不过并不是并发的。Felix还有另一个类似Go的channels,叫做fchannels,这是并发的。

Felix有一套不错的工具(Web服务器,明白易懂的编程格式,α-品质的图形配置工具)和尺寸刚好的标准库。

至于缺点?文档很少。不过,邮件讨论非常活跃。

3.Myrddin

Myrddin一些功能:

  • 类型推断
  • 模式匹配
  • Go风格slices切片
  • C风格的内存管理

举个libbio输入/输出库的例子。下面是其中的一个片段:

/*  writes to as much from `src` as possible to a file,  returning the number of bytes written.  */  const write = {f, src      std.assert(f.mode & Wr != 0, "File is not in write mode")      /*      Tack small writes onto the buffer end. Big ones      flush the buffer and then go right to kernel.      */      if src.len < (f.wbuf.len - f.wend)          std.slcp(f.wbuf[f.wend:f.wend+src.len], src)          f.wend += src.len          -> src.len      else          flush(f)          -> writebuf(f.fd, src)      ;;  }

4.K

K,连同Kona非常特别。它是将APL推进ASCII字符世界的结果。

下面是一些在Kona wiki的惯用语:

shuffle:{x@<>(#x)#1 0} / Perfect shuffle  mean:{(+/x)%#x} / Arithmetic mean  fac:*/1+!: / Factorial  fib:{x{x,+/-2#x}/!2} / Fibonacci  life:{|/(1;x)&3 4=\:+/,/2{-1 0 1!'\:x}/x} / Conway's Game of Life  sort:{x@<x} / Sort list  powerset:{x[&:'!2+&#x]} / Powerset

正如你所看到的,K非常简洁,就是可能有点太过了。然而,作为数组处理语言,它功能卓越,而且快速。

5.Objeck

Objeck用起来特别给力:

class Factorial {      function : native : Factorial(n : Int) ~ Int {          if (n <= 1) {              return n;          } else {              return n * Factorial(n-1);          };      }        function : Main(args : String[]) ~ Nil {          "Number: "->Print();          number := IO.Console->ReadString()->ToInt();          if (number < 0) {              "Number must be greater than 0"->PrintLine();              Runtime->Exit(1);          };          Factorial(number)->PrintLine();      }  }

它的缺点是没有真正的本地编译器。

其他

还有我没有提到过的ani和Alore。

Ani是一种隐含并行性和非常速度的的编程语言。而Alore是基于静态和动态类型自由组合的编程语言。

总结

我要介绍的就到这里,希望能能你眼前一亮。

译文链接:http://www.codeceo.com/article/5-programming-language-never-heard.html
英文原文:The top 5 programming languages you've never heard of
翻译作者:码农网 – 小峰