Oz (linguagem de programação) - Oz (programming language)

Onça
Paradigma multiparadigma : lógico , funcional , imperativo , orientado a objetos , restrição , distribuído , concorrente
Projetado por Gert Smolka, seus alunos
Desenvolvedor Consórcio Mozart
Apareceu pela primeira vez 1991 ; 30 anos atrás  ( 1991 )
Versão estável
Oz 1.4.0 (final), Mozart 2.0.1 / 5 de setembro de 2018 ; 2 anos atrás  ( 05/09/2018 )
Disciplina de digitação dinâmico
Licença MIT X11
Local na rede Internet mozart .github .io
Implementações principais
Sistema de Programação Mozart
Dialetos
Oz, Mozart
Influenciado por
Erlang , Lisp , Prolog
Influenciado
Alice , Scala

Oz é uma linguagem de programação multiparadigmática , desenvolvida no Programming Systems Lab da Université catholique de Louvain , para o ensino de linguagens de programação. Possui um livro canônico: Conceitos, técnicas e modelos de programação de computadores .

Oz foi projetado pela primeira vez por Gert Smolka e seus alunos em 1991. Em 1996, o desenvolvimento de Oz continuou em cooperação com o grupo de pesquisa de Seif Haridi e Peter Van Roy no Instituto Sueco de Ciência da Computação . Desde 1999, Oz tem sido continuamente desenvolvido por um grupo internacional, o Mozart Consortium, que originalmente consistia na Saarland University , no Swedish Institute of Computer Science e na Université catholique de Louvain . Em 2005, a responsabilidade de gerenciar o desenvolvimento de Mozart foi transferida para um grupo central, o Mozart Board, com o propósito expresso de abrir o desenvolvimento de Mozart para uma comunidade maior.

O sistema de programação Mozart é a principal implementação do Oz. É lançado com uma licença de código aberto pelo Mozart Consortium. Mozart foi portado para Unix , FreeBSD , Linux , Windows e macOS .

Características da linguagem

Oz contém a maioria dos conceitos dos principais paradigmas de programação , incluindo programação lógica, funcional ( avaliação preguiçosa e avaliação ansiosa ), imperativa, orientada a objetos, restrição, distribuída e simultânea. Oz tem uma semântica formal simples (consulte o capítulo 13 do livro mencionado abaixo) e uma implementação eficiente. Oz é uma linguagem orientada para a concorrência , como o termo foi introduzido por Joe Armstrong, o principal designer da linguagem Erlang . Uma linguagem orientada para simultaneidade torna a simultaneidade fácil de usar e eficiente. Oz oferece suporte a uma linguagem QTk de interface gráfica de usuário canônica (GUI).

Além da programação multiparadigma, os principais pontos fortes do Oz estão na programação de restrições e na programação distribuída . Devido ao seu design fatorado, Oz é capaz de implementar com sucesso um modelo de programação distribuída transparente para a rede. Este modelo facilita a programação de aplicativos abertos e tolerantes a falhas no idioma. Para a programação de restrição, Oz introduz a ideia de espaços de computação , que permitem busca definida pelo usuário e estratégias de distribuição ortogonais ao domínio de restrição.

Visão geral da linguagem

Estruturas de dados

Oz é baseado em uma linguagem central com muito poucos tipos de dados que podem ser estendidos para outros mais práticos por meio do açúcar sintático .

Estruturas de dados básicas:

  • Números: ponto flutuante ou inteiro (inteiro real)
  • Records: para agrupar dados: circle(x:0 y:1 radius:3 color:blue style:dots) . Aqui, os termos x, y, raio etc. são chamados de feições e os dados associados às feições (neste caso 0,1,3 etc.) são os valores.
  • Tuplas: Grava com inteiro apresenta em ordem crescente: circle(1:0 2:1 3:3 4:blue 5:dots) .
  • Listas: uma estrutura linear simples
'|'(2 '|'(4 '|'(6 '|'(8 nil)))) % as a record.
2|(4|(6|(8|nil))) % with some syntactic sugar
2|4|6|8|nil % more syntactic sugar
[2 4 6 8] % even more syntactic sugar

Essas estruturas de dados são valores (constantes), primeira classe e verificados dinamicamente por tipo . Os nomes de variáveis ​​em Oz começam com uma letra maiúscula para distingui-los dos literais que sempre começam com uma letra minúscula.

Funções

Funções são valores de primeira classe, permitindo programação funcional de ordem superior :

fun {Fact N}
   if N =< 0 then 1 else N*{Fact N-1} end
end
fun {Comb N K}
   {Fact N} div ({Fact K} * {Fact N-K}) % integers can't overflow in Oz (unless no memory is left)
end

fun {SumList List}
   case List of nil then 0
   [] H|T then H+{SumList T} % pattern matching on lists
   end
end

As funções podem ser usadas com variáveis ​​livres e limitadas. Valores de variáveis ​​livres são encontrados usando escopo léxico estático .

Programação de ordem superior

As funções são como outros objetos de Oz. Uma função pode ser passada como um atributo para outras funções ou pode ser retornada em uma função.

fun {Square N}  % A general function
   N*N
end

fun {Map F Xs}  % F is a function here - higher order programming
   case Xs
      of nil then nil
      [] X|Xr then {F X}|{Map F Xr}
   end
end

%usage
{Browse {Map Square [1 2 3]}}  %browses [1 4 9]

Funções anônimas

Como muitas outras linguagens funcionais, Oz suporta o uso de funções anônimas (ou seja, funções que não têm um nome) com programação de ordem superior. O símbolo $ é usado para denotar isso.

A seguir, a função square é definida anonimamente e passada, fazendo [1 4 9] com que seja pesquisada.

