E um rato e um sapo. Compilador Universal

Em uma série sobre programação confiável [1], [2] Swift permaneceu imerecidamente esquecido. Para ser honesto, eu simplesmente não o considerava multiplataforma, mas trabalhando exclusivamente para o macOS / iOS. Por acaso, o Swift também é suportado por um ambiente de desenvolvimento como o RemObjects Elements .

Acabou que ela tinha um Compilador Universal. Pode compilar programas em C #, Go, Java, Oxygene Object Pascal, Swift para: Android, Cacau (MacOS, iOS, tvOS), JVM, Linux (x64, armv6, aarch64), .NET / .NET Core / Mono, Windows nativo (x86 / x64), WebAssembly.

E faz isso em quase qualquer combinação de idioma → sistema de destino! Por exemplo, você pode escrever um programa em Java que usará o WPF para a plataforma .NET de destino, e isso é tudo nos exemplos que acompanham o pacote.

Portanto, apresento uma mini nota sobre os RemObjects Elements e, ao mesmo tempo, sobre a confiabilidade dos dois idiomas suportados - Swift e Oxygene.

Figura de radionetplus


Além das discussões sobre o problema da interoperabilidade de diferentes ambientes de tempo de execução - nativo, JVM, .NET, GC, ARC, acabou sendo inacreditável e em ambos os sentidos, pois durante as discussões eles chegaram à conclusão de que o IO normal é impossível.

Brevemente sobre os elementos RemObjects


Esse é um ambiente de desenvolvimento independente com um depurador, incluindo um remoto, e a conclusão de código para Windows ou macOS, ou se integra ao Visual Studio, e o Xcode é necessário para o Cocoa. Para a Swift, é grátis; quanto mais, custa US $ 199 para a versão para projetos pessoais, até US $ 799 para uma licença comercial para todos os idiomas. Para trabalhar com DBMS cliente - servidor, é necessário pagar substancialmente mais.

Water é o nome da versão do Windows, é bastante ascético, não possui um editor de formulários visuais, mas simpatiza com o rigor, e o instalador ocupa apenas 700 MB, é claro, sem incluir JRE, .NET, Android NDK, etc.

Para repreendê-la, ou não vou elogiar muito, ela desempenha suas funções, nunca caiu (mas a memória está fluindo).

O bônus para o IDE é muito:

  • ( Water , -)
  • -
  • C#, Swift, Java, Delphi, C, Obj-C Oxygene, C#, Swift, Java, Go
  • Go- . Go
  • -
  • Delphi/VCL


Obviamente, há um pequeno problema para aqueles que pensam que (c) você pode simplesmente pegar e transferir qualquer programa para outra plataforma.

A OI aqui é que o programa só pode usar os recursos de sua plataforma RTL _e_ destino para todos os idiomas e suas combinações. Ou seja, para os fins do .NET, você pode usar o WPF, mas não o rt.jar, mas para o Native, apenas WinAPI ou GTK, respectivamente. Mas a biblioteca base escrita em Oxygene está disponível em todos os lugares, assim como a camada de migração com o Delphi - pela maneira como eles estão disponíveis no github .

Um projeto pode incluir subprojetos em diferentes idiomas suportados pelo RO. E com a importação de bibliotecas externas, também existem opções bem desenvolvidas.

O gerenciamento de memória será usado em uma plataforma de destino, como o ARC for Cocoa. Não entrei em detalhes, pois o Native GC é usado por padrão, embora exista uma opção - está marcada, existe no meu projeto no github .

Adicione uma observação. Se o programa foi escrito sob gerenciamento manual de memória (malloc / free), ele funcionará simplesmente no ARC. E se o programa estava no ARC, ele funcionará sem alterações no GC (exceto para destruição imediata).

Confiabilidade


Oxigênio


Este é basicamente um objeto Pascal antigo e familiar, mas com esteróides. A versão Oxygene for .NET também foi comercializada como Delphi Prism.