{Browse {Map fun {$ N} N*N end [1 2 3]}}

Como as funções anônimas não têm nomes, não é possível definir funções anônimas recursivas.

Procedimentos

As funções em Oz devem retornar um valor na última instrução encontrada no corpo da função durante sua execução. No exemplo abaixo, a função Ret retorna 5 se X> 0 e -5 caso contrário.

declare
fun {Ret X}
   if X > 0 then 5 else ~5 end
end

Mas Oz também fornece uma facilidade no caso de uma função não retornar valores. Essas funções são chamadas de procedimentos. Os procedimentos são definidos usando a construção "proc" como segue

declare
proc {Ret X}
   if X > 0 then {Browse 5} else {Browse ~5} end
end

O exemplo acima não retorna nenhum valor, apenas imprime 5 ou -5 no navegador Oz dependendo do sinal de X.

Variáveis ​​de fluxo de dados e simultaneidade declarativa

Quando o programa encontra uma variável não associada, ele espera por um valor. Por exemplo, abaixo, o encadeamento esperará até que X e Y estejam vinculados a um valor antes de mostrar o valor de Z.

thread 
   Z = X+Y
   {Browse Z}
end
thread X = 40 end
thread Y = 2 end

O valor de uma variável de fluxo de dados não pode ser alterado depois de vinculado:

X = 1
X = 2 % error

As variáveis ​​do Dataflow facilitam a criação de agentes de stream simultâneos:

fun {Ints N Max}
   if N == Max then nil
   else 
      {Delay 1000}
      N|{Ints N+1 Max}
   end
end

fun {Sum S Stream}
   case Stream
      of nil then S
      [] H|T then S|{Sum H+S T}
   end
end

local X Y in
   thread X = {Ints 0 1000} end
   thread Y = {Sum 0 X} end
   {Browse Y}
end

Por causa da maneira como as variáveis ​​de fluxo de dados funcionam, é possível colocar threads em qualquer lugar em um programa e garantir que terá o mesmo resultado. Isso torna a programação simultânea muito fácil. Threads são muito baratos: é possível ter 100.000 threads rodando ao mesmo tempo.

Exemplo: peneira de divisão de teste

Este exemplo calcula um fluxo de números primos usando o algoritmo de divisão de teste, criando recursivamente agentes de fluxo simultâneos que filtram os números não primos:

fun {Sieve Xs}
   case Xs of nil then nil
   [] X|Xr then Ys in
      thread Ys = {Filter Xr fun {$ Y} Y mod X \= 0 end} end
      X|{Sieve Ys}
   end
end

Preguiça

Oz usa a avaliação rápida por padrão, mas a avaliação preguiçosa é possível. Abaixo, o fato só é calculado quando o valor de X é necessário para calcular o valor de Y.

fun lazy {Fact N}
   if N =< 0 then 1 else N*{Fact N-1} end
end
local X Y in
  X = {Fact 100} 
  Y = X + 1
end

A avaliação preguiçosa dá a possibilidade de armazenar estruturas de dados verdadeiramente infinitas em Oz. O poder da avaliação preguiçosa pode ser visto no seguinte exemplo de código:

declare
fun lazy {Merge Xs Ys}
   case Xs#Ys
   of (X|Xr)#(Y|Yr) then
      if X < Y then X|{Merge Xr Ys}
      elseif X>Y then Y|{Merge Xs Yr}
      else X|{Merge Xr Yr}
      end
   end
end

fun lazy {Times N Xs}
   case Xs
   of nil then nil
   [] X|Xr then N*X|{Times N Xr}
   end
end

declare H
H = 1 | {Merge {Times 2 H} {Merge {Times 3 H} {Times 5 H}}}
{Browse {List.take H 6}}

O código acima calcula elegantemente todos os números regulares em uma lista infinita. Os números reais são calculados apenas quando são necessários.

Simultaneidade de passagem de mensagem

O modelo declarativo concorrente pode ser estendido com a passagem de mensagens por meio de semântica simples:

declare
local Stream Port in
   Port = {NewPort Stream}
   {Send Port 1} % Stream is now 1|_ ('_' indicates an unbound and unnamed variable)
   {Send Port 2} % Stream is now 1|2|_ 
   ...
   {Send Port n} % Stream is now 1|2| .. |n|_
end

Com uma porta e um thread, os agentes assíncronos podem ser definidos:

fun {NewAgent Init Fun}
   Msg Out in
   thread {FoldL Msg Fun Init Out} end
   {NewPort Msg}
end

Estado e objetos

É novamente possível estender o modelo declarativo para oferecer suporte à programação orientada a objeto e estado com semântica muito simples. Para criar uma nova estrutura de dados mutável chamada Células:

local A X in
   A = {NewCell 0}
   A := 1  % changes the value of A to 1
   X = @A  % @ is used to access the value of A
end

Com essas mudanças semânticas simples, todo o paradigma orientado a objetos pode ser suportado. Com um pouco de açúcar sintático, OOP torna-se bem integrado em Oz.

class Counter
   attr val
   meth init(Value)
      val:=Value
   end
   meth browse
      {Browse @val}
   end
   meth inc(Value)
      val :=@val+Value
   end
end

local C in
   C = {New Counter init(0)}
   {C inc(6)}
   {C browse}
end

Velocidade de execução

A velocidade de execução de um programa produzido pelo compilador Mozart (versão 1.4.0 implementando Oz 3) é muito lenta. Em um conjunto de benchmarks, ele é em média cerca de 50 vezes mais lento do que o GNU Compiler Collection (GCC) para a linguagem C, resolvendo as tarefas de benchmarks.

Veja também

Referências

links externos