Parece mais seguro devido a:

  • Gc
  • suporte de controle anulável
  • disponibilidade de contratos e invariantes
  • controle de registro de identidade
  • a capacidade de controlar o recuo dos pares de início / fim (não está claro como isso funciona)
  • métodos de classe segura de thread bloqueado / lento
  • usando usando, no sentido de RAII

Minuses. O GC também tem uma desvantagem - não determinismo temporário, consumo excessivo de memória. Você também pode anotar as desvantagens de que a escala da empresa e da comunidade é pequena e, portanto, provavelmentemais erros de implementação do que para os technomonsters. A documentação é fraca e a estrutura nativa é mínima, o que pode atrair várias "bicicletas" para projetos se o seu destino não for .NET ou JRE.

No lado técnico, adicionou açúcar em relação ao Delphi:

  • assíncrono / aguardar / futuro, aguardar - até agora apenas para .NET
  • LINQ
  • tipos genéricos / dinâmicos (diferentes do Delphi)
  • tuplas
  • sequência / rendimento
  • interpolação de string

Interlúdio. C #


Foi eliminado anteriormente devido à limitada plataforma cruzada, mas com o lançamento do .NET Core 3 e o advento do compilador nativo, inclusive para Linux, ficou um pouco melhor. Além disso, o idioma também é suportado no RemObjects com uma seleção arbitrária de destinos.

Na verdade, com confiabilidade, o C # está mais ou menos certo. O GC estraga a beleza, não é muito confortável trabalhar com anulável, o que leva a NPEs regulares, a capacidade de obter uma exceção de uma função de aparência inocente e problemas com o uso sem êxito do LINQ.

Devido ao GC e ao consumo de recursos, não é muito adequado para o Embedded. Além disso, apenas o intérprete sem o JIT .NET Micro Framework foi abandonado para incorporação desde 2015, embora tenha sido desenvolvido como TinyCLR

Agora sobre Swift


Em geral, uma linguagem compilada por máquina do tipo C, uma das mais novas e criadas, levando em consideração a história de seus antecessores. Feito pela Apple, o compilador oficial ainda está no Ubuntu, transferido para o Open Source.

As oportunidades no nível de confiabilidade prestaram atenção decente. Posso reclamar da possibilidade de alterar classes constantes e da capacidade de confundir uma classe de referência com uma estrutura - um valor, no entanto aqui como em C #.

O gerenciamento de memória está no ARC original e o RemObjects para plataformas diferentes da Apple possui GC.
Pesado para incorporado, sem habilidades em tempo real.

O resto que eu gostaria de ver é quase tudo. Não há contratos (existem extensões não-padrão em RemObjects), mas algum tipo de emulação é possível através de observadores ou propriedade @propertyWrapper que apareceram no 5.2 ( ainda não implementado na RemObjects )

Tuples Note-se, os nomes dos parâmetros funções, array.insert(x, at: i)desembrulhar explícito para opcional e geralmente pensado trabalhar com ele.

Uma nuance essencial, eu chamaria de evolução da linguagem. Muitos exemplos do tutorial oficial (5.2) simplesmente não funcionam no mesmo Repl.it (5.0), sem mencionar o RemObjects, que não está claro quais versões correspondem exatamente .

A implementação no RemObjects difere da referência - Matriz é referenciada aqui e String é imutável, as interfaces também são diferentes daquelas descritas no tutorial, e as interfaces da biblioteca não apenas têm suas próprias, mas variam um pouco entre as plataformas. O que traz alguma variedade ao chato processo de codificação =) O

resumo final atualiza a tabela de confiabilidade

Na verdade, lembro que isso é apenas superficial de acordo com os dados de referência, e todos os profissionais que escrevem nesses idiomas são convidados a edições físicas.

Qualidade de compilação


Vamos tentar fazer um programa Swift semelhante à distância de Levenshtein no artigo 0xd34df00d e compare com os programas de lá.

Rápido
/*    
	  Windows.Native, Elements.Island
*/

class Program {
	 public static func LevDist(_ s1: [UInt8], _ s2: [UInt8]) -> Int32! {
		 let m = s1.count
		 let n = s2.count
		 //  Edge cases.
		 if m == 0 {
			 return n
		 } else {
			 if n == 0 {
				 return m
			 }
		 }

		 var range = Range(0 ... (n + 1))
		 var v0: Swift.Array<Int64> = range.GetSequence()  //17ms

//         var v1 = v0;    // in Swift must copy, but RO make a ref
		 var v1 = Swift.Array<Int64>(v0);

		 var i = 0
		 while i < m {
			 v1[0] = i + 1
			 var j = 0
			 while j < n {
				 let substCost = (s1[i] == s2[j] ? v0[j] : v0[j] + 1)
				 let delCost = v0[j + 1] + 1
				 let insCost = v1[j] + 1
				 v1[j + 1] = substCost < delCost ? substCost : delCost
				 if insCost < v1[j + 1] {
					 v1[j + 1] = insCost
				 }
				 j += 1
			 }

			 let temp = v0; v0 = v1; v1 = temp // copy refs
			 i += 1
		 }
		 return v0[n]
	 }
 }


var b1 = [UInt8](repeating: 61 as! UInt8, count: 20000)
var b2: [UInt8] = b1
var b3 = Swift.Array<UInt8>(repeating: UInt8(63), count: 20000)

print("Start Distance");

var execTimer: StopWatch! = StopWatch()
execTimer.Start()

print(Program.LevDist(b1, b2))
print(Program.LevDist(b1, b3))

execTimer.Stop()

var execTime: Float64 = execTimer.ElapsedMilliseconds / 1000.0 / 10

print("\(execTime) s")
return 0


O resto com mudanças mínimas, embora, claro, as falhas mais graves, eu aparei no github . Para aqueles que não têm medo e são muito preguiçosos para baixar o ambiente e compilar, também existem binários, se desejar, você pode executar opções JVM e NET relativamente seguras ou na sandbox.

As alterações estão relacionadas às edições do RO, à remoção do Encoding.UTF8.GetBytes da parte de medição, e na versão Pascal a formação de linhas no formulário for i := 1 to 20000 do s1 := s1 + 'a';pode levar até 4 minutos (fora da parte de medição).

Tabela de resultados (normalizada por Java como universal)
LínguaPlataformaCompiladorTempo sNormaParâmetros
C #NET4.7NET4.7.306213.075445%-o +
C #NET Core 3.1Elements 10.011.327385%release,> dotnet cs.dll
C #Win x64Elements 10.06.312215%lançamento
JavaJvmJDK 1.8.0.2422.941100%-g: none
$ java LevDist
JavaJvmElements 10.02.85197%release
$java -jar java8.jar
OxygeneNET4.7Elements 10.022,079751%release, range checking off
OxygeneWin x64Elements 10.09,421320%release, range checking off
SwiftJVMElements 10.023,733807%release
$java -jar swiftjvm.jar
SwiftWin x64Elements 10.0131,4004468%release
Go (Beta)Win x64Elements 10.089,2433034%release
Seria interessante testar o WASM, mas eu perdi esse ponto.

As medições foram realizadas em uma máquina virtual com o Win7, que reduz a velocidade da tarefa aproximadamente três vezes em relação ao meu hardware real, a média foi tirada de 3 medições 5.

Até agora, há apenas uma conclusão: a vida no Swift também é possível fora do ecossistema da maçã. Mas até agora não é rápido. A hipótese de que existe um problema no Win7, porque o SDK do Win10 é usado para compilação nativa, não foi confirmada - no Server 2016 1607, os horários são praticamente os mesmos.

[1] Programação confiável no contexto de idiomas - noob review. Parte 1
[2] Programação confiável no contexto de idiomas. Parte 2 - Desafiantes

All Articles